diff options
292 files changed, 9693 insertions, 3623 deletions
diff --git a/Documentation/devicetree/bindings/net/can/xilinx_can.txt b/Documentation/devicetree/bindings/net/can/xilinx_can.txt new file mode 100644 index 000000000000..fe38847d8e26 --- /dev/null +++ b/Documentation/devicetree/bindings/net/can/xilinx_can.txt | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | Xilinx Axi CAN/Zynq CANPS controller Device Tree Bindings | ||
| 2 | --------------------------------------------------------- | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible : Should be "xlnx,zynq-can-1.0" for Zynq CAN | ||
| 6 | controllers and "xlnx,axi-can-1.00.a" for Axi CAN | ||
| 7 | controllers. | ||
| 8 | - reg : Physical base address and size of the Axi CAN/Zynq | ||
| 9 | CANPS registers map. | ||
| 10 | - interrupts : Property with a value describing the interrupt | ||
| 11 | number. | ||
| 12 | - interrupt-parent : Must be core interrupt controller | ||
| 13 | - clock-names : List of input clock names - "can_clk", "pclk" | ||
| 14 | (For CANPS), "can_clk" , "s_axi_aclk"(For AXI CAN) | ||
| 15 | (See clock bindings for details). | ||
| 16 | - clocks : Clock phandles (see clock bindings for details). | ||
| 17 | - tx-fifo-depth : Can Tx fifo depth. | ||
| 18 | - rx-fifo-depth : Can Rx fifo depth. | ||
| 19 | |||
| 20 | |||
| 21 | Example: | ||
| 22 | |||
| 23 | For Zynq CANPS Dts file: | ||
| 24 | zynq_can_0: can@e0008000 { | ||
| 25 | compatible = "xlnx,zynq-can-1.0"; | ||
| 26 | clocks = <&clkc 19>, <&clkc 36>; | ||
| 27 | clock-names = "can_clk", "pclk"; | ||
| 28 | reg = <0xe0008000 0x1000>; | ||
| 29 | interrupts = <0 28 4>; | ||
| 30 | interrupt-parent = <&intc>; | ||
| 31 | tx-fifo-depth = <0x40>; | ||
| 32 | rx-fifo-depth = <0x40>; | ||
| 33 | }; | ||
| 34 | For Axi CAN Dts file: | ||
| 35 | axi_can_0: axi-can@40000000 { | ||
| 36 | compatible = "xlnx,axi-can-1.00.a"; | ||
| 37 | clocks = <&clkc 0>, <&clkc 1>; | ||
| 38 | clock-names = "can_clk","s_axi_aclk" ; | ||
| 39 | reg = <0x40000000 0x10000>; | ||
| 40 | interrupt-parent = <&intc>; | ||
| 41 | interrupts = <0 59 1>; | ||
| 42 | tx-fifo-depth = <0x40>; | ||
| 43 | rx-fifo-depth = <0x40>; | ||
| 44 | }; | ||
diff --git a/Documentation/devicetree/bindings/net/nfc/pn544.txt b/Documentation/devicetree/bindings/net/nfc/pn544.txt new file mode 100644 index 000000000000..dab69f36167c --- /dev/null +++ b/Documentation/devicetree/bindings/net/nfc/pn544.txt | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | * NXP Semiconductors PN544 NFC Controller | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: Should be "nxp,pn544-i2c". | ||
| 5 | - clock-frequency: I²C work frequency. | ||
| 6 | - reg: address on the bus | ||
| 7 | - interrupt-parent: phandle for the interrupt gpio controller | ||
| 8 | - interrupts: GPIO interrupt to which the chip is connected | ||
| 9 | - enable-gpios: Output GPIO pin used for enabling/disabling the PN544 | ||
| 10 | - firmware-gpios: Output GPIO pin used to enter firmware download mode | ||
| 11 | |||
| 12 | Optional SoC Specific Properties: | ||
| 13 | - pinctrl-names: Contains only one value - "default". | ||
| 14 | - pintctrl-0: Specifies the pin control groups used for this controller. | ||
| 15 | |||
| 16 | Example (for ARM-based BeagleBone with PN544 on I2C2): | ||
| 17 | |||
| 18 | &i2c2 { | ||
| 19 | |||
| 20 | status = "okay"; | ||
| 21 | |||
| 22 | pn544: pn544@28 { | ||
| 23 | |||
| 24 | compatible = "nxp,pn544-i2c"; | ||
| 25 | |||
| 26 | reg = <0x28>; | ||
| 27 | clock-frequency = <400000>; | ||
| 28 | |||
| 29 | interrupt-parent = <&gpio1>; | ||
| 30 | interrupts = <17 GPIO_ACTIVE_HIGH>; | ||
| 31 | |||
| 32 | enable-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; | ||
| 33 | firmware-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; | ||
| 34 | }; | ||
| 35 | }; | ||
diff --git a/Documentation/devicetree/bindings/net/nfc/st21nfca.txt b/Documentation/devicetree/bindings/net/nfc/st21nfca.txt new file mode 100644 index 000000000000..4724fe669172 --- /dev/null +++ b/Documentation/devicetree/bindings/net/nfc/st21nfca.txt | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | * STMicroelectronics SAS. ST21NFCA NFC Controller | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: Should be "st,st21nfca-i2c". | ||
| 5 | - clock-frequency: I²C work frequency. | ||
| 6 | - reg: address on the bus | ||
| 7 | - interrupt-parent: phandle for the interrupt gpio controller | ||
| 8 | - interrupts: GPIO interrupt to which the chip is connected | ||
| 9 | - enable-gpios: Output GPIO pin used for enabling/disabling the ST21NFCA | ||
| 10 | |||
| 11 | Optional SoC Specific Properties: | ||
| 12 | - pinctrl-names: Contains only one value - "default". | ||
| 13 | - pintctrl-0: Specifies the pin control groups used for this controller. | ||
| 14 | |||
| 15 | Example (for ARM-based BeagleBoard xM with ST21NFCA on I2C2): | ||
| 16 | |||
| 17 | &i2c2 { | ||
| 18 | |||
| 19 | status = "okay"; | ||
| 20 | |||
| 21 | st21nfca: st21nfca@1 { | ||
| 22 | |||
| 23 | compatible = "st,st21nfca_i2c"; | ||
| 24 | |||
| 25 | reg = <0x01>; | ||
| 26 | clock-frequency = <400000>; | ||
| 27 | |||
| 28 | interrupt-parent = <&gpio5>; | ||
| 29 | interrupts = <2 IRQ_TYPE_LEVEL_LOW>; | ||
| 30 | |||
| 31 | enable-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>; | ||
| 32 | }; | ||
| 33 | }; | ||
diff --git a/Documentation/devicetree/bindings/net/nfc/trf7970a.txt b/Documentation/devicetree/bindings/net/nfc/trf7970a.txt index 8dd3ef7bc56b..1e436133685f 100644 --- a/Documentation/devicetree/bindings/net/nfc/trf7970a.txt +++ b/Documentation/devicetree/bindings/net/nfc/trf7970a.txt | |||
| @@ -12,6 +12,7 @@ Required properties: | |||
| 12 | Optional SoC Specific Properties: | 12 | Optional SoC Specific Properties: |
| 13 | - pinctrl-names: Contains only one value - "default". | 13 | - pinctrl-names: Contains only one value - "default". |
| 14 | - pintctrl-0: Specifies the pin control groups used for this controller. | 14 | - pintctrl-0: Specifies the pin control groups used for this controller. |
| 15 | - autosuspend-delay: Specify autosuspend delay in milliseconds. | ||
| 15 | 16 | ||
| 16 | Example (for ARM-based BeagleBone with TRF7970A on SPI1): | 17 | Example (for ARM-based BeagleBone with TRF7970A on SPI1): |
| 17 | 18 | ||
| @@ -29,6 +30,7 @@ Example (for ARM-based BeagleBone with TRF7970A on SPI1): | |||
| 29 | ti,enable-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>, | 30 | ti,enable-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>, |
| 30 | <&gpio2 5 GPIO_ACTIVE_LOW>; | 31 | <&gpio2 5 GPIO_ACTIVE_LOW>; |
| 31 | vin-supply = <&ldo3_reg>; | 32 | vin-supply = <&ldo3_reg>; |
| 33 | autosuspend-delay = <30000>; | ||
| 32 | status = "okay"; | 34 | status = "okay"; |
| 33 | }; | 35 | }; |
| 34 | }; | 36 | }; |
diff --git a/MAINTAINERS b/MAINTAINERS index 75106235a38d..dd33abf44766 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -1888,7 +1888,7 @@ F: drivers/net/ethernet/broadcom/bnx2.* | |||
| 1888 | F: drivers/net/ethernet/broadcom/bnx2_* | 1888 | F: drivers/net/ethernet/broadcom/bnx2_* |
| 1889 | 1889 | ||
| 1890 | BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER | 1890 | BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER |
| 1891 | M: Ariel Elior <ariele@broadcom.com> | 1891 | M: Ariel Elior <ariel.elior@qlogic.com> |
| 1892 | L: netdev@vger.kernel.org | 1892 | L: netdev@vger.kernel.org |
| 1893 | S: Supported | 1893 | S: Supported |
| 1894 | F: drivers/net/ethernet/broadcom/bnx2x/ | 1894 | F: drivers/net/ethernet/broadcom/bnx2x/ |
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c index e4dec9fcb084..9c6029ba526f 100644 --- a/arch/arm/mach-tegra/board-paz00.c +++ b/arch/arm/mach-tegra/board-paz00.c | |||
| @@ -23,9 +23,7 @@ | |||
| 23 | #include "board.h" | 23 | #include "board.h" |
| 24 | 24 | ||
| 25 | static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = { | 25 | static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = { |
| 26 | .name = "wifi_rfkill", | 26 | .name = "wifi_rfkill", |
| 27 | .reset_gpio = 25, /* PD1 */ | ||
| 28 | .shutdown_gpio = 85, /* PK5 */ | ||
| 29 | .type = RFKILL_TYPE_WLAN, | 27 | .type = RFKILL_TYPE_WLAN, |
| 30 | }; | 28 | }; |
| 31 | 29 | ||
diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index a8b5408dd349..da4cdb16844e 100644 --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c | |||
| @@ -168,6 +168,7 @@ static void nvram_read_alpha2(const char *prefix, const char *name, | |||
| 168 | static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom, | 168 | static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom, |
| 169 | const char *prefix, bool fallback) | 169 | const char *prefix, bool fallback) |
| 170 | { | 170 | { |
| 171 | nvram_read_u16(prefix, NULL, "devid", &sprom->dev_id, 0, fallback); | ||
| 171 | nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff, fallback); | 172 | nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff, fallback); |
| 172 | nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff, fallback); | 173 | nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff, fallback); |
| 173 | nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff, fallback); | 174 | nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff, fallback); |
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 0a87e5691341..cc8d4a6099cd 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
| @@ -448,7 +448,6 @@ mmc_spi_command_send(struct mmc_spi_host *host, | |||
| 448 | { | 448 | { |
| 449 | struct scratch *data = host->data; | 449 | struct scratch *data = host->data; |
| 450 | u8 *cp = data->status; | 450 | u8 *cp = data->status; |
| 451 | u32 arg = cmd->arg; | ||
| 452 | int status; | 451 | int status; |
| 453 | struct spi_transfer *t; | 452 | struct spi_transfer *t; |
| 454 | 453 | ||
| @@ -465,14 +464,12 @@ mmc_spi_command_send(struct mmc_spi_host *host, | |||
| 465 | * We init the whole buffer to all-ones, which is what we need | 464 | * We init the whole buffer to all-ones, which is what we need |
| 466 | * to write while we're reading (later) response data. | 465 | * to write while we're reading (later) response data. |
| 467 | */ | 466 | */ |
| 468 | memset(cp++, 0xff, sizeof(data->status)); | 467 | memset(cp, 0xff, sizeof(data->status)); |
| 469 | 468 | ||
| 470 | *cp++ = 0x40 | cmd->opcode; | 469 | cp[1] = 0x40 | cmd->opcode; |
| 471 | *cp++ = (u8)(arg >> 24); | 470 | put_unaligned_be32(cmd->arg, cp+2); |
| 472 | *cp++ = (u8)(arg >> 16); | 471 | cp[6] = crc7_be(0, cp+1, 5) | 0x01; |
| 473 | *cp++ = (u8)(arg >> 8); | 472 | cp += 7; |
| 474 | *cp++ = (u8)arg; | ||
| 475 | *cp++ = (crc7(0, &data->status[1], 5) << 1) | 0x01; | ||
| 476 | 473 | ||
| 477 | /* Then, read up to 13 bytes (while writing all-ones): | 474 | /* Then, read up to 13 bytes (while writing all-ones): |
| 478 | * - N(CR) (== 1..8) bytes of all-ones | 475 | * - N(CR) (== 1..8) bytes of all-ones |
| @@ -711,10 +708,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, | |||
| 711 | * so we have to cope with this situation and check the response | 708 | * so we have to cope with this situation and check the response |
| 712 | * bit-by-bit. Arggh!!! | 709 | * bit-by-bit. Arggh!!! |
| 713 | */ | 710 | */ |
| 714 | pattern = scratch->status[0] << 24; | 711 | pattern = get_unaligned_be32(scratch->status); |
| 715 | pattern |= scratch->status[1] << 16; | ||
| 716 | pattern |= scratch->status[2] << 8; | ||
| 717 | pattern |= scratch->status[3]; | ||
| 718 | 712 | ||
| 719 | /* First 3 bit of pattern are undefined */ | 713 | /* First 3 bit of pattern are undefined */ |
| 720 | pattern |= 0xE0000000; | 714 | pattern |= 0xE0000000; |
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 714b18790caf..41688229c570 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig | |||
| @@ -129,6 +129,14 @@ config CAN_RCAR | |||
| 129 | To compile this driver as a module, choose M here: the module will | 129 | To compile this driver as a module, choose M here: the module will |
| 130 | be called rcar_can. | 130 | be called rcar_can. |
| 131 | 131 | ||
| 132 | config CAN_XILINXCAN | ||
| 133 | tristate "Xilinx CAN" | ||
| 134 | depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST | ||
| 135 | depends on COMMON_CLK && HAS_IOMEM | ||
| 136 | ---help--- | ||
| 137 | Xilinx CAN driver. This driver supports both soft AXI CAN IP and | ||
| 138 | Zynq CANPS IP. | ||
| 139 | |||
| 132 | source "drivers/net/can/mscan/Kconfig" | 140 | source "drivers/net/can/mscan/Kconfig" |
| 133 | 141 | ||
| 134 | source "drivers/net/can/sja1000/Kconfig" | 142 | source "drivers/net/can/sja1000/Kconfig" |
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index 90f538c73f8c..1697f22353a9 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile | |||
| @@ -26,5 +26,6 @@ obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o | |||
| 26 | obj-$(CONFIG_PCH_CAN) += pch_can.o | 26 | obj-$(CONFIG_PCH_CAN) += pch_can.o |
| 27 | obj-$(CONFIG_CAN_GRCAN) += grcan.o | 27 | obj-$(CONFIG_CAN_GRCAN) += grcan.o |
| 28 | obj-$(CONFIG_CAN_RCAR) += rcar_can.o | 28 | obj-$(CONFIG_CAN_RCAR) += rcar_can.o |
| 29 | obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o | ||
| 29 | 30 | ||
| 30 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG | 31 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG |
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c new file mode 100644 index 000000000000..5e8b5609c067 --- /dev/null +++ b/drivers/net/can/xilinx_can.c | |||
| @@ -0,0 +1,1208 @@ | |||
| 1 | /* Xilinx CAN device driver | ||
| 2 | * | ||
| 3 | * Copyright (C) 2012 - 2014 Xilinx, Inc. | ||
| 4 | * Copyright (C) 2009 PetaLogix. All rights reserved. | ||
| 5 | * | ||
| 6 | * Description: | ||
| 7 | * This driver is developed for Axi CAN IP and for Zynq CANPS Controller. | ||
| 8 | * This program is free software: you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation, either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/clk.h> | ||
| 20 | #include <linux/errno.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/io.h> | ||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/netdevice.h> | ||
| 27 | #include <linux/of.h> | ||
| 28 | #include <linux/platform_device.h> | ||
| 29 | #include <linux/skbuff.h> | ||
| 30 | #include <linux/string.h> | ||
| 31 | #include <linux/types.h> | ||
| 32 | #include <linux/can/dev.h> | ||
| 33 | #include <linux/can/error.h> | ||
| 34 | #include <linux/can/led.h> | ||
| 35 | |||
| 36 | #define DRIVER_NAME "xilinx_can" | ||
| 37 | |||
| 38 | /* CAN registers set */ | ||
| 39 | enum xcan_reg { | ||
| 40 | XCAN_SRR_OFFSET = 0x00, /* Software reset */ | ||
| 41 | XCAN_MSR_OFFSET = 0x04, /* Mode select */ | ||
| 42 | XCAN_BRPR_OFFSET = 0x08, /* Baud rate prescaler */ | ||
| 43 | XCAN_BTR_OFFSET = 0x0C, /* Bit timing */ | ||
| 44 | XCAN_ECR_OFFSET = 0x10, /* Error counter */ | ||
| 45 | XCAN_ESR_OFFSET = 0x14, /* Error status */ | ||
| 46 | XCAN_SR_OFFSET = 0x18, /* Status */ | ||
| 47 | XCAN_ISR_OFFSET = 0x1C, /* Interrupt status */ | ||
| 48 | XCAN_IER_OFFSET = 0x20, /* Interrupt enable */ | ||
| 49 | XCAN_ICR_OFFSET = 0x24, /* Interrupt clear */ | ||
| 50 | XCAN_TXFIFO_ID_OFFSET = 0x30,/* TX FIFO ID */ | ||
| 51 | XCAN_TXFIFO_DLC_OFFSET = 0x34, /* TX FIFO DLC */ | ||
| 52 | XCAN_TXFIFO_DW1_OFFSET = 0x38, /* TX FIFO Data Word 1 */ | ||
| 53 | XCAN_TXFIFO_DW2_OFFSET = 0x3C, /* TX FIFO Data Word 2 */ | ||
| 54 | XCAN_RXFIFO_ID_OFFSET = 0x50, /* RX FIFO ID */ | ||
| 55 | XCAN_RXFIFO_DLC_OFFSET = 0x54, /* RX FIFO DLC */ | ||
| 56 | XCAN_RXFIFO_DW1_OFFSET = 0x58, /* RX FIFO Data Word 1 */ | ||
| 57 | XCAN_RXFIFO_DW2_OFFSET = 0x5C, /* RX FIFO Data Word 2 */ | ||
| 58 | }; | ||
| 59 | |||
| 60 | /* CAN register bit masks - XCAN_<REG>_<BIT>_MASK */ | ||
| 61 | #define XCAN_SRR_CEN_MASK 0x00000002 /* CAN enable */ | ||
| 62 | #define XCAN_SRR_RESET_MASK 0x00000001 /* Soft Reset the CAN core */ | ||
| 63 | #define XCAN_MSR_LBACK_MASK 0x00000002 /* Loop back mode select */ | ||
| 64 | #define XCAN_MSR_SLEEP_MASK 0x00000001 /* Sleep mode select */ | ||
| 65 | #define XCAN_BRPR_BRP_MASK 0x000000FF /* Baud rate prescaler */ | ||
| 66 | #define XCAN_BTR_SJW_MASK 0x00000180 /* Synchronous jump width */ | ||
| 67 | #define XCAN_BTR_TS2_MASK 0x00000070 /* Time segment 2 */ | ||
| 68 | #define XCAN_BTR_TS1_MASK 0x0000000F /* Time segment 1 */ | ||
| 69 | #define XCAN_ECR_REC_MASK 0x0000FF00 /* Receive error counter */ | ||
| 70 | #define XCAN_ECR_TEC_MASK 0x000000FF /* Transmit error counter */ | ||
| 71 | #define XCAN_ESR_ACKER_MASK 0x00000010 /* ACK error */ | ||
| 72 | #define XCAN_ESR_BERR_MASK 0x00000008 /* Bit error */ | ||
| 73 | #define XCAN_ESR_STER_MASK 0x00000004 /* Stuff error */ | ||
| 74 | #define XCAN_ESR_FMER_MASK 0x00000002 /* Form error */ | ||
| 75 | #define XCAN_ESR_CRCER_MASK 0x00000001 /* CRC error */ | ||
| 76 | #define XCAN_SR_TXFLL_MASK 0x00000400 /* TX FIFO is full */ | ||
| 77 | #define XCAN_SR_ESTAT_MASK 0x00000180 /* Error status */ | ||
| 78 | #define XCAN_SR_ERRWRN_MASK 0x00000040 /* Error warning */ | ||
| 79 | #define XCAN_SR_NORMAL_MASK 0x00000008 /* Normal mode */ | ||
| 80 | #define XCAN_SR_LBACK_MASK 0x00000002 /* Loop back mode */ | ||
| 81 | #define XCAN_SR_CONFIG_MASK 0x00000001 /* Configuration mode */ | ||
| 82 | #define XCAN_IXR_TXFEMP_MASK 0x00004000 /* TX FIFO Empty */ | ||
| 83 | #define XCAN_IXR_WKUP_MASK 0x00000800 /* Wake up interrupt */ | ||
| 84 | #define XCAN_IXR_SLP_MASK 0x00000400 /* Sleep interrupt */ | ||
| 85 | #define XCAN_IXR_BSOFF_MASK 0x00000200 /* Bus off interrupt */ | ||
| 86 | #define XCAN_IXR_ERROR_MASK 0x00000100 /* Error interrupt */ | ||
| 87 | #define XCAN_IXR_RXNEMP_MASK 0x00000080 /* RX FIFO NotEmpty intr */ | ||
| 88 | #define XCAN_IXR_RXOFLW_MASK 0x00000040 /* RX FIFO Overflow intr */ | ||
| 89 | #define XCAN_IXR_RXOK_MASK 0x00000010 /* Message received intr */ | ||
| 90 | #define XCAN_IXR_TXFLL_MASK 0x00000004 /* Tx FIFO Full intr */ | ||
| 91 | #define XCAN_IXR_TXOK_MASK 0x00000002 /* TX successful intr */ | ||
| 92 | #define XCAN_IXR_ARBLST_MASK 0x00000001 /* Arbitration lost intr */ | ||
| 93 | #define XCAN_IDR_ID1_MASK 0xFFE00000 /* Standard msg identifier */ | ||
| 94 | #define XCAN_IDR_SRR_MASK 0x00100000 /* Substitute remote TXreq */ | ||
| 95 | #define XCAN_IDR_IDE_MASK 0x00080000 /* Identifier extension */ | ||
| 96 | #define XCAN_IDR_ID2_MASK 0x0007FFFE /* Extended message ident */ | ||
| 97 | #define XCAN_IDR_RTR_MASK 0x00000001 /* Remote TX request */ | ||
| 98 | #define XCAN_DLCR_DLC_MASK 0xF0000000 /* Data length code */ | ||
| 99 | |||
| 100 | #define XCAN_INTR_ALL (XCAN_IXR_TXOK_MASK | XCAN_IXR_BSOFF_MASK |\ | ||
| 101 | XCAN_IXR_WKUP_MASK | XCAN_IXR_SLP_MASK | \ | ||
| 102 | XCAN_IXR_RXNEMP_MASK | XCAN_IXR_ERROR_MASK | \ | ||
| 103 | XCAN_IXR_ARBLST_MASK | XCAN_IXR_RXOK_MASK) | ||
| 104 | |||
| 105 | /* CAN register bit shift - XCAN_<REG>_<BIT>_SHIFT */ | ||
| 106 | #define XCAN_BTR_SJW_SHIFT 7 /* Synchronous jump width */ | ||
| 107 | #define XCAN_BTR_TS2_SHIFT 4 /* Time segment 2 */ | ||
| 108 | #define XCAN_IDR_ID1_SHIFT 21 /* Standard Messg Identifier */ | ||
| 109 | #define XCAN_IDR_ID2_SHIFT 1 /* Extended Message Identifier */ | ||
| 110 | #define XCAN_DLCR_DLC_SHIFT 28 /* Data length code */ | ||
| 111 | #define XCAN_ESR_REC_SHIFT 8 /* Rx Error Count */ | ||
| 112 | |||
| 113 | /* CAN frame length constants */ | ||
| 114 | #define XCAN_FRAME_MAX_DATA_LEN 8 | ||
| 115 | #define XCAN_TIMEOUT (1 * HZ) | ||
| 116 | |||
| 117 | /** | ||
| 118 | * struct xcan_priv - This definition define CAN driver instance | ||
| 119 | * @can: CAN private data structure. | ||
| 120 | * @tx_head: Tx CAN packets ready to send on the queue | ||
| 121 | * @tx_tail: Tx CAN packets successfully sended on the queue | ||
| 122 | * @tx_max: Maximum number packets the driver can send | ||
| 123 | * @napi: NAPI structure | ||
| 124 | * @read_reg: For reading data from CAN registers | ||
| 125 | * @write_reg: For writing data to CAN registers | ||
| 126 | * @dev: Network device data structure | ||
| 127 | * @reg_base: Ioremapped address to registers | ||
| 128 | * @irq_flags: For request_irq() | ||
| 129 | * @bus_clk: Pointer to struct clk | ||
| 130 | * @can_clk: Pointer to struct clk | ||
| 131 | */ | ||
| 132 | struct xcan_priv { | ||
| 133 | struct can_priv can; | ||
| 134 | unsigned int tx_head; | ||
| 135 | unsigned int tx_tail; | ||
| 136 | unsigned int tx_max; | ||
| 137 | struct napi_struct napi; | ||
| 138 | u32 (*read_reg)(const struct xcan_priv *priv, enum xcan_reg reg); | ||
| 139 | void (*write_reg)(const struct xcan_priv *priv, enum xcan_reg reg, | ||
| 140 | u32 val); | ||
| 141 | struct net_device *dev; | ||
| 142 | void __iomem *reg_base; | ||
| 143 | unsigned long irq_flags; | ||
| 144 | struct clk *bus_clk; | ||
| 145 | struct clk *can_clk; | ||
| 146 | }; | ||
| 147 | |||
| 148 | /* CAN Bittiming constants as per Xilinx CAN specs */ | ||
| 149 | static const struct can_bittiming_const xcan_bittiming_const = { | ||
| 150 | .name = DRIVER_NAME, | ||
| 151 | .tseg1_min = 1, | ||
| 152 | .tseg1_max = 16, | ||
| 153 | .tseg2_min = 1, | ||
| 154 | .tseg2_max = 8, | ||
| 155 | .sjw_max = 4, | ||
| 156 | .brp_min = 1, | ||
| 157 | .brp_max = 256, | ||
| 158 | .brp_inc = 1, | ||
| 159 | }; | ||
| 160 | |||
| 161 | /** | ||
| 162 | * xcan_write_reg_le - Write a value to the device register little endian | ||
| 163 | * @priv: Driver private data structure | ||
| 164 | * @reg: Register offset | ||
| 165 | * @val: Value to write at the Register offset | ||
| 166 | * | ||
| 167 | * Write data to the paricular CAN register | ||
| 168 | */ | ||
| 169 | static void xcan_write_reg_le(const struct xcan_priv *priv, enum xcan_reg reg, | ||
| 170 | u32 val) | ||
| 171 | { | ||
| 172 | iowrite32(val, priv->reg_base + reg); | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * xcan_read_reg_le - Read a value from the device register little endian | ||
| 177 | * @priv: Driver private data structure | ||
| 178 | * @reg: Register offset | ||
| 179 | * | ||
| 180 | * Read data from the particular CAN register | ||
| 181 | * Return: value read from the CAN register | ||
| 182 | */ | ||
| 183 | static u32 xcan_read_reg_le(const struct xcan_priv *priv, enum xcan_reg reg) | ||
| 184 | { | ||
| 185 | return ioread32(priv->reg_base + reg); | ||
| 186 | } | ||
| 187 | |||
| 188 | /** | ||
| 189 | * xcan_write_reg_be - Write a value to the device register big endian | ||
| 190 | * @priv: Driver private data structure | ||
| 191 | * @reg: Register offset | ||
| 192 | * @val: Value to write at the Register offset | ||
| 193 | * | ||
| 194 | * Write data to the paricular CAN register | ||
| 195 | */ | ||
| 196 | static void xcan_write_reg_be(const struct xcan_priv *priv, enum xcan_reg reg, | ||
| 197 | u32 val) | ||
| 198 | { | ||
| 199 | iowrite32be(val, priv->reg_base + reg); | ||
| 200 | } | ||
| 201 | |||
| 202 | /** | ||
| 203 | * xcan_read_reg_be - Read a value from the device register big endian | ||
| 204 | * @priv: Driver private data structure | ||
| 205 | * @reg: Register offset | ||
| 206 | * | ||
| 207 | * Read data from the particular CAN register | ||
| 208 | * Return: value read from the CAN register | ||
| 209 | */ | ||
| 210 | static u32 xcan_read_reg_be(const struct xcan_priv *priv, enum xcan_reg reg) | ||
| 211 | { | ||
| 212 | return ioread32be(priv->reg_base + reg); | ||
| 213 | } | ||
| 214 | |||
| 215 | /** | ||
| 216 | * set_reset_mode - Resets the CAN device mode | ||
| 217 | * @ndev: Pointer to net_device structure | ||
| 218 | * | ||
| 219 | * This is the driver reset mode routine.The driver | ||
| 220 | * enters into configuration mode. | ||
| 221 | * | ||
| 222 | * Return: 0 on success and failure value on error | ||
| 223 | */ | ||
| 224 | static int set_reset_mode(struct net_device *ndev) | ||
| 225 | { | ||
| 226 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 227 | unsigned long timeout; | ||
| 228 | |||
| 229 | priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); | ||
| 230 | |||
| 231 | timeout = jiffies + XCAN_TIMEOUT; | ||
| 232 | while (!(priv->read_reg(priv, XCAN_SR_OFFSET) & XCAN_SR_CONFIG_MASK)) { | ||
| 233 | if (time_after(jiffies, timeout)) { | ||
| 234 | netdev_warn(ndev, "timed out for config mode\n"); | ||
| 235 | return -ETIMEDOUT; | ||
| 236 | } | ||
| 237 | usleep_range(500, 10000); | ||
| 238 | } | ||
| 239 | |||
| 240 | return 0; | ||
| 241 | } | ||
| 242 | |||
| 243 | /** | ||
| 244 | * xcan_set_bittiming - CAN set bit timing routine | ||
| 245 | * @ndev: Pointer to net_device structure | ||
| 246 | * | ||
| 247 | * This is the driver set bittiming routine. | ||
| 248 | * Return: 0 on success and failure value on error | ||
| 249 | */ | ||
| 250 | static int xcan_set_bittiming(struct net_device *ndev) | ||
| 251 | { | ||
| 252 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 253 | struct can_bittiming *bt = &priv->can.bittiming; | ||
| 254 | u32 btr0, btr1; | ||
| 255 | u32 is_config_mode; | ||
| 256 | |||
| 257 | /* Check whether Xilinx CAN is in configuration mode. | ||
| 258 | * It cannot set bit timing if Xilinx CAN is not in configuration mode. | ||
| 259 | */ | ||
| 260 | is_config_mode = priv->read_reg(priv, XCAN_SR_OFFSET) & | ||
| 261 | XCAN_SR_CONFIG_MASK; | ||
| 262 | if (!is_config_mode) { | ||
| 263 | netdev_alert(ndev, | ||
| 264 | "BUG! Cannot set bittiming - CAN is not in config mode\n"); | ||
| 265 | return -EPERM; | ||
| 266 | } | ||
| 267 | |||
| 268 | /* Setting Baud Rate prescalar value in BRPR Register */ | ||
| 269 | btr0 = (bt->brp - 1); | ||
| 270 | |||
| 271 | /* Setting Time Segment 1 in BTR Register */ | ||
| 272 | btr1 = (bt->prop_seg + bt->phase_seg1 - 1); | ||
| 273 | |||
| 274 | /* Setting Time Segment 2 in BTR Register */ | ||
| 275 | btr1 |= (bt->phase_seg2 - 1) << XCAN_BTR_TS2_SHIFT; | ||
| 276 | |||
| 277 | /* Setting Synchronous jump width in BTR Register */ | ||
| 278 | btr1 |= (bt->sjw - 1) << XCAN_BTR_SJW_SHIFT; | ||
| 279 | |||
| 280 | priv->write_reg(priv, XCAN_BRPR_OFFSET, btr0); | ||
| 281 | priv->write_reg(priv, XCAN_BTR_OFFSET, btr1); | ||
| 282 | |||
| 283 | netdev_dbg(ndev, "BRPR=0x%08x, BTR=0x%08x\n", | ||
| 284 | priv->read_reg(priv, XCAN_BRPR_OFFSET), | ||
| 285 | priv->read_reg(priv, XCAN_BTR_OFFSET)); | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | /** | ||
| 291 | * xcan_chip_start - This the drivers start routine | ||
| 292 | * @ndev: Pointer to net_device structure | ||
| 293 | * | ||
| 294 | * This is the drivers start routine. | ||
| 295 | * Based on the State of the CAN device it puts | ||
| 296 | * the CAN device into a proper mode. | ||
| 297 | * | ||
| 298 | * Return: 0 on success and failure value on error | ||
| 299 | */ | ||
| 300 | static int xcan_chip_start(struct net_device *ndev) | ||
| 301 | { | ||
| 302 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 303 | u32 err, reg_msr, reg_sr_mask; | ||
| 304 | unsigned long timeout; | ||
| 305 | |||
| 306 | /* Check if it is in reset mode */ | ||
| 307 | err = set_reset_mode(ndev); | ||
| 308 | if (err < 0) | ||
| 309 | return err; | ||
| 310 | |||
| 311 | err = xcan_set_bittiming(ndev); | ||
| 312 | if (err < 0) | ||
| 313 | return err; | ||
| 314 | |||
| 315 | /* Enable interrupts */ | ||
| 316 | priv->write_reg(priv, XCAN_IER_OFFSET, XCAN_INTR_ALL); | ||
| 317 | |||
| 318 | /* Check whether it is loopback mode or normal mode */ | ||
| 319 | if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { | ||
| 320 | reg_msr = XCAN_MSR_LBACK_MASK; | ||
| 321 | reg_sr_mask = XCAN_SR_LBACK_MASK; | ||
| 322 | } else { | ||
| 323 | reg_msr = 0x0; | ||
| 324 | reg_sr_mask = XCAN_SR_NORMAL_MASK; | ||
| 325 | } | ||
| 326 | |||
| 327 | priv->write_reg(priv, XCAN_MSR_OFFSET, reg_msr); | ||
| 328 | priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK); | ||
| 329 | |||
| 330 | timeout = jiffies + XCAN_TIMEOUT; | ||
| 331 | while (!(priv->read_reg(priv, XCAN_SR_OFFSET) & reg_sr_mask)) { | ||
| 332 | if (time_after(jiffies, timeout)) { | ||
| 333 | netdev_warn(ndev, | ||
| 334 | "timed out for correct mode\n"); | ||
| 335 | return -ETIMEDOUT; | ||
| 336 | } | ||
| 337 | } | ||
| 338 | netdev_dbg(ndev, "status:#x%08x\n", | ||
| 339 | priv->read_reg(priv, XCAN_SR_OFFSET)); | ||
| 340 | |||
| 341 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
| 342 | return 0; | ||
| 343 | } | ||
| 344 | |||
| 345 | /** | ||
| 346 | * xcan_do_set_mode - This sets the mode of the driver | ||
| 347 | * @ndev: Pointer to net_device structure | ||
| 348 | * @mode: Tells the mode of the driver | ||
| 349 | * | ||
| 350 | * This check the drivers state and calls the | ||
| 351 | * the corresponding modes to set. | ||
| 352 | * | ||
| 353 | * Return: 0 on success and failure value on error | ||
| 354 | */ | ||
| 355 | static int xcan_do_set_mode(struct net_device *ndev, enum can_mode mode) | ||
| 356 | { | ||
| 357 | int ret; | ||
| 358 | |||
| 359 | switch (mode) { | ||
| 360 | case CAN_MODE_START: | ||
| 361 | ret = xcan_chip_start(ndev); | ||
| 362 | if (ret < 0) { | ||
| 363 | netdev_err(ndev, "xcan_chip_start failed!\n"); | ||
| 364 | return ret; | ||
| 365 | } | ||
| 366 | netif_wake_queue(ndev); | ||
| 367 | break; | ||
| 368 | default: | ||
| 369 | ret = -EOPNOTSUPP; | ||
| 370 | break; | ||
| 371 | } | ||
| 372 | |||
| 373 | return ret; | ||
| 374 | } | ||
| 375 | |||
| 376 | /** | ||
| 377 | * xcan_start_xmit - Starts the transmission | ||
| 378 | * @skb: sk_buff pointer that contains data to be Txed | ||
| 379 | * @ndev: Pointer to net_device structure | ||
| 380 | * | ||
| 381 | * This function is invoked from upper layers to initiate transmission. This | ||
| 382 | * function uses the next available free txbuff and populates their fields to | ||
| 383 | * start the transmission. | ||
| 384 | * | ||
| 385 | * Return: 0 on success and failure value on error | ||
| 386 | */ | ||
| 387 | static int xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev) | ||
| 388 | { | ||
| 389 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 390 | struct net_device_stats *stats = &ndev->stats; | ||
| 391 | struct can_frame *cf = (struct can_frame *)skb->data; | ||
| 392 | u32 id, dlc, data[2] = {0, 0}; | ||
| 393 | |||
| 394 | if (can_dropped_invalid_skb(ndev, skb)) | ||
| 395 | return NETDEV_TX_OK; | ||
| 396 | |||
| 397 | /* Check if the TX buffer is full */ | ||
| 398 | if (unlikely(priv->read_reg(priv, XCAN_SR_OFFSET) & | ||
| 399 | XCAN_SR_TXFLL_MASK)) { | ||
| 400 | netif_stop_queue(ndev); | ||
| 401 | netdev_err(ndev, "BUG!, TX FIFO full when queue awake!\n"); | ||
| 402 | return NETDEV_TX_BUSY; | ||
| 403 | } | ||
| 404 | |||
| 405 | /* Watch carefully on the bit sequence */ | ||
| 406 | if (cf->can_id & CAN_EFF_FLAG) { | ||
| 407 | /* Extended CAN ID format */ | ||
| 408 | id = ((cf->can_id & CAN_EFF_MASK) << XCAN_IDR_ID2_SHIFT) & | ||
| 409 | XCAN_IDR_ID2_MASK; | ||
| 410 | id |= (((cf->can_id & CAN_EFF_MASK) >> | ||
| 411 | (CAN_EFF_ID_BITS-CAN_SFF_ID_BITS)) << | ||
| 412 | XCAN_IDR_ID1_SHIFT) & XCAN_IDR_ID1_MASK; | ||
| 413 | |||
| 414 | /* The substibute remote TX request bit should be "1" | ||
| 415 | * for extended frames as in the Xilinx CAN datasheet | ||
| 416 | */ | ||
| 417 | id |= XCAN_IDR_IDE_MASK | XCAN_IDR_SRR_MASK; | ||
| 418 | |||
| 419 | if (cf->can_id & CAN_RTR_FLAG) | ||
| 420 | /* Extended frames remote TX request */ | ||
| 421 | id |= XCAN_IDR_RTR_MASK; | ||
| 422 | } else { | ||
| 423 | /* Standard CAN ID format */ | ||
| 424 | id = ((cf->can_id & CAN_SFF_MASK) << XCAN_IDR_ID1_SHIFT) & | ||
| 425 | XCAN_IDR_ID1_MASK; | ||
| 426 | |||
| 427 | if (cf->can_id & CAN_RTR_FLAG) | ||
| 428 | /* Standard frames remote TX request */ | ||
| 429 | id |= XCAN_IDR_SRR_MASK; | ||
| 430 | } | ||
| 431 | |||
| 432 | dlc = cf->can_dlc << XCAN_DLCR_DLC_SHIFT; | ||
| 433 | |||
| 434 | if (cf->can_dlc > 0) | ||
| 435 | data[0] = be32_to_cpup((__be32 *)(cf->data + 0)); | ||
| 436 | if (cf->can_dlc > 4) | ||
| 437 | data[1] = be32_to_cpup((__be32 *)(cf->data + 4)); | ||
| 438 | |||
| 439 | can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max); | ||
| 440 | priv->tx_head++; | ||
| 441 | |||
| 442 | /* Write the Frame to Xilinx CAN TX FIFO */ | ||
| 443 | priv->write_reg(priv, XCAN_TXFIFO_ID_OFFSET, id); | ||
| 444 | /* If the CAN frame is RTR frame this write triggers tranmission */ | ||
| 445 | priv->write_reg(priv, XCAN_TXFIFO_DLC_OFFSET, dlc); | ||
| 446 | if (!(cf->can_id & CAN_RTR_FLAG)) { | ||
| 447 | priv->write_reg(priv, XCAN_TXFIFO_DW1_OFFSET, data[0]); | ||
| 448 | /* If the CAN frame is Standard/Extended frame this | ||
| 449 | * write triggers tranmission | ||
| 450 | */ | ||
| 451 | priv->write_reg(priv, XCAN_TXFIFO_DW2_OFFSET, data[1]); | ||
| 452 | stats->tx_bytes += cf->can_dlc; | ||
| 453 | } | ||
| 454 | |||
| 455 | /* Check if the TX buffer is full */ | ||
| 456 | if ((priv->tx_head - priv->tx_tail) == priv->tx_max) | ||
| 457 | netif_stop_queue(ndev); | ||
| 458 | |||
| 459 | return NETDEV_TX_OK; | ||
| 460 | } | ||
| 461 | |||
| 462 | /** | ||
| 463 | * xcan_rx - Is called from CAN isr to complete the received | ||
| 464 | * frame processing | ||
| 465 | * @ndev: Pointer to net_device structure | ||
| 466 | * | ||
| 467 | * This function is invoked from the CAN isr(poll) to process the Rx frames. It | ||
| 468 | * does minimal processing and invokes "netif_receive_skb" to complete further | ||
| 469 | * processing. | ||
| 470 | * Return: 1 on success and 0 on failure. | ||
| 471 | */ | ||
| 472 | static int xcan_rx(struct net_device *ndev) | ||
| 473 | { | ||
| 474 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 475 | struct net_device_stats *stats = &ndev->stats; | ||
| 476 | struct can_frame *cf; | ||
| 477 | struct sk_buff *skb; | ||
| 478 | u32 id_xcan, dlc, data[2] = {0, 0}; | ||
| 479 | |||
| 480 | skb = alloc_can_skb(ndev, &cf); | ||
| 481 | if (unlikely(!skb)) { | ||
| 482 | stats->rx_dropped++; | ||
| 483 | return 0; | ||
| 484 | } | ||
| 485 | |||
| 486 | /* Read a frame from Xilinx zynq CANPS */ | ||
| 487 | id_xcan = priv->read_reg(priv, XCAN_RXFIFO_ID_OFFSET); | ||
| 488 | dlc = priv->read_reg(priv, XCAN_RXFIFO_DLC_OFFSET) >> | ||
| 489 | XCAN_DLCR_DLC_SHIFT; | ||
| 490 | |||
| 491 | /* Change Xilinx CAN data length format to socketCAN data format */ | ||
| 492 | cf->can_dlc = get_can_dlc(dlc); | ||
| 493 | |||
| 494 | /* Change Xilinx CAN ID format to socketCAN ID format */ | ||
| 495 | if (id_xcan & XCAN_IDR_IDE_MASK) { | ||
| 496 | /* The received frame is an Extended format frame */ | ||
| 497 | cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> 3; | ||
| 498 | cf->can_id |= (id_xcan & XCAN_IDR_ID2_MASK) >> | ||
| 499 | XCAN_IDR_ID2_SHIFT; | ||
| 500 | cf->can_id |= CAN_EFF_FLAG; | ||
| 501 | if (id_xcan & XCAN_IDR_RTR_MASK) | ||
| 502 | cf->can_id |= CAN_RTR_FLAG; | ||
| 503 | } else { | ||
| 504 | /* The received frame is a standard format frame */ | ||
| 505 | cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> | ||
| 506 | XCAN_IDR_ID1_SHIFT; | ||
| 507 | if (id_xcan & XCAN_IDR_SRR_MASK) | ||
| 508 | cf->can_id |= CAN_RTR_FLAG; | ||
| 509 | } | ||
| 510 | |||
| 511 | if (!(id_xcan & XCAN_IDR_SRR_MASK)) { | ||
| 512 | data[0] = priv->read_reg(priv, XCAN_RXFIFO_DW1_OFFSET); | ||
| 513 | data[1] = priv->read_reg(priv, XCAN_RXFIFO_DW2_OFFSET); | ||
| 514 | |||
| 515 | /* Change Xilinx CAN data format to socketCAN data format */ | ||
| 516 | if (cf->can_dlc > 0) | ||
| 517 | *(__be32 *)(cf->data) = cpu_to_be32(data[0]); | ||
| 518 | if (cf->can_dlc > 4) | ||
| 519 | *(__be32 *)(cf->data + 4) = cpu_to_be32(data[1]); | ||
| 520 | } | ||
| 521 | |||
| 522 | stats->rx_bytes += cf->can_dlc; | ||
| 523 | stats->rx_packets++; | ||
| 524 | netif_receive_skb(skb); | ||
| 525 | |||
| 526 | return 1; | ||
| 527 | } | ||
| 528 | |||
| 529 | /** | ||
| 530 | * xcan_err_interrupt - error frame Isr | ||
| 531 | * @ndev: net_device pointer | ||
| 532 | * @isr: interrupt status register value | ||
| 533 | * | ||
| 534 | * This is the CAN error interrupt and it will | ||
| 535 | * check the the type of error and forward the error | ||
| 536 | * frame to upper layers. | ||
| 537 | */ | ||
| 538 | static void xcan_err_interrupt(struct net_device *ndev, u32 isr) | ||
| 539 | { | ||
| 540 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 541 | struct net_device_stats *stats = &ndev->stats; | ||
| 542 | struct can_frame *cf; | ||
| 543 | struct sk_buff *skb; | ||
| 544 | u32 err_status, status, txerr = 0, rxerr = 0; | ||
| 545 | |||
| 546 | skb = alloc_can_err_skb(ndev, &cf); | ||
| 547 | |||
| 548 | err_status = priv->read_reg(priv, XCAN_ESR_OFFSET); | ||
| 549 | priv->write_reg(priv, XCAN_ESR_OFFSET, err_status); | ||
| 550 | txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK; | ||
| 551 | rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) & | ||
| 552 | XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT); | ||
| 553 | status = priv->read_reg(priv, XCAN_SR_OFFSET); | ||
| 554 | |||
| 555 | if (isr & XCAN_IXR_BSOFF_MASK) { | ||
| 556 | priv->can.state = CAN_STATE_BUS_OFF; | ||
| 557 | priv->can.can_stats.bus_off++; | ||
| 558 | /* Leave device in Config Mode in bus-off state */ | ||
| 559 | priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); | ||
| 560 | can_bus_off(ndev); | ||
| 561 | if (skb) | ||
| 562 | cf->can_id |= CAN_ERR_BUSOFF; | ||
| 563 | } else if ((status & XCAN_SR_ESTAT_MASK) == XCAN_SR_ESTAT_MASK) { | ||
| 564 | priv->can.state = CAN_STATE_ERROR_PASSIVE; | ||
| 565 | priv->can.can_stats.error_passive++; | ||
| 566 | if (skb) { | ||
| 567 | cf->can_id |= CAN_ERR_CRTL; | ||
| 568 | cf->data[1] = (rxerr > 127) ? | ||
| 569 | CAN_ERR_CRTL_RX_PASSIVE : | ||
| 570 | CAN_ERR_CRTL_TX_PASSIVE; | ||
| 571 | cf->data[6] = txerr; | ||
| 572 | cf->data[7] = rxerr; | ||
| 573 | } | ||
| 574 | } else if (status & XCAN_SR_ERRWRN_MASK) { | ||
| 575 | priv->can.state = CAN_STATE_ERROR_WARNING; | ||
| 576 | priv->can.can_stats.error_warning++; | ||
| 577 | if (skb) { | ||
| 578 | cf->can_id |= CAN_ERR_CRTL; | ||
| 579 | cf->data[1] |= (txerr > rxerr) ? | ||
| 580 | CAN_ERR_CRTL_TX_WARNING : | ||
| 581 | CAN_ERR_CRTL_RX_WARNING; | ||
| 582 | cf->data[6] = txerr; | ||
| 583 | cf->data[7] = rxerr; | ||
| 584 | } | ||
| 585 | } | ||
| 586 | |||
| 587 | /* Check for Arbitration lost interrupt */ | ||
| 588 | if (isr & XCAN_IXR_ARBLST_MASK) { | ||
| 589 | priv->can.can_stats.arbitration_lost++; | ||
| 590 | if (skb) { | ||
| 591 | cf->can_id |= CAN_ERR_LOSTARB; | ||
| 592 | cf->data[0] = CAN_ERR_LOSTARB_UNSPEC; | ||
| 593 | } | ||
| 594 | } | ||
| 595 | |||
| 596 | /* Check for RX FIFO Overflow interrupt */ | ||
| 597 | if (isr & XCAN_IXR_RXOFLW_MASK) { | ||
| 598 | stats->rx_over_errors++; | ||
| 599 | stats->rx_errors++; | ||
| 600 | priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); | ||
| 601 | if (skb) { | ||
| 602 | cf->can_id |= CAN_ERR_CRTL; | ||
| 603 | cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; | ||
| 604 | } | ||
| 605 | } | ||
| 606 | |||
| 607 | /* Check for error interrupt */ | ||
| 608 | if (isr & XCAN_IXR_ERROR_MASK) { | ||
| 609 | if (skb) { | ||
| 610 | cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; | ||
| 611 | cf->data[2] |= CAN_ERR_PROT_UNSPEC; | ||
| 612 | } | ||
| 613 | |||
| 614 | /* Check for Ack error interrupt */ | ||
| 615 | if (err_status & XCAN_ESR_ACKER_MASK) { | ||
| 616 | stats->tx_errors++; | ||
| 617 | if (skb) { | ||
| 618 | cf->can_id |= CAN_ERR_ACK; | ||
| 619 | cf->data[3] |= CAN_ERR_PROT_LOC_ACK; | ||
| 620 | } | ||
| 621 | } | ||
| 622 | |||
| 623 | /* Check for Bit error interrupt */ | ||
| 624 | if (err_status & XCAN_ESR_BERR_MASK) { | ||
| 625 | stats->tx_errors++; | ||
| 626 | if (skb) { | ||
| 627 | cf->can_id |= CAN_ERR_PROT; | ||
| 628 | cf->data[2] = CAN_ERR_PROT_BIT; | ||
| 629 | } | ||
| 630 | } | ||
| 631 | |||
| 632 | /* Check for Stuff error interrupt */ | ||
| 633 | if (err_status & XCAN_ESR_STER_MASK) { | ||
| 634 | stats->rx_errors++; | ||
| 635 | if (skb) { | ||
| 636 | cf->can_id |= CAN_ERR_PROT; | ||
| 637 | cf->data[2] = CAN_ERR_PROT_STUFF; | ||
| 638 | } | ||
| 639 | } | ||
| 640 | |||
| 641 | /* Check for Form error interrupt */ | ||
| 642 | if (err_status & XCAN_ESR_FMER_MASK) { | ||
| 643 | stats->rx_errors++; | ||
| 644 | if (skb) { | ||
| 645 | cf->can_id |= CAN_ERR_PROT; | ||
| 646 | cf->data[2] = CAN_ERR_PROT_FORM; | ||
| 647 | } | ||
| 648 | } | ||
| 649 | |||
| 650 | /* Check for CRC error interrupt */ | ||
| 651 | if (err_status & XCAN_ESR_CRCER_MASK) { | ||
| 652 | stats->rx_errors++; | ||
| 653 | if (skb) { | ||
| 654 | cf->can_id |= CAN_ERR_PROT; | ||
| 655 | cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ | | ||
| 656 | CAN_ERR_PROT_LOC_CRC_DEL; | ||
| 657 | } | ||
| 658 | } | ||
| 659 | priv->can.can_stats.bus_error++; | ||
| 660 | } | ||
| 661 | |||
| 662 | if (skb) { | ||
| 663 | stats->rx_packets++; | ||
| 664 | stats->rx_bytes += cf->can_dlc; | ||
| 665 | netif_rx(skb); | ||
| 666 | } | ||
| 667 | |||
| 668 | netdev_dbg(ndev, "%s: error status register:0x%x\n", | ||
| 669 | __func__, priv->read_reg(priv, XCAN_ESR_OFFSET)); | ||
| 670 | } | ||
| 671 | |||
| 672 | /** | ||
| 673 | * xcan_state_interrupt - It will check the state of the CAN device | ||
| 674 | * @ndev: net_device pointer | ||
| 675 | * @isr: interrupt status register value | ||
| 676 | * | ||
| 677 | * This will checks the state of the CAN device | ||
| 678 | * and puts the device into appropriate state. | ||
| 679 | */ | ||
| 680 | static void xcan_state_interrupt(struct net_device *ndev, u32 isr) | ||
| 681 | { | ||
| 682 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 683 | |||
| 684 | /* Check for Sleep interrupt if set put CAN device in sleep state */ | ||
| 685 | if (isr & XCAN_IXR_SLP_MASK) | ||
| 686 | priv->can.state = CAN_STATE_SLEEPING; | ||
| 687 | |||
| 688 | /* Check for Wake up interrupt if set put CAN device in Active state */ | ||
| 689 | if (isr & XCAN_IXR_WKUP_MASK) | ||
| 690 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
| 691 | } | ||
| 692 | |||
| 693 | /** | ||
| 694 | * xcan_rx_poll - Poll routine for rx packets (NAPI) | ||
| 695 | * @napi: napi structure pointer | ||
| 696 | * @quota: Max number of rx packets to be processed. | ||
| 697 | * | ||
| 698 | * This is the poll routine for rx part. | ||
| 699 | * It will process the packets maximux quota value. | ||
| 700 | * | ||
| 701 | * Return: number of packets received | ||
| 702 | */ | ||
| 703 | static int xcan_rx_poll(struct napi_struct *napi, int quota) | ||
| 704 | { | ||
| 705 | struct net_device *ndev = napi->dev; | ||
| 706 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 707 | u32 isr, ier; | ||
| 708 | int work_done = 0; | ||
| 709 | |||
| 710 | isr = priv->read_reg(priv, XCAN_ISR_OFFSET); | ||
| 711 | while ((isr & XCAN_IXR_RXNEMP_MASK) && (work_done < quota)) { | ||
| 712 | if (isr & XCAN_IXR_RXOK_MASK) { | ||
| 713 | priv->write_reg(priv, XCAN_ICR_OFFSET, | ||
| 714 | XCAN_IXR_RXOK_MASK); | ||
| 715 | work_done += xcan_rx(ndev); | ||
| 716 | } else { | ||
| 717 | priv->write_reg(priv, XCAN_ICR_OFFSET, | ||
| 718 | XCAN_IXR_RXNEMP_MASK); | ||
| 719 | break; | ||
| 720 | } | ||
| 721 | priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_RXNEMP_MASK); | ||
| 722 | isr = priv->read_reg(priv, XCAN_ISR_OFFSET); | ||
| 723 | } | ||
| 724 | |||
| 725 | if (work_done) | ||
| 726 | can_led_event(ndev, CAN_LED_EVENT_RX); | ||
| 727 | |||
| 728 | if (work_done < quota) { | ||
| 729 | napi_complete(napi); | ||
| 730 | ier = priv->read_reg(priv, XCAN_IER_OFFSET); | ||
| 731 | ier |= (XCAN_IXR_RXOK_MASK | XCAN_IXR_RXNEMP_MASK); | ||
| 732 | priv->write_reg(priv, XCAN_IER_OFFSET, ier); | ||
| 733 | } | ||
| 734 | return work_done; | ||
| 735 | } | ||
| 736 | |||
| 737 | /** | ||
| 738 | * xcan_tx_interrupt - Tx Done Isr | ||
| 739 | * @ndev: net_device pointer | ||
| 740 | * @isr: Interrupt status register value | ||
| 741 | */ | ||
| 742 | static void xcan_tx_interrupt(struct net_device *ndev, u32 isr) | ||
| 743 | { | ||
| 744 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 745 | struct net_device_stats *stats = &ndev->stats; | ||
| 746 | |||
| 747 | while ((priv->tx_head - priv->tx_tail > 0) && | ||
| 748 | (isr & XCAN_IXR_TXOK_MASK)) { | ||
| 749 | priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK); | ||
| 750 | can_get_echo_skb(ndev, priv->tx_tail % | ||
| 751 | priv->tx_max); | ||
| 752 | priv->tx_tail++; | ||
| 753 | stats->tx_packets++; | ||
| 754 | isr = priv->read_reg(priv, XCAN_ISR_OFFSET); | ||
| 755 | } | ||
| 756 | can_led_event(ndev, CAN_LED_EVENT_TX); | ||
| 757 | netif_wake_queue(ndev); | ||
| 758 | } | ||
| 759 | |||
| 760 | /** | ||
| 761 | * xcan_interrupt - CAN Isr | ||
| 762 | * @irq: irq number | ||
| 763 | * @dev_id: device id poniter | ||
| 764 | * | ||
| 765 | * This is the xilinx CAN Isr. It checks for the type of interrupt | ||
| 766 | * and invokes the corresponding ISR. | ||
| 767 | * | ||
| 768 | * Return: | ||
| 769 | * IRQ_NONE - If CAN device is in sleep mode, IRQ_HANDLED otherwise | ||
| 770 | */ | ||
| 771 | static irqreturn_t xcan_interrupt(int irq, void *dev_id) | ||
| 772 | { | ||
| 773 | struct net_device *ndev = (struct net_device *)dev_id; | ||
| 774 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 775 | u32 isr, ier; | ||
| 776 | |||
| 777 | /* Get the interrupt status from Xilinx CAN */ | ||
| 778 | isr = priv->read_reg(priv, XCAN_ISR_OFFSET); | ||
| 779 | if (!isr) | ||
| 780 | return IRQ_NONE; | ||
| 781 | |||
| 782 | /* Check for the type of interrupt and Processing it */ | ||
| 783 | if (isr & (XCAN_IXR_SLP_MASK | XCAN_IXR_WKUP_MASK)) { | ||
| 784 | priv->write_reg(priv, XCAN_ICR_OFFSET, (XCAN_IXR_SLP_MASK | | ||
| 785 | XCAN_IXR_WKUP_MASK)); | ||
| 786 | xcan_state_interrupt(ndev, isr); | ||
| 787 | } | ||
| 788 | |||
| 789 | /* Check for Tx interrupt and Processing it */ | ||
| 790 | if (isr & XCAN_IXR_TXOK_MASK) | ||
| 791 | xcan_tx_interrupt(ndev, isr); | ||
| 792 | |||
| 793 | /* Check for the type of error interrupt and Processing it */ | ||
| 794 | if (isr & (XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK | | ||
| 795 | XCAN_IXR_BSOFF_MASK | XCAN_IXR_ARBLST_MASK)) { | ||
| 796 | priv->write_reg(priv, XCAN_ICR_OFFSET, (XCAN_IXR_ERROR_MASK | | ||
| 797 | XCAN_IXR_RXOFLW_MASK | XCAN_IXR_BSOFF_MASK | | ||
| 798 | XCAN_IXR_ARBLST_MASK)); | ||
| 799 | xcan_err_interrupt(ndev, isr); | ||
| 800 | } | ||
| 801 | |||
| 802 | /* Check for the type of receive interrupt and Processing it */ | ||
| 803 | if (isr & (XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK)) { | ||
| 804 | ier = priv->read_reg(priv, XCAN_IER_OFFSET); | ||
| 805 | ier &= ~(XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK); | ||
| 806 | priv->write_reg(priv, XCAN_IER_OFFSET, ier); | ||
| 807 | napi_schedule(&priv->napi); | ||
| 808 | } | ||
| 809 | return IRQ_HANDLED; | ||
| 810 | } | ||
| 811 | |||
| 812 | /** | ||
| 813 | * xcan_chip_stop - Driver stop routine | ||
| 814 | * @ndev: Pointer to net_device structure | ||
| 815 | * | ||
| 816 | * This is the drivers stop routine. It will disable the | ||
| 817 | * interrupts and put the device into configuration mode. | ||
| 818 | */ | ||
| 819 | static void xcan_chip_stop(struct net_device *ndev) | ||
| 820 | { | ||
| 821 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 822 | u32 ier; | ||
| 823 | |||
| 824 | /* Disable interrupts and leave the can in configuration mode */ | ||
| 825 | ier = priv->read_reg(priv, XCAN_IER_OFFSET); | ||
| 826 | ier &= ~XCAN_INTR_ALL; | ||
| 827 | priv->write_reg(priv, XCAN_IER_OFFSET, ier); | ||
| 828 | priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); | ||
| 829 | priv->can.state = CAN_STATE_STOPPED; | ||
| 830 | } | ||
| 831 | |||
| 832 | /** | ||
| 833 | * xcan_open - Driver open routine | ||
| 834 | * @ndev: Pointer to net_device structure | ||
| 835 | * | ||
| 836 | * This is the driver open routine. | ||
| 837 | * Return: 0 on success and failure value on error | ||
| 838 | */ | ||
| 839 | static int xcan_open(struct net_device *ndev) | ||
| 840 | { | ||
| 841 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 842 | int ret; | ||
| 843 | |||
| 844 | ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags, | ||
| 845 | ndev->name, ndev); | ||
| 846 | if (ret < 0) { | ||
| 847 | netdev_err(ndev, "irq allocation for CAN failed\n"); | ||
| 848 | goto err; | ||
| 849 | } | ||
| 850 | |||
| 851 | ret = clk_prepare_enable(priv->can_clk); | ||
| 852 | if (ret) { | ||
| 853 | netdev_err(ndev, "unable to enable device clock\n"); | ||
| 854 | goto err_irq; | ||
| 855 | } | ||
| 856 | |||
| 857 | ret = clk_prepare_enable(priv->bus_clk); | ||
| 858 | if (ret) { | ||
| 859 | netdev_err(ndev, "unable to enable bus clock\n"); | ||
| 860 | goto err_can_clk; | ||
| 861 | } | ||
| 862 | |||
| 863 | /* Set chip into reset mode */ | ||
| 864 | ret = set_reset_mode(ndev); | ||
| 865 | if (ret < 0) { | ||
| 866 | netdev_err(ndev, "mode resetting failed!\n"); | ||
| 867 | goto err_bus_clk; | ||
| 868 | } | ||
| 869 | |||
| 870 | /* Common open */ | ||
| 871 | ret = open_candev(ndev); | ||
| 872 | if (ret) | ||
| 873 | goto err_bus_clk; | ||
| 874 | |||
| 875 | ret = xcan_chip_start(ndev); | ||
| 876 | if (ret < 0) { | ||
| 877 | netdev_err(ndev, "xcan_chip_start failed!\n"); | ||
| 878 | goto err_candev; | ||
| 879 | } | ||
| 880 | |||
| 881 | can_led_event(ndev, CAN_LED_EVENT_OPEN); | ||
| 882 | napi_enable(&priv->napi); | ||
| 883 | netif_start_queue(ndev); | ||
| 884 | |||
| 885 | return 0; | ||
| 886 | |||
| 887 | err_candev: | ||
| 888 | close_candev(ndev); | ||
| 889 | err_bus_clk: | ||
| 890 | clk_disable_unprepare(priv->bus_clk); | ||
| 891 | err_can_clk: | ||
| 892 | clk_disable_unprepare(priv->can_clk); | ||
| 893 | err_irq: | ||
| 894 | free_irq(ndev->irq, ndev); | ||
| 895 | err: | ||
| 896 | return ret; | ||
| 897 | } | ||
| 898 | |||
| 899 | /** | ||
| 900 | * xcan_close - Driver close routine | ||
| 901 | * @ndev: Pointer to net_device structure | ||
| 902 | * | ||
| 903 | * Return: 0 always | ||
| 904 | */ | ||
| 905 | static int xcan_close(struct net_device *ndev) | ||
| 906 | { | ||
| 907 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 908 | |||
| 909 | netif_stop_queue(ndev); | ||
| 910 | napi_disable(&priv->napi); | ||
| 911 | xcan_chip_stop(ndev); | ||
| 912 | clk_disable_unprepare(priv->bus_clk); | ||
| 913 | clk_disable_unprepare(priv->can_clk); | ||
| 914 | free_irq(ndev->irq, ndev); | ||
| 915 | close_candev(ndev); | ||
| 916 | |||
| 917 | can_led_event(ndev, CAN_LED_EVENT_STOP); | ||
| 918 | |||
| 919 | return 0; | ||
| 920 | } | ||
| 921 | |||
| 922 | /** | ||
| 923 | * xcan_get_berr_counter - error counter routine | ||
| 924 | * @ndev: Pointer to net_device structure | ||
| 925 | * @bec: Pointer to can_berr_counter structure | ||
| 926 | * | ||
| 927 | * This is the driver error counter routine. | ||
| 928 | * Return: 0 on success and failure value on error | ||
| 929 | */ | ||
| 930 | static int xcan_get_berr_counter(const struct net_device *ndev, | ||
| 931 | struct can_berr_counter *bec) | ||
| 932 | { | ||
| 933 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 934 | int ret; | ||
| 935 | |||
| 936 | ret = clk_prepare_enable(priv->can_clk); | ||
| 937 | if (ret) | ||
| 938 | goto err; | ||
| 939 | |||
| 940 | ret = clk_prepare_enable(priv->bus_clk); | ||
| 941 | if (ret) | ||
| 942 | goto err_clk; | ||
| 943 | |||
| 944 | bec->txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK; | ||
| 945 | bec->rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) & | ||
| 946 | XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT); | ||
| 947 | |||
| 948 | clk_disable_unprepare(priv->bus_clk); | ||
| 949 | clk_disable_unprepare(priv->can_clk); | ||
| 950 | |||
| 951 | return 0; | ||
| 952 | |||
| 953 | err_clk: | ||
| 954 | clk_disable_unprepare(priv->can_clk); | ||
| 955 | err: | ||
| 956 | return ret; | ||
| 957 | } | ||
| 958 | |||
| 959 | |||
| 960 | static const struct net_device_ops xcan_netdev_ops = { | ||
| 961 | .ndo_open = xcan_open, | ||
| 962 | .ndo_stop = xcan_close, | ||
| 963 | .ndo_start_xmit = xcan_start_xmit, | ||
| 964 | }; | ||
| 965 | |||
| 966 | /** | ||
| 967 | * xcan_suspend - Suspend method for the driver | ||
| 968 | * @dev: Address of the platform_device structure | ||
| 969 | * | ||
| 970 | * Put the driver into low power mode. | ||
| 971 | * Return: 0 always | ||
| 972 | */ | ||
| 973 | static int __maybe_unused xcan_suspend(struct device *dev) | ||
| 974 | { | ||
| 975 | struct platform_device *pdev = dev_get_drvdata(dev); | ||
| 976 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
| 977 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 978 | |||
| 979 | if (netif_running(ndev)) { | ||
| 980 | netif_stop_queue(ndev); | ||
| 981 | netif_device_detach(ndev); | ||
| 982 | } | ||
| 983 | |||
| 984 | priv->write_reg(priv, XCAN_MSR_OFFSET, XCAN_MSR_SLEEP_MASK); | ||
| 985 | priv->can.state = CAN_STATE_SLEEPING; | ||
| 986 | |||
| 987 | clk_disable(priv->bus_clk); | ||
| 988 | clk_disable(priv->can_clk); | ||
| 989 | |||
| 990 | return 0; | ||
| 991 | } | ||
| 992 | |||
| 993 | /** | ||
| 994 | * xcan_resume - Resume from suspend | ||
| 995 | * @dev: Address of the platformdevice structure | ||
| 996 | * | ||
| 997 | * Resume operation after suspend. | ||
| 998 | * Return: 0 on success and failure value on error | ||
| 999 | */ | ||
| 1000 | static int __maybe_unused xcan_resume(struct device *dev) | ||
| 1001 | { | ||
| 1002 | struct platform_device *pdev = dev_get_drvdata(dev); | ||
| 1003 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
| 1004 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 1005 | int ret; | ||
| 1006 | |||
| 1007 | ret = clk_enable(priv->bus_clk); | ||
| 1008 | if (ret) { | ||
| 1009 | dev_err(dev, "Cannot enable clock.\n"); | ||
| 1010 | return ret; | ||
| 1011 | } | ||
| 1012 | ret = clk_enable(priv->can_clk); | ||
| 1013 | if (ret) { | ||
| 1014 | dev_err(dev, "Cannot enable clock.\n"); | ||
| 1015 | clk_disable_unprepare(priv->bus_clk); | ||
| 1016 | return ret; | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | priv->write_reg(priv, XCAN_MSR_OFFSET, 0); | ||
| 1020 | priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK); | ||
| 1021 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
| 1022 | |||
| 1023 | if (netif_running(ndev)) { | ||
| 1024 | netif_device_attach(ndev); | ||
| 1025 | netif_start_queue(ndev); | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | return 0; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | static SIMPLE_DEV_PM_OPS(xcan_dev_pm_ops, xcan_suspend, xcan_resume); | ||
| 1032 | |||
| 1033 | /** | ||
| 1034 | * xcan_probe - Platform registration call | ||
| 1035 | * @pdev: Handle to the platform device structure | ||
| 1036 | * | ||
| 1037 | * This function does all the memory allocation and registration for the CAN | ||
| 1038 | * device. | ||
| 1039 | * | ||
| 1040 | * Return: 0 on success and failure value on error | ||
| 1041 | */ | ||
| 1042 | static int xcan_probe(struct platform_device *pdev) | ||
| 1043 | { | ||
| 1044 | struct resource *res; /* IO mem resources */ | ||
| 1045 | struct net_device *ndev; | ||
| 1046 | struct xcan_priv *priv; | ||
| 1047 | void __iomem *addr; | ||
| 1048 | int ret, rx_max, tx_max; | ||
| 1049 | |||
| 1050 | /* Get the virtual base address for the device */ | ||
| 1051 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1052 | addr = devm_ioremap_resource(&pdev->dev, res); | ||
| 1053 | if (IS_ERR(addr)) { | ||
| 1054 | ret = PTR_ERR(addr); | ||
| 1055 | goto err; | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | ret = of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", &tx_max); | ||
| 1059 | if (ret < 0) | ||
| 1060 | goto err; | ||
| 1061 | |||
| 1062 | ret = of_property_read_u32(pdev->dev.of_node, "rx-fifo-depth", &rx_max); | ||
| 1063 | if (ret < 0) | ||
| 1064 | goto err; | ||
| 1065 | |||
| 1066 | /* Create a CAN device instance */ | ||
| 1067 | ndev = alloc_candev(sizeof(struct xcan_priv), tx_max); | ||
| 1068 | if (!ndev) | ||
| 1069 | return -ENOMEM; | ||
| 1070 | |||
| 1071 | priv = netdev_priv(ndev); | ||
| 1072 | priv->dev = ndev; | ||
| 1073 | priv->can.bittiming_const = &xcan_bittiming_const; | ||
| 1074 | priv->can.do_set_mode = xcan_do_set_mode; | ||
| 1075 | priv->can.do_get_berr_counter = xcan_get_berr_counter; | ||
| 1076 | priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | | ||
| 1077 | CAN_CTRLMODE_BERR_REPORTING; | ||
| 1078 | priv->reg_base = addr; | ||
| 1079 | priv->tx_max = tx_max; | ||
| 1080 | |||
| 1081 | /* Get IRQ for the device */ | ||
| 1082 | ndev->irq = platform_get_irq(pdev, 0); | ||
| 1083 | ndev->flags |= IFF_ECHO; /* We support local echo */ | ||
| 1084 | |||
| 1085 | platform_set_drvdata(pdev, ndev); | ||
| 1086 | SET_NETDEV_DEV(ndev, &pdev->dev); | ||
| 1087 | ndev->netdev_ops = &xcan_netdev_ops; | ||
| 1088 | |||
| 1089 | /* Getting the CAN can_clk info */ | ||
| 1090 | priv->can_clk = devm_clk_get(&pdev->dev, "can_clk"); | ||
| 1091 | if (IS_ERR(priv->can_clk)) { | ||
| 1092 | dev_err(&pdev->dev, "Device clock not found.\n"); | ||
| 1093 | ret = PTR_ERR(priv->can_clk); | ||
| 1094 | goto err_free; | ||
| 1095 | } | ||
| 1096 | /* Check for type of CAN device */ | ||
| 1097 | if (of_device_is_compatible(pdev->dev.of_node, | ||
| 1098 | "xlnx,zynq-can-1.0")) { | ||
| 1099 | priv->bus_clk = devm_clk_get(&pdev->dev, "pclk"); | ||
| 1100 | if (IS_ERR(priv->bus_clk)) { | ||
| 1101 | dev_err(&pdev->dev, "bus clock not found\n"); | ||
| 1102 | ret = PTR_ERR(priv->bus_clk); | ||
| 1103 | goto err_free; | ||
| 1104 | } | ||
| 1105 | } else { | ||
| 1106 | priv->bus_clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); | ||
| 1107 | if (IS_ERR(priv->bus_clk)) { | ||
| 1108 | dev_err(&pdev->dev, "bus clock not found\n"); | ||
| 1109 | ret = PTR_ERR(priv->bus_clk); | ||
| 1110 | goto err_free; | ||
| 1111 | } | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | ret = clk_prepare_enable(priv->can_clk); | ||
| 1115 | if (ret) { | ||
| 1116 | dev_err(&pdev->dev, "unable to enable device clock\n"); | ||
| 1117 | goto err_free; | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | ret = clk_prepare_enable(priv->bus_clk); | ||
| 1121 | if (ret) { | ||
| 1122 | dev_err(&pdev->dev, "unable to enable bus clock\n"); | ||
| 1123 | goto err_unprepare_disable_dev; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | priv->write_reg = xcan_write_reg_le; | ||
| 1127 | priv->read_reg = xcan_read_reg_le; | ||
| 1128 | |||
| 1129 | if (priv->read_reg(priv, XCAN_SR_OFFSET) != XCAN_SR_CONFIG_MASK) { | ||
| 1130 | priv->write_reg = xcan_write_reg_be; | ||
| 1131 | priv->read_reg = xcan_read_reg_be; | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | priv->can.clock.freq = clk_get_rate(priv->can_clk); | ||
| 1135 | |||
| 1136 | netif_napi_add(ndev, &priv->napi, xcan_rx_poll, rx_max); | ||
| 1137 | |||
| 1138 | ret = register_candev(ndev); | ||
| 1139 | if (ret) { | ||
| 1140 | dev_err(&pdev->dev, "fail to register failed (err=%d)\n", ret); | ||
| 1141 | goto err_unprepare_disable_busclk; | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | devm_can_led_init(ndev); | ||
| 1145 | clk_disable_unprepare(priv->bus_clk); | ||
| 1146 | clk_disable_unprepare(priv->can_clk); | ||
| 1147 | netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth:%d\n", | ||
| 1148 | priv->reg_base, ndev->irq, priv->can.clock.freq, | ||
| 1149 | priv->tx_max); | ||
| 1150 | |||
| 1151 | return 0; | ||
| 1152 | |||
| 1153 | err_unprepare_disable_busclk: | ||
| 1154 | clk_disable_unprepare(priv->bus_clk); | ||
| 1155 | err_unprepare_disable_dev: | ||
| 1156 | clk_disable_unprepare(priv->can_clk); | ||
| 1157 | err_free: | ||
| 1158 | free_candev(ndev); | ||
| 1159 | err: | ||
| 1160 | return ret; | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | /** | ||
| 1164 | * xcan_remove - Unregister the device after releasing the resources | ||
| 1165 | * @pdev: Handle to the platform device structure | ||
| 1166 | * | ||
| 1167 | * This function frees all the resources allocated to the device. | ||
| 1168 | * Return: 0 always | ||
| 1169 | */ | ||
| 1170 | static int xcan_remove(struct platform_device *pdev) | ||
| 1171 | { | ||
| 1172 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
| 1173 | struct xcan_priv *priv = netdev_priv(ndev); | ||
| 1174 | |||
| 1175 | if (set_reset_mode(ndev) < 0) | ||
| 1176 | netdev_err(ndev, "mode resetting failed!\n"); | ||
| 1177 | |||
| 1178 | unregister_candev(ndev); | ||
| 1179 | netif_napi_del(&priv->napi); | ||
| 1180 | free_candev(ndev); | ||
| 1181 | |||
| 1182 | return 0; | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | /* Match table for OF platform binding */ | ||
| 1186 | static struct of_device_id xcan_of_match[] = { | ||
| 1187 | { .compatible = "xlnx,zynq-can-1.0", }, | ||
| 1188 | { .compatible = "xlnx,axi-can-1.00.a", }, | ||
| 1189 | { /* end of list */ }, | ||
| 1190 | }; | ||
| 1191 | MODULE_DEVICE_TABLE(of, xcan_of_match); | ||
| 1192 | |||
| 1193 | static struct platform_driver xcan_driver = { | ||
| 1194 | .probe = xcan_probe, | ||
| 1195 | .remove = xcan_remove, | ||
| 1196 | .driver = { | ||
| 1197 | .owner = THIS_MODULE, | ||
| 1198 | .name = DRIVER_NAME, | ||
| 1199 | .pm = &xcan_dev_pm_ops, | ||
| 1200 | .of_match_table = xcan_of_match, | ||
| 1201 | }, | ||
| 1202 | }; | ||
| 1203 | |||
| 1204 | module_platform_driver(xcan_driver); | ||
| 1205 | |||
| 1206 | MODULE_LICENSE("GPL"); | ||
| 1207 | MODULE_AUTHOR("Xilinx Inc"); | ||
| 1208 | MODULE_DESCRIPTION("Xilinx CAN interface"); | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 4d8f8aba0ea5..4cab09d3f807 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
| 8 | * | 8 | * |
| 9 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 9 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 10 | * Written by: Eliezer Tamir | 10 | * Written by: Eliezer Tamir |
| 11 | * Based on code from Michael Chan's bnx2 driver | 11 | * Based on code from Michael Chan's bnx2 driver |
| 12 | */ | 12 | */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 9261d5313b5b..d18441ebe944 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
| 8 | * | 8 | * |
| 9 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 9 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 10 | * Written by: Eliezer Tamir | 10 | * Written by: Eliezer Tamir |
| 11 | * Based on code from Michael Chan's bnx2 driver | 11 | * Based on code from Michael Chan's bnx2 driver |
| 12 | * UDP CSUM errata workaround by Arik Gendelman | 12 | * UDP CSUM errata workaround by Arik Gendelman |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 3448cc033ca5..571427c7226b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
| 8 | * | 8 | * |
| 9 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 9 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 10 | * Written by: Eliezer Tamir | 10 | * Written by: Eliezer Tamir |
| 11 | * Based on code from Michael Chan's bnx2 driver | 11 | * Based on code from Michael Chan's bnx2 driver |
| 12 | * UDP CSUM errata workaround by Arik Gendelman | 12 | * UDP CSUM errata workaround by Arik Gendelman |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c index 97ea5421dd96..51a952c51cb1 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | * license other than the GPL, without Broadcom's express prior written | 12 | * license other than the GPL, without Broadcom's express prior written |
| 13 | * consent. | 13 | * consent. |
| 14 | * | 14 | * |
| 15 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 15 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 16 | * Written by: Dmitry Kravkov | 16 | * Written by: Dmitry Kravkov |
| 17 | * | 17 | * |
| 18 | */ | 18 | */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h index 804b8f64463e..c6939ecb02c5 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | * license other than the GPL, without Broadcom's express prior written | 12 | * license other than the GPL, without Broadcom's express prior written |
| 13 | * consent. | 13 | * consent. |
| 14 | * | 14 | * |
| 15 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 15 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 16 | * Written by: Dmitry Kravkov | 16 | * Written by: Dmitry Kravkov |
| 17 | * | 17 | * |
| 18 | */ | 18 | */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 03224090ecf9..5203a8924edf 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
| 8 | * | 8 | * |
| 9 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 9 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 10 | * Written by: Eliezer Tamir | 10 | * Written by: Eliezer Tamir |
| 11 | * Based on code from Michael Chan's bnx2 driver | 11 | * Based on code from Michael Chan's bnx2 driver |
| 12 | * UDP CSUM errata workaround by Arik Gendelman | 12 | * UDP CSUM errata workaround by Arik Gendelman |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h index f572ae164fce..8aafd9b5d6a2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h | |||
| @@ -6,8 +6,8 @@ | |||
| 6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
| 8 | * | 8 | * |
| 9 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 9 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 10 | * Written by: Vladislav Zolotarov <vladz@broadcom.com> | 10 | * Written by: Vladislav Zolotarov |
| 11 | * Based on the original idea of John Wright <john.wright@hp.com>. | 11 | * Based on the original idea of John Wright <john.wright@hp.com>. |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h index c2dfea7968f4..bd90e50bd8e6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h | |||
| @@ -7,9 +7,9 @@ | |||
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation. | 8 | * the Free Software Foundation. |
| 9 | * | 9 | * |
| 10 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 10 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 11 | * Written by: Eliezer Tamir | 11 | * Written by: Eliezer Tamir |
| 12 | * Modified by: Vladislav Zolotarov <vladz@broadcom.com> | 12 | * Modified by: Vladislav Zolotarov |
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #ifndef BNX2X_INIT_H | 15 | #ifndef BNX2X_INIT_H |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h index 8ab0dd900960..5669ed2e87d0 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h | |||
| @@ -8,8 +8,8 @@ | |||
| 8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation. | 9 | * the Free Software Foundation. |
| 10 | * | 10 | * |
| 11 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 11 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 12 | * Written by: Vladislav Zolotarov <vladz@broadcom.com> | 12 | * Written by: Vladislav Zolotarov |
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #ifndef BNX2X_INIT_OPS_H | 15 | #ifndef BNX2X_INIT_OPS_H |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 3b0d43154e67..ff2bdd80f0aa 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
| 8 | * | 8 | * |
| 9 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 9 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 10 | * Written by: Eliezer Tamir | 10 | * Written by: Eliezer Tamir |
| 11 | * Based on code from Michael Chan's bnx2 driver | 11 | * Based on code from Michael Chan's bnx2 driver |
| 12 | * UDP CSUM errata workaround by Arik Gendelman | 12 | * UDP CSUM errata workaround by Arik Gendelman |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 31297266b743..736264b5fc3b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | * license other than the GPL, without Broadcom's express prior written | 12 | * license other than the GPL, without Broadcom's express prior written |
| 13 | * consent. | 13 | * consent. |
| 14 | * | 14 | * |
| 15 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 15 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 16 | * Written by: Vladislav Zolotarov | 16 | * Written by: Vladislav Zolotarov |
| 17 | * | 17 | * |
| 18 | */ | 18 | */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index 80f6c790ed88..718ecd294661 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | * license other than the GPL, without Broadcom's express prior written | 12 | * license other than the GPL, without Broadcom's express prior written |
| 13 | * consent. | 13 | * consent. |
| 14 | * | 14 | * |
| 15 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 15 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 16 | * Written by: Vladislav Zolotarov | 16 | * Written by: Vladislav Zolotarov |
| 17 | * | 17 | * |
| 18 | */ | 18 | */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 02a23c2901c8..a93c7af7afe6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | |||
| @@ -12,9 +12,9 @@ | |||
| 12 | * license other than the GPL, without Broadcom's express prior written | 12 | * license other than the GPL, without Broadcom's express prior written |
| 13 | * consent. | 13 | * consent. |
| 14 | * | 14 | * |
| 15 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 15 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 16 | * Written by: Shmulik Ravid <shmulikr@broadcom.com> | 16 | * Written by: Shmulik Ravid |
| 17 | * Ariel Elior <ariele@broadcom.com> | 17 | * Ariel Elior <ariel.elior@qlogic.com> |
| 18 | * | 18 | * |
| 19 | */ | 19 | */ |
| 20 | #include "bnx2x.h" | 20 | #include "bnx2x.h" |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index cd4d624d8485..96c575e147a5 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | |||
| @@ -12,9 +12,9 @@ | |||
| 12 | * license other than the GPL, without Broadcom's express prior written | 12 | * license other than the GPL, without Broadcom's express prior written |
| 13 | * consent. | 13 | * consent. |
| 14 | * | 14 | * |
| 15 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 15 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 16 | * Written by: Shmulik Ravid <shmulikr@broadcom.com> | 16 | * Written by: Shmulik Ravid |
| 17 | * Ariel Elior <ariele@broadcom.com> | 17 | * Ariel Elior <ariel.elior@qlogic.com> |
| 18 | */ | 18 | */ |
| 19 | #ifndef BNX2X_SRIOV_H | 19 | #ifndef BNX2X_SRIOV_H |
| 20 | #define BNX2X_SRIOV_H | 20 | #define BNX2X_SRIOV_H |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index 3b75070411aa..ca47665f94bf 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
| 8 | * | 8 | * |
| 9 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 9 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 10 | * Written by: Eliezer Tamir | 10 | * Written by: Eliezer Tamir |
| 11 | * Based on code from Michael Chan's bnx2 driver | 11 | * Based on code from Michael Chan's bnx2 driver |
| 12 | * UDP CSUM errata workaround by Arik Gendelman | 12 | * UDP CSUM errata workaround by Arik Gendelman |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h index f35845006cdd..2beceaefdeea 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
| 8 | * | 8 | * |
| 9 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 9 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 10 | * Written by: Eliezer Tamir | 10 | * Written by: Eliezer Tamir |
| 11 | * Based on code from Michael Chan's bnx2 driver | 11 | * Based on code from Michael Chan's bnx2 driver |
| 12 | * UDP CSUM errata workaround by Arik Gendelman | 12 | * UDP CSUM errata workaround by Arik Gendelman |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index 784c7155b98a..d712d0ddd719 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | |||
| @@ -12,9 +12,9 @@ | |||
| 12 | * license other than the GPL, without Broadcom's express prior written | 12 | * license other than the GPL, without Broadcom's express prior written |
| 13 | * consent. | 13 | * consent. |
| 14 | * | 14 | * |
| 15 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 15 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 16 | * Written by: Shmulik Ravid <shmulikr@broadcom.com> | 16 | * Written by: Shmulik Ravid |
| 17 | * Ariel Elior <ariele@broadcom.com> | 17 | * Ariel Elior <ariel.elior@qlogic.com> |
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include "bnx2x.h" | 20 | #include "bnx2x.h" |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h index c922b81170e5..e21e706762c9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | * license other than the GPL, without Broadcom's express prior written | 12 | * license other than the GPL, without Broadcom's express prior written |
| 13 | * consent. | 13 | * consent. |
| 14 | * | 14 | * |
| 15 | * Maintained by: Eilon Greenstein <eilong@broadcom.com> | 15 | * Maintained by: Ariel Elior <ariel.elior@qlogic.com> |
| 16 | * Written by: Ariel Elior <ariele@broadcom.com> | 16 | * Written by: Ariel Elior <ariel.elior@qlogic.com> |
| 17 | */ | 17 | */ |
| 18 | #ifndef VF_PF_IF_H | 18 | #ifndef VF_PF_IF_H |
| 19 | #define VF_PF_IF_H | 19 | #define VF_PF_IF_H |
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 0d8995cc92ed..d5a220d5bad1 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c | |||
| @@ -1217,7 +1217,7 @@ static void enic_calc_int_moderation(struct enic *enic, struct vnic_rq *rq) | |||
| 1217 | */ | 1217 | */ |
| 1218 | 1218 | ||
| 1219 | traffic <<= 3; | 1219 | traffic <<= 3; |
| 1220 | traffic /= delta; | 1220 | traffic = delta > UINT_MAX ? 0 : traffic / (u32)delta; |
| 1221 | 1221 | ||
| 1222 | for (index = 0; index < ENIC_MAX_COALESCE_TIMERS; index++) | 1222 | for (index = 0; index < ENIC_MAX_COALESCE_TIMERS; index++) |
| 1223 | if (traffic < mod_table[index].rx_rate) | 1223 | if (traffic < mod_table[index].rx_rate) |
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 31c376628bfd..2e7c5553955e 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
| @@ -374,6 +374,7 @@ enum vf_state { | |||
| 374 | #define BE_FLAGS_LINK_STATUS_INIT 1 | 374 | #define BE_FLAGS_LINK_STATUS_INIT 1 |
| 375 | #define BE_FLAGS_WORKER_SCHEDULED (1 << 3) | 375 | #define BE_FLAGS_WORKER_SCHEDULED (1 << 3) |
| 376 | #define BE_FLAGS_VLAN_PROMISC (1 << 4) | 376 | #define BE_FLAGS_VLAN_PROMISC (1 << 4) |
| 377 | #define BE_FLAGS_MCAST_PROMISC (1 << 5) | ||
| 377 | #define BE_FLAGS_NAPI_ENABLED (1 << 9) | 378 | #define BE_FLAGS_NAPI_ENABLED (1 << 9) |
| 378 | #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11) | 379 | #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11) |
| 379 | #define BE_FLAGS_VXLAN_OFFLOADS (1 << 12) | 380 | #define BE_FLAGS_VXLAN_OFFLOADS (1 << 12) |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 476752d0a6a4..a568f7d1a24c 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c | |||
| @@ -119,22 +119,29 @@ static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1) | |||
| 119 | return (void *)addr; | 119 | return (void *)addr; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | static int be_mcc_compl_process(struct be_adapter *adapter, | 122 | static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status) |
| 123 | struct be_mcc_compl *compl) | 123 | { |
| 124 | if (base_status == MCC_STATUS_NOT_SUPPORTED || | ||
| 125 | base_status == MCC_STATUS_ILLEGAL_REQUEST || | ||
| 126 | addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES || | ||
| 127 | (opcode == OPCODE_COMMON_WRITE_FLASHROM && | ||
| 128 | (base_status == MCC_STATUS_ILLEGAL_FIELD || | ||
| 129 | addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH))) | ||
| 130 | return true; | ||
| 131 | else | ||
| 132 | return false; | ||
| 133 | } | ||
| 134 | |||
| 135 | /* Place holder for all the async MCC cmds wherein the caller is not in a busy | ||
| 136 | * loop (has not issued be_mcc_notify_wait()) | ||
| 137 | */ | ||
| 138 | static void be_async_cmd_process(struct be_adapter *adapter, | ||
| 139 | struct be_mcc_compl *compl, | ||
| 140 | struct be_cmd_resp_hdr *resp_hdr) | ||
| 124 | { | 141 | { |
| 125 | u16 compl_status, extd_status; | 142 | enum mcc_base_status base_status = base_status(compl->status); |
| 126 | struct be_cmd_resp_hdr *resp_hdr; | ||
| 127 | u8 opcode = 0, subsystem = 0; | 143 | u8 opcode = 0, subsystem = 0; |
| 128 | 144 | ||
| 129 | /* Just swap the status to host endian; mcc tag is opaquely copied | ||
| 130 | * from mcc_wrb */ | ||
| 131 | be_dws_le_to_cpu(compl, 4); | ||
| 132 | |||
| 133 | compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & | ||
| 134 | CQE_STATUS_COMPL_MASK; | ||
| 135 | |||
| 136 | resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1); | ||
| 137 | |||
| 138 | if (resp_hdr) { | 145 | if (resp_hdr) { |
| 139 | opcode = resp_hdr->opcode; | 146 | opcode = resp_hdr->opcode; |
| 140 | subsystem = resp_hdr->subsystem; | 147 | subsystem = resp_hdr->subsystem; |
| @@ -143,61 +150,86 @@ static int be_mcc_compl_process(struct be_adapter *adapter, | |||
| 143 | if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST && | 150 | if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST && |
| 144 | subsystem == CMD_SUBSYSTEM_LOWLEVEL) { | 151 | subsystem == CMD_SUBSYSTEM_LOWLEVEL) { |
| 145 | complete(&adapter->et_cmd_compl); | 152 | complete(&adapter->et_cmd_compl); |
| 146 | return 0; | 153 | return; |
| 147 | } | 154 | } |
| 148 | 155 | ||
| 149 | if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) || | 156 | if ((opcode == OPCODE_COMMON_WRITE_FLASHROM || |
| 150 | (opcode == OPCODE_COMMON_WRITE_OBJECT)) && | 157 | opcode == OPCODE_COMMON_WRITE_OBJECT) && |
| 151 | (subsystem == CMD_SUBSYSTEM_COMMON)) { | 158 | subsystem == CMD_SUBSYSTEM_COMMON) { |
| 152 | adapter->flash_status = compl_status; | 159 | adapter->flash_status = compl->status; |
| 153 | complete(&adapter->et_cmd_compl); | 160 | complete(&adapter->et_cmd_compl); |
| 161 | return; | ||
| 154 | } | 162 | } |
| 155 | 163 | ||
| 156 | if (compl_status == MCC_STATUS_SUCCESS) { | 164 | if ((opcode == OPCODE_ETH_GET_STATISTICS || |
| 157 | if (((opcode == OPCODE_ETH_GET_STATISTICS) || | 165 | opcode == OPCODE_ETH_GET_PPORT_STATS) && |
| 158 | (opcode == OPCODE_ETH_GET_PPORT_STATS)) && | 166 | subsystem == CMD_SUBSYSTEM_ETH && |
| 159 | (subsystem == CMD_SUBSYSTEM_ETH)) { | 167 | base_status == MCC_STATUS_SUCCESS) { |
| 160 | be_parse_stats(adapter); | 168 | be_parse_stats(adapter); |
| 161 | adapter->stats_cmd_sent = false; | 169 | adapter->stats_cmd_sent = false; |
| 162 | } | 170 | return; |
| 163 | if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES && | 171 | } |
| 164 | subsystem == CMD_SUBSYSTEM_COMMON) { | 172 | |
| 173 | if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES && | ||
| 174 | subsystem == CMD_SUBSYSTEM_COMMON) { | ||
| 175 | if (base_status == MCC_STATUS_SUCCESS) { | ||
| 165 | struct be_cmd_resp_get_cntl_addnl_attribs *resp = | 176 | struct be_cmd_resp_get_cntl_addnl_attribs *resp = |
| 166 | (void *)resp_hdr; | 177 | (void *)resp_hdr; |
| 167 | adapter->drv_stats.be_on_die_temperature = | 178 | adapter->drv_stats.be_on_die_temperature = |
| 168 | resp->on_die_temperature; | 179 | resp->on_die_temperature; |
| 169 | } | 180 | } else { |
| 170 | } else { | ||
| 171 | if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) | ||
| 172 | adapter->be_get_temp_freq = 0; | 181 | adapter->be_get_temp_freq = 0; |
| 182 | } | ||
| 183 | return; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | static int be_mcc_compl_process(struct be_adapter *adapter, | ||
| 188 | struct be_mcc_compl *compl) | ||
| 189 | { | ||
| 190 | enum mcc_base_status base_status; | ||
| 191 | enum mcc_addl_status addl_status; | ||
| 192 | struct be_cmd_resp_hdr *resp_hdr; | ||
| 193 | u8 opcode = 0, subsystem = 0; | ||
| 173 | 194 | ||
| 174 | if (compl_status == MCC_STATUS_NOT_SUPPORTED || | 195 | /* Just swap the status to host endian; mcc tag is opaquely copied |
| 175 | compl_status == MCC_STATUS_ILLEGAL_REQUEST) | 196 | * from mcc_wrb */ |
| 176 | goto done; | 197 | be_dws_le_to_cpu(compl, 4); |
| 177 | 198 | ||
| 178 | if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { | 199 | base_status = base_status(compl->status); |
| 200 | addl_status = addl_status(compl->status); | ||
| 201 | |||
| 202 | resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1); | ||
| 203 | if (resp_hdr) { | ||
| 204 | opcode = resp_hdr->opcode; | ||
| 205 | subsystem = resp_hdr->subsystem; | ||
| 206 | } | ||
| 207 | |||
| 208 | be_async_cmd_process(adapter, compl, resp_hdr); | ||
| 209 | |||
| 210 | if (base_status != MCC_STATUS_SUCCESS && | ||
| 211 | !be_skip_err_log(opcode, base_status, addl_status)) { | ||
| 212 | |||
| 213 | if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { | ||
| 179 | dev_warn(&adapter->pdev->dev, | 214 | dev_warn(&adapter->pdev->dev, |
| 180 | "VF is not privileged to issue opcode %d-%d\n", | 215 | "VF is not privileged to issue opcode %d-%d\n", |
| 181 | opcode, subsystem); | 216 | opcode, subsystem); |
| 182 | } else { | 217 | } else { |
| 183 | extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & | ||
| 184 | CQE_STATUS_EXTD_MASK; | ||
| 185 | dev_err(&adapter->pdev->dev, | 218 | dev_err(&adapter->pdev->dev, |
| 186 | "opcode %d-%d failed:status %d-%d\n", | 219 | "opcode %d-%d failed:status %d-%d\n", |
| 187 | opcode, subsystem, compl_status, extd_status); | 220 | opcode, subsystem, base_status, addl_status); |
| 188 | |||
| 189 | if (extd_status == MCC_ADDL_STS_INSUFFICIENT_RESOURCES) | ||
| 190 | return extd_status; | ||
| 191 | } | 221 | } |
| 192 | } | 222 | } |
| 193 | done: | 223 | return compl->status; |
| 194 | return compl_status; | ||
| 195 | } | 224 | } |
| 196 | 225 | ||
| 197 | /* Link state evt is a string of bytes; no need for endian swapping */ | 226 | /* Link state evt is a string of bytes; no need for endian swapping */ |
| 198 | static void be_async_link_state_process(struct be_adapter *adapter, | 227 | static void be_async_link_state_process(struct be_adapter *adapter, |
| 199 | struct be_async_event_link_state *evt) | 228 | struct be_mcc_compl *compl) |
| 200 | { | 229 | { |
| 230 | struct be_async_event_link_state *evt = | ||
| 231 | (struct be_async_event_link_state *)compl; | ||
| 232 | |||
| 201 | /* When link status changes, link speed must be re-queried from FW */ | 233 | /* When link status changes, link speed must be re-queried from FW */ |
| 202 | adapter->phy.link_speed = -1; | 234 | adapter->phy.link_speed = -1; |
| 203 | 235 | ||
| @@ -220,10 +252,11 @@ static void be_async_link_state_process(struct be_adapter *adapter, | |||
| 220 | 252 | ||
| 221 | /* Grp5 CoS Priority evt */ | 253 | /* Grp5 CoS Priority evt */ |
| 222 | static void be_async_grp5_cos_priority_process(struct be_adapter *adapter, | 254 | static void be_async_grp5_cos_priority_process(struct be_adapter *adapter, |
| 223 | struct | 255 | struct be_mcc_compl *compl) |
| 224 | be_async_event_grp5_cos_priority | ||
| 225 | *evt) | ||
| 226 | { | 256 | { |
| 257 | struct be_async_event_grp5_cos_priority *evt = | ||
| 258 | (struct be_async_event_grp5_cos_priority *)compl; | ||
| 259 | |||
| 227 | if (evt->valid) { | 260 | if (evt->valid) { |
| 228 | adapter->vlan_prio_bmap = evt->available_priority_bmap; | 261 | adapter->vlan_prio_bmap = evt->available_priority_bmap; |
| 229 | adapter->recommended_prio &= ~VLAN_PRIO_MASK; | 262 | adapter->recommended_prio &= ~VLAN_PRIO_MASK; |
| @@ -234,10 +267,11 @@ static void be_async_grp5_cos_priority_process(struct be_adapter *adapter, | |||
| 234 | 267 | ||
| 235 | /* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */ | 268 | /* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */ |
| 236 | static void be_async_grp5_qos_speed_process(struct be_adapter *adapter, | 269 | static void be_async_grp5_qos_speed_process(struct be_adapter *adapter, |
| 237 | struct | 270 | struct be_mcc_compl *compl) |
| 238 | be_async_event_grp5_qos_link_speed | ||
| 239 | *evt) | ||
| 240 | { | 271 | { |
| 272 | struct be_async_event_grp5_qos_link_speed *evt = | ||
| 273 | (struct be_async_event_grp5_qos_link_speed *)compl; | ||
| 274 | |||
| 241 | if (adapter->phy.link_speed >= 0 && | 275 | if (adapter->phy.link_speed >= 0 && |
| 242 | evt->physical_port == adapter->port_num) | 276 | evt->physical_port == adapter->port_num) |
| 243 | adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10; | 277 | adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10; |
| @@ -245,10 +279,11 @@ static void be_async_grp5_qos_speed_process(struct be_adapter *adapter, | |||
| 245 | 279 | ||
| 246 | /*Grp5 PVID evt*/ | 280 | /*Grp5 PVID evt*/ |
| 247 | static void be_async_grp5_pvid_state_process(struct be_adapter *adapter, | 281 | static void be_async_grp5_pvid_state_process(struct be_adapter *adapter, |
| 248 | struct | 282 | struct be_mcc_compl *compl) |
| 249 | be_async_event_grp5_pvid_state | ||
| 250 | *evt) | ||
| 251 | { | 283 | { |
| 284 | struct be_async_event_grp5_pvid_state *evt = | ||
| 285 | (struct be_async_event_grp5_pvid_state *)compl; | ||
| 286 | |||
| 252 | if (evt->enabled) { | 287 | if (evt->enabled) { |
| 253 | adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK; | 288 | adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK; |
| 254 | dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid); | 289 | dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid); |
| @@ -258,26 +293,21 @@ static void be_async_grp5_pvid_state_process(struct be_adapter *adapter, | |||
| 258 | } | 293 | } |
| 259 | 294 | ||
| 260 | static void be_async_grp5_evt_process(struct be_adapter *adapter, | 295 | static void be_async_grp5_evt_process(struct be_adapter *adapter, |
| 261 | u32 trailer, struct be_mcc_compl *evt) | 296 | struct be_mcc_compl *compl) |
| 262 | { | 297 | { |
| 263 | u8 event_type = 0; | 298 | u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) & |
| 264 | 299 | ASYNC_EVENT_TYPE_MASK; | |
| 265 | event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) & | ||
| 266 | ASYNC_TRAILER_EVENT_TYPE_MASK; | ||
| 267 | 300 | ||
| 268 | switch (event_type) { | 301 | switch (event_type) { |
| 269 | case ASYNC_EVENT_COS_PRIORITY: | 302 | case ASYNC_EVENT_COS_PRIORITY: |
| 270 | be_async_grp5_cos_priority_process(adapter, | 303 | be_async_grp5_cos_priority_process(adapter, compl); |
| 271 | (struct be_async_event_grp5_cos_priority *)evt); | 304 | break; |
| 272 | break; | ||
| 273 | case ASYNC_EVENT_QOS_SPEED: | 305 | case ASYNC_EVENT_QOS_SPEED: |
| 274 | be_async_grp5_qos_speed_process(adapter, | 306 | be_async_grp5_qos_speed_process(adapter, compl); |
| 275 | (struct be_async_event_grp5_qos_link_speed *)evt); | 307 | break; |
| 276 | break; | ||
| 277 | case ASYNC_EVENT_PVID_STATE: | 308 | case ASYNC_EVENT_PVID_STATE: |
| 278 | be_async_grp5_pvid_state_process(adapter, | 309 | be_async_grp5_pvid_state_process(adapter, compl); |
| 279 | (struct be_async_event_grp5_pvid_state *)evt); | 310 | break; |
| 280 | break; | ||
| 281 | default: | 311 | default: |
| 282 | dev_warn(&adapter->pdev->dev, "Unknown grp5 event 0x%x!\n", | 312 | dev_warn(&adapter->pdev->dev, "Unknown grp5 event 0x%x!\n", |
| 283 | event_type); | 313 | event_type); |
| @@ -286,13 +316,13 @@ static void be_async_grp5_evt_process(struct be_adapter *adapter, | |||
| 286 | } | 316 | } |
| 287 | 317 | ||
| 288 | static void be_async_dbg_evt_process(struct be_adapter *adapter, | 318 | static void be_async_dbg_evt_process(struct be_adapter *adapter, |
| 289 | u32 trailer, struct be_mcc_compl *cmp) | 319 | struct be_mcc_compl *cmp) |
| 290 | { | 320 | { |
| 291 | u8 event_type = 0; | 321 | u8 event_type = 0; |
| 292 | struct be_async_event_qnq *evt = (struct be_async_event_qnq *) cmp; | 322 | struct be_async_event_qnq *evt = (struct be_async_event_qnq *) cmp; |
| 293 | 323 | ||
| 294 | event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) & | 324 | event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) & |
| 295 | ASYNC_TRAILER_EVENT_TYPE_MASK; | 325 | ASYNC_EVENT_TYPE_MASK; |
| 296 | 326 | ||
| 297 | switch (event_type) { | 327 | switch (event_type) { |
| 298 | case ASYNC_DEBUG_EVENT_TYPE_QNQ: | 328 | case ASYNC_DEBUG_EVENT_TYPE_QNQ: |
| @@ -307,25 +337,33 @@ static void be_async_dbg_evt_process(struct be_adapter *adapter, | |||
| 307 | } | 337 | } |
| 308 | } | 338 | } |
| 309 | 339 | ||
| 310 | static inline bool is_link_state_evt(u32 trailer) | 340 | static inline bool is_link_state_evt(u32 flags) |
| 311 | { | 341 | { |
| 312 | return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & | 342 | return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == |
| 313 | ASYNC_TRAILER_EVENT_CODE_MASK) == | 343 | ASYNC_EVENT_CODE_LINK_STATE; |
| 314 | ASYNC_EVENT_CODE_LINK_STATE; | ||
| 315 | } | 344 | } |
| 316 | 345 | ||
| 317 | static inline bool is_grp5_evt(u32 trailer) | 346 | static inline bool is_grp5_evt(u32 flags) |
| 318 | { | 347 | { |
| 319 | return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & | 348 | return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == |
| 320 | ASYNC_TRAILER_EVENT_CODE_MASK) == | 349 | ASYNC_EVENT_CODE_GRP_5; |
| 321 | ASYNC_EVENT_CODE_GRP_5); | ||
| 322 | } | 350 | } |
| 323 | 351 | ||
| 324 | static inline bool is_dbg_evt(u32 trailer) | 352 | static inline bool is_dbg_evt(u32 flags) |
| 325 | { | 353 | { |
| 326 | return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & | 354 | return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) == |
| 327 | ASYNC_TRAILER_EVENT_CODE_MASK) == | 355 | ASYNC_EVENT_CODE_QNQ; |
| 328 | ASYNC_EVENT_CODE_QNQ); | 356 | } |
| 357 | |||
| 358 | static void be_mcc_event_process(struct be_adapter *adapter, | ||
| 359 | struct be_mcc_compl *compl) | ||
| 360 | { | ||
| 361 | if (is_link_state_evt(compl->flags)) | ||
| 362 | be_async_link_state_process(adapter, compl); | ||
| 363 | else if (is_grp5_evt(compl->flags)) | ||
| 364 | be_async_grp5_evt_process(adapter, compl); | ||
| 365 | else if (is_dbg_evt(compl->flags)) | ||
| 366 | be_async_dbg_evt_process(adapter, compl); | ||
| 329 | } | 367 | } |
| 330 | 368 | ||
| 331 | static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter) | 369 | static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter) |
| @@ -367,21 +405,13 @@ int be_process_mcc(struct be_adapter *adapter) | |||
| 367 | struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; | 405 | struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; |
| 368 | 406 | ||
| 369 | spin_lock(&adapter->mcc_cq_lock); | 407 | spin_lock(&adapter->mcc_cq_lock); |
| 408 | |||
| 370 | while ((compl = be_mcc_compl_get(adapter))) { | 409 | while ((compl = be_mcc_compl_get(adapter))) { |
| 371 | if (compl->flags & CQE_FLAGS_ASYNC_MASK) { | 410 | if (compl->flags & CQE_FLAGS_ASYNC_MASK) { |
| 372 | /* Interpret flags as an async trailer */ | 411 | be_mcc_event_process(adapter, compl); |
| 373 | if (is_link_state_evt(compl->flags)) | ||
| 374 | be_async_link_state_process(adapter, | ||
| 375 | (struct be_async_event_link_state *) compl); | ||
| 376 | else if (is_grp5_evt(compl->flags)) | ||
| 377 | be_async_grp5_evt_process(adapter, | ||
| 378 | compl->flags, compl); | ||
| 379 | else if (is_dbg_evt(compl->flags)) | ||
| 380 | be_async_dbg_evt_process(adapter, | ||
| 381 | compl->flags, compl); | ||
| 382 | } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { | 412 | } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { |
| 383 | status = be_mcc_compl_process(adapter, compl); | 413 | status = be_mcc_compl_process(adapter, compl); |
| 384 | atomic_dec(&mcc_obj->q.used); | 414 | atomic_dec(&mcc_obj->q.used); |
| 385 | } | 415 | } |
| 386 | be_mcc_compl_use(compl); | 416 | be_mcc_compl_use(compl); |
| 387 | num++; | 417 | num++; |
| @@ -441,7 +471,9 @@ static int be_mcc_notify_wait(struct be_adapter *adapter) | |||
| 441 | if (status == -EIO) | 471 | if (status == -EIO) |
| 442 | goto out; | 472 | goto out; |
| 443 | 473 | ||
| 444 | status = resp->status; | 474 | status = (resp->base_status | |
| 475 | ((resp->addl_status & CQE_ADDL_STATUS_MASK) << | ||
| 476 | CQE_ADDL_STATUS_SHIFT)); | ||
| 445 | out: | 477 | out: |
| 446 | return status; | 478 | return status; |
| 447 | } | 479 | } |
| @@ -2300,7 +2332,7 @@ err_unlock: | |||
| 2300 | } | 2332 | } |
| 2301 | 2333 | ||
| 2302 | int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, | 2334 | int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, |
| 2303 | int offset) | 2335 | u16 optype, int offset) |
| 2304 | { | 2336 | { |
| 2305 | struct be_mcc_wrb *wrb; | 2337 | struct be_mcc_wrb *wrb; |
| 2306 | struct be_cmd_read_flash_crc *req; | 2338 | struct be_cmd_read_flash_crc *req; |
| @@ -2319,7 +2351,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, | |||
| 2319 | OPCODE_COMMON_READ_FLASHROM, sizeof(*req), | 2351 | OPCODE_COMMON_READ_FLASHROM, sizeof(*req), |
| 2320 | wrb, NULL); | 2352 | wrb, NULL); |
| 2321 | 2353 | ||
| 2322 | req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT); | 2354 | req->params.op_type = cpu_to_le32(optype); |
| 2323 | req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); | 2355 | req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); |
| 2324 | req->params.offset = cpu_to_le32(offset); | 2356 | req->params.offset = cpu_to_le32(offset); |
| 2325 | req->params.data_buf_size = cpu_to_le32(0x4); | 2357 | req->params.data_buf_size = cpu_to_le32(0x4); |
| @@ -3562,33 +3594,47 @@ void be_reset_nic_desc(struct be_nic_res_desc *nic) | |||
| 3562 | nic->cq_count = 0xFFFF; | 3594 | nic->cq_count = 0xFFFF; |
| 3563 | nic->toe_conn_count = 0xFFFF; | 3595 | nic->toe_conn_count = 0xFFFF; |
| 3564 | nic->eq_count = 0xFFFF; | 3596 | nic->eq_count = 0xFFFF; |
| 3597 | nic->iface_count = 0xFFFF; | ||
| 3565 | nic->link_param = 0xFF; | 3598 | nic->link_param = 0xFF; |
| 3599 | nic->channel_id_param = cpu_to_le16(0xF000); | ||
| 3566 | nic->acpi_params = 0xFF; | 3600 | nic->acpi_params = 0xFF; |
| 3567 | nic->wol_param = 0x0F; | 3601 | nic->wol_param = 0x0F; |
| 3568 | nic->bw_min = 0xFFFFFFFF; | 3602 | nic->tunnel_iface_count = 0xFFFF; |
| 3603 | nic->direct_tenant_iface_count = 0xFFFF; | ||
| 3569 | nic->bw_max = 0xFFFFFFFF; | 3604 | nic->bw_max = 0xFFFFFFFF; |
| 3570 | } | 3605 | } |
| 3571 | 3606 | ||
| 3572 | int be_cmd_config_qos(struct be_adapter *adapter, u32 bps, u8 domain) | 3607 | int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed, |
| 3608 | u8 domain) | ||
| 3573 | { | 3609 | { |
| 3574 | if (lancer_chip(adapter)) { | 3610 | struct be_nic_res_desc nic_desc; |
| 3575 | struct be_nic_res_desc nic_desc; | 3611 | u32 bw_percent; |
| 3612 | u16 version = 0; | ||
| 3576 | 3613 | ||
| 3577 | be_reset_nic_desc(&nic_desc); | 3614 | if (BE3_chip(adapter)) |
| 3615 | return be_cmd_set_qos(adapter, max_rate / 10, domain); | ||
| 3616 | |||
| 3617 | be_reset_nic_desc(&nic_desc); | ||
| 3618 | nic_desc.pf_num = adapter->pf_number; | ||
| 3619 | nic_desc.vf_num = domain; | ||
| 3620 | if (lancer_chip(adapter)) { | ||
| 3578 | nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0; | 3621 | nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0; |
| 3579 | nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0; | 3622 | nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0; |
| 3580 | nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) | | 3623 | nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) | |
| 3581 | (1 << NOSV_SHIFT); | 3624 | (1 << NOSV_SHIFT); |
| 3582 | nic_desc.pf_num = adapter->pf_number; | 3625 | nic_desc.bw_max = cpu_to_le32(max_rate / 10); |
| 3583 | nic_desc.vf_num = domain; | ||
| 3584 | nic_desc.bw_max = cpu_to_le32(bps); | ||
| 3585 | |||
| 3586 | return be_cmd_set_profile_config(adapter, &nic_desc, | ||
| 3587 | RESOURCE_DESC_SIZE_V0, | ||
| 3588 | 0, domain); | ||
| 3589 | } else { | 3626 | } else { |
| 3590 | return be_cmd_set_qos(adapter, bps, domain); | 3627 | version = 1; |
| 3628 | nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1; | ||
| 3629 | nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1; | ||
| 3630 | nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT); | ||
| 3631 | bw_percent = max_rate ? (max_rate * 100) / link_speed : 100; | ||
| 3632 | nic_desc.bw_max = cpu_to_le32(bw_percent); | ||
| 3591 | } | 3633 | } |
| 3634 | |||
| 3635 | return be_cmd_set_profile_config(adapter, &nic_desc, | ||
| 3636 | nic_desc.hdr.desc_len, | ||
| 3637 | version, domain); | ||
| 3592 | } | 3638 | } |
| 3593 | 3639 | ||
| 3594 | int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op) | 3640 | int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op) |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 228d4b611084..d4616ffb7238 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h | |||
| @@ -50,7 +50,7 @@ struct be_mcc_wrb { | |||
| 50 | #define CQE_FLAGS_CONSUMED_MASK (1 << 27) | 50 | #define CQE_FLAGS_CONSUMED_MASK (1 << 27) |
| 51 | 51 | ||
| 52 | /* Completion Status */ | 52 | /* Completion Status */ |
| 53 | enum { | 53 | enum mcc_base_status { |
| 54 | MCC_STATUS_SUCCESS = 0, | 54 | MCC_STATUS_SUCCESS = 0, |
| 55 | MCC_STATUS_FAILED = 1, | 55 | MCC_STATUS_FAILED = 1, |
| 56 | MCC_STATUS_ILLEGAL_REQUEST = 2, | 56 | MCC_STATUS_ILLEGAL_REQUEST = 2, |
| @@ -60,12 +60,25 @@ enum { | |||
| 60 | MCC_STATUS_NOT_SUPPORTED = 66 | 60 | MCC_STATUS_NOT_SUPPORTED = 66 |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | #define MCC_ADDL_STS_INSUFFICIENT_RESOURCES 0x16 | 63 | /* Additional status */ |
| 64 | enum mcc_addl_status { | ||
| 65 | MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES = 0x16, | ||
| 66 | MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH = 0x4d, | ||
| 67 | MCC_ADDL_STATUS_TOO_MANY_INTERFACES = 0x4a | ||
| 68 | }; | ||
| 69 | |||
| 70 | #define CQE_BASE_STATUS_MASK 0xFFFF | ||
| 71 | #define CQE_BASE_STATUS_SHIFT 0 /* bits 0 - 15 */ | ||
| 72 | #define CQE_ADDL_STATUS_MASK 0xFF | ||
| 73 | #define CQE_ADDL_STATUS_SHIFT 16 /* bits 16 - 31 */ | ||
| 64 | 74 | ||
| 65 | #define CQE_STATUS_COMPL_MASK 0xFFFF | 75 | #define base_status(status) \ |
| 66 | #define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ | 76 | ((enum mcc_base_status) \ |
| 67 | #define CQE_STATUS_EXTD_MASK 0xFFFF | 77 | (status > 0 ? (status & CQE_BASE_STATUS_MASK) : 0)) |
| 68 | #define CQE_STATUS_EXTD_SHIFT 16 /* bits 16 - 31 */ | 78 | #define addl_status(status) \ |
| 79 | ((enum mcc_addl_status) \ | ||
| 80 | (status > 0 ? (status >> CQE_ADDL_STATUS_SHIFT) & \ | ||
| 81 | CQE_ADDL_STATUS_MASK : 0)) | ||
| 69 | 82 | ||
| 70 | struct be_mcc_compl { | 83 | struct be_mcc_compl { |
| 71 | u32 status; /* dword 0 */ | 84 | u32 status; /* dword 0 */ |
| @@ -74,13 +87,13 @@ struct be_mcc_compl { | |||
| 74 | u32 flags; /* dword 3 */ | 87 | u32 flags; /* dword 3 */ |
| 75 | }; | 88 | }; |
| 76 | 89 | ||
| 77 | /* When the async bit of mcc_compl is set, the last 4 bytes of | 90 | /* When the async bit of mcc_compl flags is set, flags |
| 78 | * mcc_compl is interpreted as follows: | 91 | * is interpreted as follows: |
| 79 | */ | 92 | */ |
| 80 | #define ASYNC_TRAILER_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */ | 93 | #define ASYNC_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */ |
| 81 | #define ASYNC_TRAILER_EVENT_CODE_MASK 0xFF | 94 | #define ASYNC_EVENT_CODE_MASK 0xFF |
| 82 | #define ASYNC_TRAILER_EVENT_TYPE_SHIFT 16 | 95 | #define ASYNC_EVENT_TYPE_SHIFT 16 |
| 83 | #define ASYNC_TRAILER_EVENT_TYPE_MASK 0xFF | 96 | #define ASYNC_EVENT_TYPE_MASK 0xFF |
| 84 | #define ASYNC_EVENT_CODE_LINK_STATE 0x1 | 97 | #define ASYNC_EVENT_CODE_LINK_STATE 0x1 |
| 85 | #define ASYNC_EVENT_CODE_GRP_5 0x5 | 98 | #define ASYNC_EVENT_CODE_GRP_5 0x5 |
| 86 | #define ASYNC_EVENT_QOS_SPEED 0x1 | 99 | #define ASYNC_EVENT_QOS_SPEED 0x1 |
| @@ -89,10 +102,6 @@ struct be_mcc_compl { | |||
| 89 | #define ASYNC_EVENT_CODE_QNQ 0x6 | 102 | #define ASYNC_EVENT_CODE_QNQ 0x6 |
| 90 | #define ASYNC_DEBUG_EVENT_TYPE_QNQ 1 | 103 | #define ASYNC_DEBUG_EVENT_TYPE_QNQ 1 |
| 91 | 104 | ||
| 92 | struct be_async_event_trailer { | ||
| 93 | u32 code; | ||
| 94 | }; | ||
| 95 | |||
| 96 | enum { | 105 | enum { |
| 97 | LINK_DOWN = 0x0, | 106 | LINK_DOWN = 0x0, |
| 98 | LINK_UP = 0x1 | 107 | LINK_UP = 0x1 |
| @@ -100,7 +109,7 @@ enum { | |||
| 100 | #define LINK_STATUS_MASK 0x1 | 109 | #define LINK_STATUS_MASK 0x1 |
| 101 | #define LOGICAL_LINK_STATUS_MASK 0x2 | 110 | #define LOGICAL_LINK_STATUS_MASK 0x2 |
| 102 | 111 | ||
| 103 | /* When the event code of an async trailer is link-state, the mcc_compl | 112 | /* When the event code of compl->flags is link-state, the mcc_compl |
| 104 | * must be interpreted as follows | 113 | * must be interpreted as follows |
| 105 | */ | 114 | */ |
| 106 | struct be_async_event_link_state { | 115 | struct be_async_event_link_state { |
| @@ -110,10 +119,10 @@ struct be_async_event_link_state { | |||
| 110 | u8 port_speed; | 119 | u8 port_speed; |
| 111 | u8 port_fault; | 120 | u8 port_fault; |
| 112 | u8 rsvd0[7]; | 121 | u8 rsvd0[7]; |
| 113 | struct be_async_event_trailer trailer; | 122 | u32 flags; |
| 114 | } __packed; | 123 | } __packed; |
| 115 | 124 | ||
| 116 | /* When the event code of an async trailer is GRP-5 and event_type is QOS_SPEED | 125 | /* When the event code of compl->flags is GRP-5 and event_type is QOS_SPEED |
| 117 | * the mcc_compl must be interpreted as follows | 126 | * the mcc_compl must be interpreted as follows |
| 118 | */ | 127 | */ |
| 119 | struct be_async_event_grp5_qos_link_speed { | 128 | struct be_async_event_grp5_qos_link_speed { |
| @@ -121,10 +130,10 @@ struct be_async_event_grp5_qos_link_speed { | |||
| 121 | u8 rsvd[5]; | 130 | u8 rsvd[5]; |
| 122 | u16 qos_link_speed; | 131 | u16 qos_link_speed; |
| 123 | u32 event_tag; | 132 | u32 event_tag; |
| 124 | struct be_async_event_trailer trailer; | 133 | u32 flags; |
| 125 | } __packed; | 134 | } __packed; |
| 126 | 135 | ||
| 127 | /* When the event code of an async trailer is GRP5 and event type is | 136 | /* When the event code of compl->flags is GRP5 and event type is |
| 128 | * CoS-Priority, the mcc_compl must be interpreted as follows | 137 | * CoS-Priority, the mcc_compl must be interpreted as follows |
| 129 | */ | 138 | */ |
| 130 | struct be_async_event_grp5_cos_priority { | 139 | struct be_async_event_grp5_cos_priority { |
| @@ -134,10 +143,10 @@ struct be_async_event_grp5_cos_priority { | |||
| 134 | u8 valid; | 143 | u8 valid; |
| 135 | u8 rsvd0; | 144 | u8 rsvd0; |
| 136 | u8 event_tag; | 145 | u8 event_tag; |
| 137 | struct be_async_event_trailer trailer; | 146 | u32 flags; |
| 138 | } __packed; | 147 | } __packed; |
| 139 | 148 | ||
| 140 | /* When the event code of an async trailer is GRP5 and event type is | 149 | /* When the event code of compl->flags is GRP5 and event type is |
| 141 | * PVID state, the mcc_compl must be interpreted as follows | 150 | * PVID state, the mcc_compl must be interpreted as follows |
| 142 | */ | 151 | */ |
| 143 | struct be_async_event_grp5_pvid_state { | 152 | struct be_async_event_grp5_pvid_state { |
| @@ -146,7 +155,7 @@ struct be_async_event_grp5_pvid_state { | |||
| 146 | u16 tag; | 155 | u16 tag; |
| 147 | u32 event_tag; | 156 | u32 event_tag; |
| 148 | u32 rsvd1; | 157 | u32 rsvd1; |
| 149 | struct be_async_event_trailer trailer; | 158 | u32 flags; |
| 150 | } __packed; | 159 | } __packed; |
| 151 | 160 | ||
| 152 | /* async event indicating outer VLAN tag in QnQ */ | 161 | /* async event indicating outer VLAN tag in QnQ */ |
| @@ -156,7 +165,7 @@ struct be_async_event_qnq { | |||
| 156 | u16 vlan_tag; | 165 | u16 vlan_tag; |
| 157 | u32 event_tag; | 166 | u32 event_tag; |
| 158 | u8 rsvd1[4]; | 167 | u8 rsvd1[4]; |
| 159 | struct be_async_event_trailer trailer; | 168 | u32 flags; |
| 160 | } __packed; | 169 | } __packed; |
| 161 | 170 | ||
| 162 | struct be_mcc_mailbox { | 171 | struct be_mcc_mailbox { |
| @@ -258,8 +267,8 @@ struct be_cmd_resp_hdr { | |||
| 258 | u8 opcode; /* dword 0 */ | 267 | u8 opcode; /* dword 0 */ |
| 259 | u8 subsystem; /* dword 0 */ | 268 | u8 subsystem; /* dword 0 */ |
| 260 | u8 rsvd[2]; /* dword 0 */ | 269 | u8 rsvd[2]; /* dword 0 */ |
| 261 | u8 status; /* dword 1 */ | 270 | u8 base_status; /* dword 1 */ |
| 262 | u8 add_status; /* dword 1 */ | 271 | u8 addl_status; /* dword 1 */ |
| 263 | u8 rsvd1[2]; /* dword 1 */ | 272 | u8 rsvd1[2]; /* dword 1 */ |
| 264 | u32 response_length; /* dword 2 */ | 273 | u32 response_length; /* dword 2 */ |
| 265 | u32 actual_resp_len; /* dword 3 */ | 274 | u32 actual_resp_len; /* dword 3 */ |
| @@ -1186,7 +1195,8 @@ struct be_cmd_read_flash_crc { | |||
| 1186 | struct flashrom_params params; | 1195 | struct flashrom_params params; |
| 1187 | u8 crc[4]; | 1196 | u8 crc[4]; |
| 1188 | u8 rsvd[4]; | 1197 | u8 rsvd[4]; |
| 1189 | }; | 1198 | } __packed; |
| 1199 | |||
| 1190 | /**************** Lancer Firmware Flash ************/ | 1200 | /**************** Lancer Firmware Flash ************/ |
| 1191 | struct amap_lancer_write_obj_context { | 1201 | struct amap_lancer_write_obj_context { |
| 1192 | u8 write_length[24]; | 1202 | u8 write_length[24]; |
| @@ -1891,16 +1901,20 @@ struct be_nic_res_desc { | |||
| 1891 | u16 cq_count; | 1901 | u16 cq_count; |
| 1892 | u16 toe_conn_count; | 1902 | u16 toe_conn_count; |
| 1893 | u16 eq_count; | 1903 | u16 eq_count; |
| 1894 | u32 rsvd5; | 1904 | u16 vlan_id; |
| 1905 | u16 iface_count; | ||
| 1895 | u32 cap_flags; | 1906 | u32 cap_flags; |
| 1896 | u8 link_param; | 1907 | u8 link_param; |
| 1897 | u8 rsvd6[3]; | 1908 | u8 rsvd6; |
| 1909 | u16 channel_id_param; | ||
| 1898 | u32 bw_min; | 1910 | u32 bw_min; |
| 1899 | u32 bw_max; | 1911 | u32 bw_max; |
| 1900 | u8 acpi_params; | 1912 | u8 acpi_params; |
| 1901 | u8 wol_param; | 1913 | u8 wol_param; |
| 1902 | u16 rsvd7; | 1914 | u16 rsvd7; |
| 1903 | u32 rsvd8[7]; | 1915 | u16 tunnel_iface_count; |
| 1916 | u16 direct_tenant_iface_count; | ||
| 1917 | u32 rsvd8[6]; | ||
| 1904 | } __packed; | 1918 | } __packed; |
| 1905 | 1919 | ||
| 1906 | /************ Multi-Channel type ***********/ | 1920 | /************ Multi-Channel type ***********/ |
| @@ -2084,7 +2098,7 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, | |||
| 2084 | u32 data_size, u32 data_offset, const char *obj_name, | 2098 | u32 data_size, u32 data_offset, const char *obj_name, |
| 2085 | u32 *data_read, u32 *eof, u8 *addn_status); | 2099 | u32 *data_read, u32 *eof, u8 *addn_status); |
| 2086 | int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, | 2100 | int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, |
| 2087 | int offset); | 2101 | u16 optype, int offset); |
| 2088 | int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, | 2102 | int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, |
| 2089 | struct be_dma_mem *nonemb_cmd); | 2103 | struct be_dma_mem *nonemb_cmd); |
| 2090 | int be_cmd_fw_init(struct be_adapter *adapter); | 2104 | int be_cmd_fw_init(struct be_adapter *adapter); |
| @@ -2101,7 +2115,8 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter, | |||
| 2101 | int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, | 2115 | int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, |
| 2102 | u8 loopback_type, u8 enable); | 2116 | u8 loopback_type, u8 enable); |
| 2103 | int be_cmd_get_phy_info(struct be_adapter *adapter); | 2117 | int be_cmd_get_phy_info(struct be_adapter *adapter); |
| 2104 | int be_cmd_config_qos(struct be_adapter *adapter, u32 bps, u8 domain); | 2118 | int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, |
| 2119 | u16 link_speed, u8 domain); | ||
| 2105 | void be_detect_error(struct be_adapter *adapter); | 2120 | void be_detect_error(struct be_adapter *adapter); |
| 2106 | int be_cmd_get_die_temperature(struct be_adapter *adapter); | 2121 | int be_cmd_get_die_temperature(struct be_adapter *adapter); |
| 2107 | int be_cmd_get_cntl_attributes(struct be_adapter *adapter); | 2122 | int be_cmd_get_cntl_attributes(struct be_adapter *adapter); |
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h index 3bd198550edb..8840c64aaeca 100644 --- a/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/drivers/net/ethernet/emulex/benet/be_hw.h | |||
| @@ -188,10 +188,14 @@ | |||
| 188 | #define OPTYPE_FCOE_FW_ACTIVE 10 | 188 | #define OPTYPE_FCOE_FW_ACTIVE 10 |
| 189 | #define OPTYPE_FCOE_FW_BACKUP 11 | 189 | #define OPTYPE_FCOE_FW_BACKUP 11 |
| 190 | #define OPTYPE_NCSI_FW 13 | 190 | #define OPTYPE_NCSI_FW 13 |
| 191 | #define OPTYPE_REDBOOT_DIR 18 | ||
| 192 | #define OPTYPE_REDBOOT_CONFIG 19 | ||
| 193 | #define OPTYPE_SH_PHY_FW 21 | ||
| 194 | #define OPTYPE_FLASHISM_JUMPVECTOR 22 | ||
| 195 | #define OPTYPE_UFI_DIR 23 | ||
| 191 | #define OPTYPE_PHY_FW 99 | 196 | #define OPTYPE_PHY_FW 99 |
| 192 | #define TN_8022 13 | 197 | #define TN_8022 13 |
| 193 | 198 | ||
| 194 | #define ILLEGAL_IOCTL_REQ 2 | ||
| 195 | #define FLASHROM_OPER_PHY_FLASH 9 | 199 | #define FLASHROM_OPER_PHY_FLASH 9 |
| 196 | #define FLASHROM_OPER_PHY_SAVE 10 | 200 | #define FLASHROM_OPER_PHY_SAVE 10 |
| 197 | #define FLASHROM_OPER_FLASH 1 | 201 | #define FLASHROM_OPER_FLASH 1 |
| @@ -250,6 +254,9 @@ | |||
| 250 | #define IMAGE_FIRMWARE_BACKUP_FCoE 178 | 254 | #define IMAGE_FIRMWARE_BACKUP_FCoE 178 |
| 251 | #define IMAGE_FIRMWARE_BACKUP_COMP_FCoE 179 | 255 | #define IMAGE_FIRMWARE_BACKUP_COMP_FCoE 179 |
| 252 | #define IMAGE_FIRMWARE_PHY 192 | 256 | #define IMAGE_FIRMWARE_PHY 192 |
| 257 | #define IMAGE_REDBOOT_DIR 208 | ||
| 258 | #define IMAGE_REDBOOT_CONFIG 209 | ||
| 259 | #define IMAGE_UFI_DIR 210 | ||
| 253 | #define IMAGE_BOOT_CODE 224 | 260 | #define IMAGE_BOOT_CODE 224 |
| 254 | 261 | ||
| 255 | /************* Rx Packet Type Encoding **************/ | 262 | /************* Rx Packet Type Encoding **************/ |
| @@ -534,7 +541,8 @@ struct flash_section_entry { | |||
| 534 | u32 image_size; | 541 | u32 image_size; |
| 535 | u32 cksum; | 542 | u32 cksum; |
| 536 | u32 entry_point; | 543 | u32 entry_point; |
| 537 | u32 rsvd0; | 544 | u16 optype; |
| 545 | u16 rsvd0; | ||
| 538 | u32 rsvd1; | 546 | u32 rsvd1; |
| 539 | u8 ver_data[32]; | 547 | u8 ver_data[32]; |
| 540 | } __packed; | 548 | } __packed; |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index e1d445dd8564..6822b3d76d85 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
| @@ -1111,7 +1111,8 @@ static int be_vid_config(struct be_adapter *adapter) | |||
| 1111 | status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num); | 1111 | status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num); |
| 1112 | if (status) { | 1112 | if (status) { |
| 1113 | /* Set to VLAN promisc mode as setting VLAN filter failed */ | 1113 | /* Set to VLAN promisc mode as setting VLAN filter failed */ |
| 1114 | if (status == MCC_ADDL_STS_INSUFFICIENT_RESOURCES) | 1114 | if (addl_status(status) == |
| 1115 | MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES) | ||
| 1115 | goto set_vlan_promisc; | 1116 | goto set_vlan_promisc; |
| 1116 | dev_err(&adapter->pdev->dev, | 1117 | dev_err(&adapter->pdev->dev, |
| 1117 | "Setting HW VLAN filtering failed.\n"); | 1118 | "Setting HW VLAN filtering failed.\n"); |
| @@ -1190,7 +1191,7 @@ ret: | |||
| 1190 | static void be_clear_promisc(struct be_adapter *adapter) | 1191 | static void be_clear_promisc(struct be_adapter *adapter) |
| 1191 | { | 1192 | { |
| 1192 | adapter->promiscuous = false; | 1193 | adapter->promiscuous = false; |
| 1193 | adapter->flags &= ~BE_FLAGS_VLAN_PROMISC; | 1194 | adapter->flags &= ~(BE_FLAGS_VLAN_PROMISC | BE_FLAGS_MCAST_PROMISC); |
| 1194 | 1195 | ||
| 1195 | be_cmd_rx_filter(adapter, IFF_PROMISC, OFF); | 1196 | be_cmd_rx_filter(adapter, IFF_PROMISC, OFF); |
| 1196 | } | 1197 | } |
| @@ -1215,10 +1216,8 @@ static void be_set_rx_mode(struct net_device *netdev) | |||
| 1215 | 1216 | ||
| 1216 | /* Enable multicast promisc if num configured exceeds what we support */ | 1217 | /* Enable multicast promisc if num configured exceeds what we support */ |
| 1217 | if (netdev->flags & IFF_ALLMULTI || | 1218 | if (netdev->flags & IFF_ALLMULTI || |
| 1218 | netdev_mc_count(netdev) > be_max_mc(adapter)) { | 1219 | netdev_mc_count(netdev) > be_max_mc(adapter)) |
| 1219 | be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); | 1220 | goto set_mcast_promisc; |
| 1220 | goto done; | ||
| 1221 | } | ||
| 1222 | 1221 | ||
| 1223 | if (netdev_uc_count(netdev) != adapter->uc_macs) { | 1222 | if (netdev_uc_count(netdev) != adapter->uc_macs) { |
| 1224 | struct netdev_hw_addr *ha; | 1223 | struct netdev_hw_addr *ha; |
| @@ -1244,15 +1243,22 @@ static void be_set_rx_mode(struct net_device *netdev) | |||
| 1244 | } | 1243 | } |
| 1245 | 1244 | ||
| 1246 | status = be_cmd_rx_filter(adapter, IFF_MULTICAST, ON); | 1245 | status = be_cmd_rx_filter(adapter, IFF_MULTICAST, ON); |
| 1247 | 1246 | if (!status) { | |
| 1248 | /* Set to MCAST promisc mode if setting MULTICAST address fails */ | 1247 | if (adapter->flags & BE_FLAGS_MCAST_PROMISC) |
| 1249 | if (status) { | 1248 | adapter->flags &= ~BE_FLAGS_MCAST_PROMISC; |
| 1250 | dev_info(&adapter->pdev->dev, | 1249 | goto done; |
| 1251 | "Exhausted multicast HW filters.\n"); | ||
| 1252 | dev_info(&adapter->pdev->dev, | ||
| 1253 | "Disabling HW multicast filtering.\n"); | ||
| 1254 | be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); | ||
| 1255 | } | 1250 | } |
| 1251 | |||
| 1252 | set_mcast_promisc: | ||
| 1253 | if (adapter->flags & BE_FLAGS_MCAST_PROMISC) | ||
| 1254 | return; | ||
| 1255 | |||
| 1256 | /* Set to MCAST promisc mode if setting MULTICAST address fails | ||
| 1257 | * or if num configured exceeds what we support | ||
| 1258 | */ | ||
| 1259 | status = be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); | ||
| 1260 | if (!status) | ||
| 1261 | adapter->flags |= BE_FLAGS_MCAST_PROMISC; | ||
| 1256 | done: | 1262 | done: |
| 1257 | return; | 1263 | return; |
| 1258 | } | 1264 | } |
| @@ -1347,7 +1353,10 @@ static int be_set_vf_tx_rate(struct net_device *netdev, int vf, | |||
| 1347 | int min_tx_rate, int max_tx_rate) | 1353 | int min_tx_rate, int max_tx_rate) |
| 1348 | { | 1354 | { |
| 1349 | struct be_adapter *adapter = netdev_priv(netdev); | 1355 | struct be_adapter *adapter = netdev_priv(netdev); |
| 1350 | int status = 0; | 1356 | struct device *dev = &adapter->pdev->dev; |
| 1357 | int percent_rate, status = 0; | ||
| 1358 | u16 link_speed = 0; | ||
| 1359 | u8 link_status; | ||
| 1351 | 1360 | ||
| 1352 | if (!sriov_enabled(adapter)) | 1361 | if (!sriov_enabled(adapter)) |
| 1353 | return -EPERM; | 1362 | return -EPERM; |
| @@ -1358,18 +1367,47 @@ static int be_set_vf_tx_rate(struct net_device *netdev, int vf, | |||
| 1358 | if (min_tx_rate) | 1367 | if (min_tx_rate) |
| 1359 | return -EINVAL; | 1368 | return -EINVAL; |
| 1360 | 1369 | ||
| 1361 | if (max_tx_rate < 100 || max_tx_rate > 10000) { | 1370 | if (!max_tx_rate) |
| 1362 | dev_err(&adapter->pdev->dev, | 1371 | goto config_qos; |
| 1363 | "max tx rate must be between 100 and 10000 Mbps\n"); | 1372 | |
| 1364 | return -EINVAL; | 1373 | status = be_cmd_link_status_query(adapter, &link_speed, |
| 1374 | &link_status, 0); | ||
| 1375 | if (status) | ||
| 1376 | goto err; | ||
| 1377 | |||
| 1378 | if (!link_status) { | ||
| 1379 | dev_err(dev, "TX-rate setting not allowed when link is down\n"); | ||
| 1380 | status = -EPERM; | ||
| 1381 | goto err; | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | if (max_tx_rate < 100 || max_tx_rate > link_speed) { | ||
| 1385 | dev_err(dev, "TX-rate must be between 100 and %d Mbps\n", | ||
| 1386 | link_speed); | ||
| 1387 | status = -EINVAL; | ||
| 1388 | goto err; | ||
| 1389 | } | ||
| 1390 | |||
| 1391 | /* On Skyhawk the QOS setting must be done only as a % value */ | ||
| 1392 | percent_rate = link_speed / 100; | ||
| 1393 | if (skyhawk_chip(adapter) && (max_tx_rate % percent_rate)) { | ||
| 1394 | dev_err(dev, "TX-rate must be a multiple of %d Mbps\n", | ||
| 1395 | percent_rate); | ||
| 1396 | status = -EINVAL; | ||
| 1397 | goto err; | ||
| 1365 | } | 1398 | } |
| 1366 | 1399 | ||
| 1367 | status = be_cmd_config_qos(adapter, max_tx_rate / 10, vf + 1); | 1400 | config_qos: |
| 1401 | status = be_cmd_config_qos(adapter, max_tx_rate, link_speed, vf + 1); | ||
| 1368 | if (status) | 1402 | if (status) |
| 1369 | dev_err(&adapter->pdev->dev, | 1403 | goto err; |
| 1370 | "max tx rate %d on VF %d failed\n", max_tx_rate, vf); | 1404 | |
| 1371 | else | 1405 | adapter->vf_cfg[vf].tx_rate = max_tx_rate; |
| 1372 | adapter->vf_cfg[vf].tx_rate = max_tx_rate; | 1406 | return 0; |
| 1407 | |||
| 1408 | err: | ||
| 1409 | dev_err(dev, "TX-rate setting of %dMbps on VF%d failed\n", | ||
| 1410 | max_tx_rate, vf); | ||
| 1373 | return status; | 1411 | return status; |
| 1374 | } | 1412 | } |
| 1375 | static int be_set_vf_link_state(struct net_device *netdev, int vf, | 1413 | static int be_set_vf_link_state(struct net_device *netdev, int vf, |
| @@ -3130,7 +3168,6 @@ static int be_vf_setup(struct be_adapter *adapter) | |||
| 3130 | struct be_vf_cfg *vf_cfg; | 3168 | struct be_vf_cfg *vf_cfg; |
| 3131 | int status, old_vfs, vf; | 3169 | int status, old_vfs, vf; |
| 3132 | u32 privileges; | 3170 | u32 privileges; |
| 3133 | u16 lnk_speed; | ||
| 3134 | 3171 | ||
| 3135 | old_vfs = pci_num_vf(adapter->pdev); | 3172 | old_vfs = pci_num_vf(adapter->pdev); |
| 3136 | if (old_vfs) { | 3173 | if (old_vfs) { |
| @@ -3186,16 +3223,9 @@ static int be_vf_setup(struct be_adapter *adapter) | |||
| 3186 | vf); | 3223 | vf); |
| 3187 | } | 3224 | } |
| 3188 | 3225 | ||
| 3189 | /* BE3 FW, by default, caps VF TX-rate to 100mbps. | 3226 | /* Allow full available bandwidth */ |
| 3190 | * Allow full available bandwidth | 3227 | if (!old_vfs) |
| 3191 | */ | 3228 | be_cmd_config_qos(adapter, 0, 0, vf + 1); |
| 3192 | if (BE3_chip(adapter) && !old_vfs) | ||
| 3193 | be_cmd_config_qos(adapter, 1000, vf + 1); | ||
| 3194 | |||
| 3195 | status = be_cmd_link_status_query(adapter, &lnk_speed, | ||
| 3196 | NULL, vf + 1); | ||
| 3197 | if (!status) | ||
| 3198 | vf_cfg->tx_rate = lnk_speed; | ||
| 3199 | 3229 | ||
| 3200 | if (!old_vfs) { | 3230 | if (!old_vfs) { |
| 3201 | be_cmd_enable_vf(adapter, vf + 1); | 3231 | be_cmd_enable_vf(adapter, vf + 1); |
| @@ -3601,34 +3631,7 @@ static void be_netpoll(struct net_device *netdev) | |||
| 3601 | } | 3631 | } |
| 3602 | #endif | 3632 | #endif |
| 3603 | 3633 | ||
| 3604 | #define FW_FILE_HDR_SIGN "ServerEngines Corp. " | 3634 | static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; |
| 3605 | static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; | ||
| 3606 | |||
| 3607 | static bool be_flash_redboot(struct be_adapter *adapter, | ||
| 3608 | const u8 *p, u32 img_start, int image_size, | ||
| 3609 | int hdr_size) | ||
| 3610 | { | ||
| 3611 | u32 crc_offset; | ||
| 3612 | u8 flashed_crc[4]; | ||
| 3613 | int status; | ||
| 3614 | |||
| 3615 | crc_offset = hdr_size + img_start + image_size - 4; | ||
| 3616 | |||
| 3617 | p += crc_offset; | ||
| 3618 | |||
| 3619 | status = be_cmd_get_flash_crc(adapter, flashed_crc, (image_size - 4)); | ||
| 3620 | if (status) { | ||
| 3621 | dev_err(&adapter->pdev->dev, | ||
| 3622 | "could not get crc from flash, not flashing redboot\n"); | ||
| 3623 | return false; | ||
| 3624 | } | ||
| 3625 | |||
| 3626 | /*update redboot only if crc does not match*/ | ||
| 3627 | if (!memcmp(flashed_crc, p, 4)) | ||
| 3628 | return false; | ||
| 3629 | else | ||
| 3630 | return true; | ||
| 3631 | } | ||
| 3632 | 3635 | ||
| 3633 | static bool phy_flashing_required(struct be_adapter *adapter) | 3636 | static bool phy_flashing_required(struct be_adapter *adapter) |
| 3634 | { | 3637 | { |
| @@ -3675,12 +3678,35 @@ static struct flash_section_info *get_fsec_info(struct be_adapter *adapter, | |||
| 3675 | return NULL; | 3678 | return NULL; |
| 3676 | } | 3679 | } |
| 3677 | 3680 | ||
| 3681 | static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p, | ||
| 3682 | u32 img_offset, u32 img_size, int hdr_size, | ||
| 3683 | u16 img_optype, bool *crc_match) | ||
| 3684 | { | ||
| 3685 | u32 crc_offset; | ||
| 3686 | int status; | ||
| 3687 | u8 crc[4]; | ||
| 3688 | |||
| 3689 | status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_size - 4); | ||
| 3690 | if (status) | ||
| 3691 | return status; | ||
| 3692 | |||
| 3693 | crc_offset = hdr_size + img_offset + img_size - 4; | ||
| 3694 | |||
| 3695 | /* Skip flashing, if crc of flashed region matches */ | ||
| 3696 | if (!memcmp(crc, p + crc_offset, 4)) | ||
| 3697 | *crc_match = true; | ||
| 3698 | else | ||
| 3699 | *crc_match = false; | ||
| 3700 | |||
| 3701 | return status; | ||
| 3702 | } | ||
| 3703 | |||
| 3678 | static int be_flash(struct be_adapter *adapter, const u8 *img, | 3704 | static int be_flash(struct be_adapter *adapter, const u8 *img, |
| 3679 | struct be_dma_mem *flash_cmd, int optype, int img_size) | 3705 | struct be_dma_mem *flash_cmd, int optype, int img_size) |
| 3680 | { | 3706 | { |
| 3681 | u32 total_bytes = 0, flash_op, num_bytes = 0; | ||
| 3682 | int status = 0; | ||
| 3683 | struct be_cmd_write_flashrom *req = flash_cmd->va; | 3707 | struct be_cmd_write_flashrom *req = flash_cmd->va; |
| 3708 | u32 total_bytes, flash_op, num_bytes; | ||
| 3709 | int status; | ||
| 3684 | 3710 | ||
| 3685 | total_bytes = img_size; | 3711 | total_bytes = img_size; |
| 3686 | while (total_bytes) { | 3712 | while (total_bytes) { |
| @@ -3704,14 +3730,11 @@ static int be_flash(struct be_adapter *adapter, const u8 *img, | |||
| 3704 | img += num_bytes; | 3730 | img += num_bytes; |
| 3705 | status = be_cmd_write_flashrom(adapter, flash_cmd, optype, | 3731 | status = be_cmd_write_flashrom(adapter, flash_cmd, optype, |
| 3706 | flash_op, num_bytes); | 3732 | flash_op, num_bytes); |
| 3707 | if (status) { | 3733 | if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST && |
| 3708 | if (status == ILLEGAL_IOCTL_REQ && | 3734 | optype == OPTYPE_PHY_FW) |
| 3709 | optype == OPTYPE_PHY_FW) | 3735 | break; |
| 3710 | break; | 3736 | else if (status) |
| 3711 | dev_err(&adapter->pdev->dev, | ||
| 3712 | "cmd to write to flash rom failed.\n"); | ||
| 3713 | return status; | 3737 | return status; |
| 3714 | } | ||
| 3715 | } | 3738 | } |
| 3716 | return 0; | 3739 | return 0; |
| 3717 | } | 3740 | } |
| @@ -3721,12 +3744,13 @@ static int be_flash_BEx(struct be_adapter *adapter, | |||
| 3721 | const struct firmware *fw, | 3744 | const struct firmware *fw, |
| 3722 | struct be_dma_mem *flash_cmd, int num_of_images) | 3745 | struct be_dma_mem *flash_cmd, int num_of_images) |
| 3723 | { | 3746 | { |
| 3724 | int status = 0, i, filehdr_size = 0; | ||
| 3725 | int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); | 3747 | int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); |
| 3726 | const u8 *p = fw->data; | 3748 | struct device *dev = &adapter->pdev->dev; |
| 3727 | const struct flash_comp *pflashcomp; | ||
| 3728 | int num_comp, redboot; | ||
| 3729 | struct flash_section_info *fsec = NULL; | 3749 | struct flash_section_info *fsec = NULL; |
| 3750 | int status, i, filehdr_size, num_comp; | ||
| 3751 | const struct flash_comp *pflashcomp; | ||
| 3752 | bool crc_match; | ||
| 3753 | const u8 *p; | ||
| 3730 | 3754 | ||
| 3731 | struct flash_comp gen3_flash_types[] = { | 3755 | struct flash_comp gen3_flash_types[] = { |
| 3732 | { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE, | 3756 | { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE, |
| @@ -3783,8 +3807,7 @@ static int be_flash_BEx(struct be_adapter *adapter, | |||
| 3783 | /* Get flash section info*/ | 3807 | /* Get flash section info*/ |
| 3784 | fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); | 3808 | fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); |
| 3785 | if (!fsec) { | 3809 | if (!fsec) { |
| 3786 | dev_err(&adapter->pdev->dev, | 3810 | dev_err(dev, "Invalid Cookie. FW image may be corrupted\n"); |
| 3787 | "Invalid Cookie. UFI corrupted ?\n"); | ||
| 3788 | return -1; | 3811 | return -1; |
| 3789 | } | 3812 | } |
| 3790 | for (i = 0; i < num_comp; i++) { | 3813 | for (i = 0; i < num_comp; i++) { |
| @@ -3800,25 +3823,32 @@ static int be_flash_BEx(struct be_adapter *adapter, | |||
| 3800 | continue; | 3823 | continue; |
| 3801 | 3824 | ||
| 3802 | if (pflashcomp[i].optype == OPTYPE_REDBOOT) { | 3825 | if (pflashcomp[i].optype == OPTYPE_REDBOOT) { |
| 3803 | redboot = be_flash_redboot(adapter, fw->data, | 3826 | status = be_check_flash_crc(adapter, fw->data, |
| 3804 | pflashcomp[i].offset, | 3827 | pflashcomp[i].offset, |
| 3805 | pflashcomp[i].size, | 3828 | pflashcomp[i].size, |
| 3806 | filehdr_size + | 3829 | filehdr_size + |
| 3807 | img_hdrs_size); | 3830 | img_hdrs_size, |
| 3808 | if (!redboot) | 3831 | OPTYPE_REDBOOT, &crc_match); |
| 3832 | if (status) { | ||
| 3833 | dev_err(dev, | ||
| 3834 | "Could not get CRC for 0x%x region\n", | ||
| 3835 | pflashcomp[i].optype); | ||
| 3836 | continue; | ||
| 3837 | } | ||
| 3838 | |||
| 3839 | if (crc_match) | ||
| 3809 | continue; | 3840 | continue; |
| 3810 | } | 3841 | } |
| 3811 | 3842 | ||
| 3812 | p = fw->data; | 3843 | p = fw->data + filehdr_size + pflashcomp[i].offset + |
| 3813 | p += filehdr_size + pflashcomp[i].offset + img_hdrs_size; | 3844 | img_hdrs_size; |
| 3814 | if (p + pflashcomp[i].size > fw->data + fw->size) | 3845 | if (p + pflashcomp[i].size > fw->data + fw->size) |
| 3815 | return -1; | 3846 | return -1; |
| 3816 | 3847 | ||
| 3817 | status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype, | 3848 | status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype, |
| 3818 | pflashcomp[i].size); | 3849 | pflashcomp[i].size); |
| 3819 | if (status) { | 3850 | if (status) { |
| 3820 | dev_err(&adapter->pdev->dev, | 3851 | dev_err(dev, "Flashing section type 0x%x failed\n", |
| 3821 | "Flashing section type %d failed.\n", | ||
| 3822 | pflashcomp[i].img_type); | 3852 | pflashcomp[i].img_type); |
| 3823 | return status; | 3853 | return status; |
| 3824 | } | 3854 | } |
| @@ -3826,74 +3856,135 @@ static int be_flash_BEx(struct be_adapter *adapter, | |||
| 3826 | return 0; | 3856 | return 0; |
| 3827 | } | 3857 | } |
| 3828 | 3858 | ||
| 3859 | static u16 be_get_img_optype(struct flash_section_entry fsec_entry) | ||
| 3860 | { | ||
| 3861 | u32 img_type = le32_to_cpu(fsec_entry.type); | ||
| 3862 | u16 img_optype = le16_to_cpu(fsec_entry.optype); | ||
| 3863 | |||
| 3864 | if (img_optype != 0xFFFF) | ||
| 3865 | return img_optype; | ||
| 3866 | |||
| 3867 | switch (img_type) { | ||
| 3868 | case IMAGE_FIRMWARE_iSCSI: | ||
| 3869 | img_optype = OPTYPE_ISCSI_ACTIVE; | ||
| 3870 | break; | ||
| 3871 | case IMAGE_BOOT_CODE: | ||
| 3872 | img_optype = OPTYPE_REDBOOT; | ||
| 3873 | break; | ||
| 3874 | case IMAGE_OPTION_ROM_ISCSI: | ||
| 3875 | img_optype = OPTYPE_BIOS; | ||
| 3876 | break; | ||
| 3877 | case IMAGE_OPTION_ROM_PXE: | ||
| 3878 | img_optype = OPTYPE_PXE_BIOS; | ||
| 3879 | break; | ||
| 3880 | case IMAGE_OPTION_ROM_FCoE: | ||
| 3881 | img_optype = OPTYPE_FCOE_BIOS; | ||
| 3882 | break; | ||
| 3883 | case IMAGE_FIRMWARE_BACKUP_iSCSI: | ||
| 3884 | img_optype = OPTYPE_ISCSI_BACKUP; | ||
| 3885 | break; | ||
| 3886 | case IMAGE_NCSI: | ||
| 3887 | img_optype = OPTYPE_NCSI_FW; | ||
| 3888 | break; | ||
| 3889 | case IMAGE_FLASHISM_JUMPVECTOR: | ||
| 3890 | img_optype = OPTYPE_FLASHISM_JUMPVECTOR; | ||
| 3891 | break; | ||
| 3892 | case IMAGE_FIRMWARE_PHY: | ||
| 3893 | img_optype = OPTYPE_SH_PHY_FW; | ||
| 3894 | break; | ||
| 3895 | case IMAGE_REDBOOT_DIR: | ||
| 3896 | img_optype = OPTYPE_REDBOOT_DIR; | ||
| 3897 | break; | ||
| 3898 | case IMAGE_REDBOOT_CONFIG: | ||
| 3899 | img_optype = OPTYPE_REDBOOT_CONFIG; | ||
| 3900 | break; | ||
| 3901 | case IMAGE_UFI_DIR: | ||
| 3902 | img_optype = OPTYPE_UFI_DIR; | ||
| 3903 | break; | ||
| 3904 | default: | ||
| 3905 | break; | ||
| 3906 | } | ||
| 3907 | |||
| 3908 | return img_optype; | ||
| 3909 | } | ||
| 3910 | |||
| 3829 | static int be_flash_skyhawk(struct be_adapter *adapter, | 3911 | static int be_flash_skyhawk(struct be_adapter *adapter, |
| 3830 | const struct firmware *fw, | 3912 | const struct firmware *fw, |
| 3831 | struct be_dma_mem *flash_cmd, int num_of_images) | 3913 | struct be_dma_mem *flash_cmd, int num_of_images) |
| 3832 | { | 3914 | { |
| 3833 | int status = 0, i, filehdr_size = 0; | ||
| 3834 | int img_offset, img_size, img_optype, redboot; | ||
| 3835 | int img_hdrs_size = num_of_images * sizeof(struct image_hdr); | 3915 | int img_hdrs_size = num_of_images * sizeof(struct image_hdr); |
| 3836 | const u8 *p = fw->data; | 3916 | struct device *dev = &adapter->pdev->dev; |
| 3837 | struct flash_section_info *fsec = NULL; | 3917 | struct flash_section_info *fsec = NULL; |
| 3918 | u32 img_offset, img_size, img_type; | ||
| 3919 | int status, i, filehdr_size; | ||
| 3920 | bool crc_match, old_fw_img; | ||
| 3921 | u16 img_optype; | ||
| 3922 | const u8 *p; | ||
| 3838 | 3923 | ||
| 3839 | filehdr_size = sizeof(struct flash_file_hdr_g3); | 3924 | filehdr_size = sizeof(struct flash_file_hdr_g3); |
| 3840 | fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); | 3925 | fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); |
| 3841 | if (!fsec) { | 3926 | if (!fsec) { |
| 3842 | dev_err(&adapter->pdev->dev, | 3927 | dev_err(dev, "Invalid Cookie. FW image may be corrupted\n"); |
| 3843 | "Invalid Cookie. UFI corrupted ?\n"); | ||
| 3844 | return -1; | 3928 | return -1; |
| 3845 | } | 3929 | } |
| 3846 | 3930 | ||
| 3847 | for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) { | 3931 | for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) { |
| 3848 | img_offset = le32_to_cpu(fsec->fsec_entry[i].offset); | 3932 | img_offset = le32_to_cpu(fsec->fsec_entry[i].offset); |
| 3849 | img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size); | 3933 | img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size); |
| 3934 | img_type = le32_to_cpu(fsec->fsec_entry[i].type); | ||
| 3935 | img_optype = be_get_img_optype(fsec->fsec_entry[i]); | ||
| 3936 | old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF; | ||
| 3850 | 3937 | ||
| 3851 | switch (le32_to_cpu(fsec->fsec_entry[i].type)) { | 3938 | if (img_optype == 0xFFFF) |
| 3852 | case IMAGE_FIRMWARE_iSCSI: | ||
| 3853 | img_optype = OPTYPE_ISCSI_ACTIVE; | ||
| 3854 | break; | ||
| 3855 | case IMAGE_BOOT_CODE: | ||
| 3856 | img_optype = OPTYPE_REDBOOT; | ||
| 3857 | break; | ||
| 3858 | case IMAGE_OPTION_ROM_ISCSI: | ||
| 3859 | img_optype = OPTYPE_BIOS; | ||
| 3860 | break; | ||
| 3861 | case IMAGE_OPTION_ROM_PXE: | ||
| 3862 | img_optype = OPTYPE_PXE_BIOS; | ||
| 3863 | break; | ||
| 3864 | case IMAGE_OPTION_ROM_FCoE: | ||
| 3865 | img_optype = OPTYPE_FCOE_BIOS; | ||
| 3866 | break; | ||
| 3867 | case IMAGE_FIRMWARE_BACKUP_iSCSI: | ||
| 3868 | img_optype = OPTYPE_ISCSI_BACKUP; | ||
| 3869 | break; | ||
| 3870 | case IMAGE_NCSI: | ||
| 3871 | img_optype = OPTYPE_NCSI_FW; | ||
| 3872 | break; | ||
| 3873 | default: | ||
| 3874 | continue; | 3939 | continue; |
| 3940 | /* Don't bother verifying CRC if an old FW image is being | ||
| 3941 | * flashed | ||
| 3942 | */ | ||
| 3943 | if (old_fw_img) | ||
| 3944 | goto flash; | ||
| 3945 | |||
| 3946 | status = be_check_flash_crc(adapter, fw->data, img_offset, | ||
| 3947 | img_size, filehdr_size + | ||
| 3948 | img_hdrs_size, img_optype, | ||
| 3949 | &crc_match); | ||
| 3950 | /* The current FW image on the card does not recognize the new | ||
| 3951 | * FLASH op_type. The FW download is partially complete. | ||
| 3952 | * Reboot the server now to enable FW image to recognize the | ||
| 3953 | * new FLASH op_type. To complete the remaining process, | ||
| 3954 | * download the same FW again after the reboot. | ||
| 3955 | */ | ||
| 3956 | if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST || | ||
| 3957 | base_status(status) == MCC_STATUS_ILLEGAL_FIELD) { | ||
| 3958 | dev_err(dev, "Flash incomplete. Reset the server\n"); | ||
| 3959 | dev_err(dev, "Download FW image again after reset\n"); | ||
| 3960 | return -EAGAIN; | ||
| 3961 | } else if (status) { | ||
| 3962 | dev_err(dev, "Could not get CRC for 0x%x region\n", | ||
| 3963 | img_optype); | ||
| 3964 | return -EFAULT; | ||
| 3875 | } | 3965 | } |
| 3876 | 3966 | ||
| 3877 | if (img_optype == OPTYPE_REDBOOT) { | 3967 | if (crc_match) |
| 3878 | redboot = be_flash_redboot(adapter, fw->data, | 3968 | continue; |
| 3879 | img_offset, img_size, | ||
| 3880 | filehdr_size + | ||
| 3881 | img_hdrs_size); | ||
| 3882 | if (!redboot) | ||
| 3883 | continue; | ||
| 3884 | } | ||
| 3885 | 3969 | ||
| 3886 | p = fw->data; | 3970 | flash: |
| 3887 | p += filehdr_size + img_offset + img_hdrs_size; | 3971 | p = fw->data + filehdr_size + img_offset + img_hdrs_size; |
| 3888 | if (p + img_size > fw->data + fw->size) | 3972 | if (p + img_size > fw->data + fw->size) |
| 3889 | return -1; | 3973 | return -1; |
| 3890 | 3974 | ||
| 3891 | status = be_flash(adapter, p, flash_cmd, img_optype, img_size); | 3975 | status = be_flash(adapter, p, flash_cmd, img_optype, img_size); |
| 3892 | if (status) { | 3976 | /* For old FW images ignore ILLEGAL_FIELD error or errors on |
| 3893 | dev_err(&adapter->pdev->dev, | 3977 | * UFI_DIR region |
| 3894 | "Flashing section type %d failed.\n", | 3978 | */ |
| 3895 | fsec->fsec_entry[i].type); | 3979 | if (old_fw_img && |
| 3896 | return status; | 3980 | (base_status(status) == MCC_STATUS_ILLEGAL_FIELD || |
| 3981 | (img_optype == OPTYPE_UFI_DIR && | ||
| 3982 | base_status(status) == MCC_STATUS_FAILED))) { | ||
| 3983 | continue; | ||
| 3984 | } else if (status) { | ||
| 3985 | dev_err(dev, "Flashing section type 0x%x failed\n", | ||
| 3986 | img_type); | ||
| 3987 | return -EFAULT; | ||
| 3897 | } | 3988 | } |
| 3898 | } | 3989 | } |
| 3899 | return 0; | 3990 | return 0; |
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index cb5c987bee39..4d989b2df420 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c | |||
| @@ -1816,6 +1816,7 @@ fec_enet_open(struct net_device *ndev) | |||
| 1816 | struct fec_enet_private *fep = netdev_priv(ndev); | 1816 | struct fec_enet_private *fep = netdev_priv(ndev); |
| 1817 | int ret; | 1817 | int ret; |
| 1818 | 1818 | ||
| 1819 | pinctrl_pm_select_default_state(&fep->pdev->dev); | ||
| 1819 | ret = fec_enet_clk_enable(ndev, true); | 1820 | ret = fec_enet_clk_enable(ndev, true); |
| 1820 | if (ret) | 1821 | if (ret) |
| 1821 | return ret; | 1822 | return ret; |
| @@ -1859,6 +1860,7 @@ fec_enet_close(struct net_device *ndev) | |||
| 1859 | } | 1860 | } |
| 1860 | 1861 | ||
| 1861 | fec_enet_clk_enable(ndev, false); | 1862 | fec_enet_clk_enable(ndev, false); |
| 1863 | pinctrl_pm_select_sleep_state(&fep->pdev->dev); | ||
| 1862 | fec_enet_free_buffers(ndev); | 1864 | fec_enet_free_buffers(ndev); |
| 1863 | 1865 | ||
| 1864 | return 0; | 1866 | return 0; |
| @@ -2162,6 +2164,9 @@ fec_probe(struct platform_device *pdev) | |||
| 2162 | fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG; | 2164 | fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG; |
| 2163 | #endif | 2165 | #endif |
| 2164 | 2166 | ||
| 2167 | /* Select default pin state */ | ||
| 2168 | pinctrl_pm_select_default_state(&pdev->dev); | ||
| 2169 | |||
| 2165 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2170 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 2166 | fep->hwp = devm_ioremap_resource(&pdev->dev, r); | 2171 | fep->hwp = devm_ioremap_resource(&pdev->dev, r); |
| 2167 | if (IS_ERR(fep->hwp)) { | 2172 | if (IS_ERR(fep->hwp)) { |
| @@ -2258,6 +2263,7 @@ fec_probe(struct platform_device *pdev) | |||
| 2258 | /* Carrier starts down, phylib will bring it up */ | 2263 | /* Carrier starts down, phylib will bring it up */ |
| 2259 | netif_carrier_off(ndev); | 2264 | netif_carrier_off(ndev); |
| 2260 | fec_enet_clk_enable(ndev, false); | 2265 | fec_enet_clk_enable(ndev, false); |
| 2266 | pinctrl_pm_select_sleep_state(&pdev->dev); | ||
| 2261 | 2267 | ||
| 2262 | ret = register_netdev(ndev); | 2268 | ret = register_netdev(ndev); |
| 2263 | if (ret) | 2269 | if (ret) |
| @@ -2317,6 +2323,7 @@ fec_suspend(struct device *dev) | |||
| 2317 | netif_device_detach(ndev); | 2323 | netif_device_detach(ndev); |
| 2318 | } | 2324 | } |
| 2319 | fec_enet_clk_enable(ndev, false); | 2325 | fec_enet_clk_enable(ndev, false); |
| 2326 | pinctrl_pm_select_sleep_state(&fep->pdev->dev); | ||
| 2320 | 2327 | ||
| 2321 | if (fep->reg_phy) | 2328 | if (fep->reg_phy) |
| 2322 | regulator_disable(fep->reg_phy); | 2329 | regulator_disable(fep->reg_phy); |
| @@ -2337,6 +2344,7 @@ fec_resume(struct device *dev) | |||
| 2337 | return ret; | 2344 | return ret; |
| 2338 | } | 2345 | } |
| 2339 | 2346 | ||
| 2347 | pinctrl_pm_select_default_state(&fep->pdev->dev); | ||
| 2340 | ret = fec_enet_clk_enable(ndev, true); | 2348 | ret = fec_enet_clk_enable(ndev, true); |
| 2341 | if (ret) | 2349 | if (ret) |
| 2342 | goto failed_clk; | 2350 | goto failed_clk; |
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 538903bf13bc..a0b418e007a0 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | 28 | ||
| 29 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 29 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 30 | 30 | ||
| 31 | #include <linux/device.h> | ||
| 31 | #include <linux/in.h> | 32 | #include <linux/in.h> |
| 32 | #include <linux/ip.h> | 33 | #include <linux/ip.h> |
| 33 | #include <linux/tcp.h> | 34 | #include <linux/tcp.h> |
| @@ -3273,7 +3274,7 @@ static int ehea_probe_adapter(struct platform_device *dev) | |||
| 3273 | return -EINVAL; | 3274 | return -EINVAL; |
| 3274 | } | 3275 | } |
| 3275 | 3276 | ||
| 3276 | adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); | 3277 | adapter = devm_kzalloc(&dev->dev, sizeof(*adapter), GFP_KERNEL); |
| 3277 | if (!adapter) { | 3278 | if (!adapter) { |
| 3278 | ret = -ENOMEM; | 3279 | ret = -ENOMEM; |
| 3279 | dev_err(&dev->dev, "no mem for ehea_adapter\n"); | 3280 | dev_err(&dev->dev, "no mem for ehea_adapter\n"); |
| @@ -3359,7 +3360,6 @@ out_kill_eq: | |||
| 3359 | 3360 | ||
| 3360 | out_free_ad: | 3361 | out_free_ad: |
| 3361 | list_del(&adapter->list); | 3362 | list_del(&adapter->list); |
| 3362 | kfree(adapter); | ||
| 3363 | 3363 | ||
| 3364 | out: | 3364 | out: |
| 3365 | ehea_update_firmware_handles(); | 3365 | ehea_update_firmware_handles(); |
| @@ -3386,7 +3386,6 @@ static int ehea_remove(struct platform_device *dev) | |||
| 3386 | ehea_destroy_eq(adapter->neq); | 3386 | ehea_destroy_eq(adapter->neq); |
| 3387 | ehea_remove_adapter_mr(adapter); | 3387 | ehea_remove_adapter_mr(adapter); |
| 3388 | list_del(&adapter->list); | 3388 | list_del(&adapter->list); |
| 3389 | kfree(adapter); | ||
| 3390 | 3389 | ||
| 3391 | ehea_update_firmware_handles(); | 3390 | ehea_update_firmware_handles(); |
| 3392 | 3391 | ||
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 7e1c91d41a87..5eca9bb185a0 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c | |||
| @@ -2192,7 +2192,6 @@ static void tile_net_dev_init(const char *name, const uint8_t *mac) | |||
| 2192 | { | 2192 | { |
| 2193 | int ret; | 2193 | int ret; |
| 2194 | int i; | 2194 | int i; |
| 2195 | int nz_addr = 0; | ||
| 2196 | struct net_device *dev; | 2195 | struct net_device *dev; |
| 2197 | struct tile_net_priv *priv; | 2196 | struct tile_net_priv *priv; |
| 2198 | 2197 | ||
| @@ -2212,7 +2211,6 @@ static void tile_net_dev_init(const char *name, const uint8_t *mac) | |||
| 2212 | 2211 | ||
| 2213 | /* Initialize "priv". */ | 2212 | /* Initialize "priv". */ |
| 2214 | priv = netdev_priv(dev); | 2213 | priv = netdev_priv(dev); |
| 2215 | memset(priv, 0, sizeof(*priv)); | ||
| 2216 | priv->dev = dev; | 2214 | priv->dev = dev; |
| 2217 | priv->channel = -1; | 2215 | priv->channel = -1; |
| 2218 | priv->loopify_channel = -1; | 2216 | priv->loopify_channel = -1; |
| @@ -2223,15 +2221,10 @@ static void tile_net_dev_init(const char *name, const uint8_t *mac) | |||
| 2223 | * be done before the device is opened. If the MAC is all zeroes, | 2221 | * be done before the device is opened. If the MAC is all zeroes, |
| 2224 | * we use a random address, since we're probably on the simulator. | 2222 | * we use a random address, since we're probably on the simulator. |
| 2225 | */ | 2223 | */ |
| 2226 | for (i = 0; i < 6; i++) | 2224 | if (!is_zero_ether_addr(mac)) |
| 2227 | nz_addr |= mac[i]; | 2225 | ether_addr_copy(dev->dev_addr, mac); |
| 2228 | 2226 | else | |
| 2229 | if (nz_addr) { | ||
| 2230 | memcpy(dev->dev_addr, mac, ETH_ALEN); | ||
| 2231 | dev->addr_len = 6; | ||
| 2232 | } else { | ||
| 2233 | eth_hw_addr_random(dev); | 2227 | eth_hw_addr_random(dev); |
| 2234 | } | ||
| 2235 | 2228 | ||
| 2236 | /* Register the network device. */ | 2229 | /* Register the network device. */ |
| 2237 | ret = register_netdev(dev); | 2230 | ret = register_netdev(dev); |
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index a6284964b711..2e58aa54484c 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
| @@ -300,6 +300,12 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) | |||
| 300 | if (IS_ERR(phydev) || phydev == NULL) | 300 | if (IS_ERR(phydev) || phydev == NULL) |
| 301 | return phydev; | 301 | return phydev; |
| 302 | 302 | ||
| 303 | /* | ||
| 304 | * For DT, see if the auto-probed phy has a correspoding child | ||
| 305 | * in the bus node, and set the of_node pointer in this case. | ||
| 306 | */ | ||
| 307 | of_mdiobus_link_phydev(bus, phydev); | ||
| 308 | |||
| 303 | err = phy_device_register(phydev); | 309 | err = phy_device_register(phydev); |
| 304 | if (err) { | 310 | if (err) { |
| 305 | phy_device_free(phydev); | 311 | phy_device_free(phydev); |
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 9f91c7aba4b0..25431965a625 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c | |||
| @@ -630,12 +630,10 @@ int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) | |||
| 630 | int ret; | 630 | int ret; |
| 631 | void *tmp; | 631 | void *tmp; |
| 632 | 632 | ||
| 633 | tmp = kmalloc(size, GFP_KERNEL); | 633 | tmp = kmemdup(data, size, GFP_KERNEL); |
| 634 | if (!tmp) | 634 | if (!tmp) |
| 635 | return -ENOMEM; | 635 | return -ENOMEM; |
| 636 | 636 | ||
| 637 | memcpy(tmp, data, size); | ||
| 638 | |||
| 639 | ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0), | 637 | ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0), |
| 640 | RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, | 638 | RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, |
| 641 | value, index, tmp, size, 500); | 639 | value, index, tmp, size, 500); |
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 6abde37fb339..75b3dfbd6509 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
| @@ -680,8 +680,8 @@ static void ath10k_core_restart(struct work_struct *work) | |||
| 680 | 680 | ||
| 681 | switch (ar->state) { | 681 | switch (ar->state) { |
| 682 | case ATH10K_STATE_ON: | 682 | case ATH10K_STATE_ON: |
| 683 | ath10k_halt(ar); | ||
| 684 | ar->state = ATH10K_STATE_RESTARTING; | 683 | ar->state = ATH10K_STATE_RESTARTING; |
| 684 | ath10k_halt(ar); | ||
| 685 | ieee80211_restart_hw(ar->hw); | 685 | ieee80211_restart_hw(ar->hw); |
| 686 | break; | 686 | break; |
| 687 | case ATH10K_STATE_OFF: | 687 | case ATH10K_STATE_OFF: |
| @@ -908,7 +908,9 @@ void ath10k_core_stop(struct ath10k *ar) | |||
| 908 | lockdep_assert_held(&ar->conf_mutex); | 908 | lockdep_assert_held(&ar->conf_mutex); |
| 909 | 909 | ||
| 910 | /* try to suspend target */ | 910 | /* try to suspend target */ |
| 911 | ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR); | 911 | if (ar->state != ATH10K_STATE_RESTARTING) |
| 912 | ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR); | ||
| 913 | |||
| 912 | ath10k_debug_stop(ar); | 914 | ath10k_debug_stop(ar); |
| 913 | ath10k_htc_stop(&ar->htc); | 915 | ath10k_htc_stop(&ar->htc); |
| 914 | ath10k_htt_detach(&ar->htt); | 916 | ath10k_htt_detach(&ar->htt); |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0ac5437492fd..7026f021ccbb 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
| @@ -2291,6 +2291,8 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
| 2291 | */ | 2291 | */ |
| 2292 | void ath10k_halt(struct ath10k *ar) | 2292 | void ath10k_halt(struct ath10k *ar) |
| 2293 | { | 2293 | { |
| 2294 | struct ath10k_vif *arvif; | ||
| 2295 | |||
| 2294 | lockdep_assert_held(&ar->conf_mutex); | 2296 | lockdep_assert_held(&ar->conf_mutex); |
| 2295 | 2297 | ||
| 2296 | if (ath10k_monitor_is_enabled(ar)) { | 2298 | if (ath10k_monitor_is_enabled(ar)) { |
| @@ -2313,6 +2315,17 @@ void ath10k_halt(struct ath10k *ar) | |||
| 2313 | ar->scan.in_progress = false; | 2315 | ar->scan.in_progress = false; |
| 2314 | ieee80211_scan_completed(ar->hw, true); | 2316 | ieee80211_scan_completed(ar->hw, true); |
| 2315 | } | 2317 | } |
| 2318 | |||
| 2319 | list_for_each_entry(arvif, &ar->arvifs, list) { | ||
| 2320 | if (!arvif->beacon) | ||
| 2321 | continue; | ||
| 2322 | |||
| 2323 | dma_unmap_single(arvif->ar->dev, | ||
| 2324 | ATH10K_SKB_CB(arvif->beacon)->paddr, | ||
| 2325 | arvif->beacon->len, DMA_TO_DEVICE); | ||
| 2326 | dev_kfree_skb_any(arvif->beacon); | ||
| 2327 | arvif->beacon = NULL; | ||
| 2328 | } | ||
| 2316 | spin_unlock_bh(&ar->data_lock); | 2329 | spin_unlock_bh(&ar->data_lock); |
| 2317 | } | 2330 | } |
| 2318 | 2331 | ||
| @@ -2771,6 +2784,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
| 2771 | 2784 | ||
| 2772 | spin_lock_bh(&ar->data_lock); | 2785 | spin_lock_bh(&ar->data_lock); |
| 2773 | if (arvif->beacon) { | 2786 | if (arvif->beacon) { |
| 2787 | dma_unmap_single(arvif->ar->dev, | ||
| 2788 | ATH10K_SKB_CB(arvif->beacon)->paddr, | ||
| 2789 | arvif->beacon->len, DMA_TO_DEVICE); | ||
| 2774 | dev_kfree_skb_any(arvif->beacon); | 2790 | dev_kfree_skb_any(arvif->beacon); |
| 2775 | arvif->beacon = NULL; | 2791 | arvif->beacon = NULL; |
| 2776 | } | 2792 | } |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index bf1083d52e61..66b1f3017f2b 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
| @@ -2452,6 +2452,10 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) | |||
| 2452 | if (val == 0xffffffff) | 2452 | if (val == 0xffffffff) |
| 2453 | continue; | 2453 | continue; |
| 2454 | 2454 | ||
| 2455 | /* the device has crashed so don't bother trying anymore */ | ||
| 2456 | if (val & FW_IND_EVENT_PENDING) | ||
| 2457 | break; | ||
| 2458 | |||
| 2455 | if (val & FW_IND_INITIALIZED) | 2459 | if (val & FW_IND_INITIALIZED) |
| 2456 | break; | 2460 | break; |
| 2457 | 2461 | ||
| @@ -2464,7 +2468,19 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) | |||
| 2464 | mdelay(10); | 2468 | mdelay(10); |
| 2465 | } while (time_before(jiffies, timeout)); | 2469 | } while (time_before(jiffies, timeout)); |
| 2466 | 2470 | ||
| 2467 | if (val == 0xffffffff || !(val & FW_IND_INITIALIZED)) { | 2471 | if (val == 0xffffffff) { |
| 2472 | ath10k_err("failed to read device register, device is gone\n"); | ||
| 2473 | ret = -EIO; | ||
| 2474 | goto out; | ||
| 2475 | } | ||
| 2476 | |||
| 2477 | if (val & FW_IND_EVENT_PENDING) { | ||
| 2478 | ath10k_warn("device has crashed during init\n"); | ||
| 2479 | ret = -ECOMM; | ||
| 2480 | goto out; | ||
| 2481 | } | ||
| 2482 | |||
| 2483 | if (!(val & FW_IND_INITIALIZED)) { | ||
| 2468 | ath10k_err("failed to receive initialized event from target: %08x\n", | 2484 | ath10k_err("failed to receive initialized event from target: %08x\n", |
| 2469 | val); | 2485 | val); |
| 2470 | ret = -ETIMEDOUT; | 2486 | ret = -ETIMEDOUT; |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index fe4d5f1c672f..72cc4f20d102 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
| @@ -1431,6 +1431,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
| 1431 | ATH10K_SKB_CB(arvif->beacon)->paddr, | 1431 | ATH10K_SKB_CB(arvif->beacon)->paddr, |
| 1432 | arvif->beacon->len, DMA_TO_DEVICE); | 1432 | arvif->beacon->len, DMA_TO_DEVICE); |
| 1433 | dev_kfree_skb_any(arvif->beacon); | 1433 | dev_kfree_skb_any(arvif->beacon); |
| 1434 | arvif->beacon = NULL; | ||
| 1434 | } | 1435 | } |
| 1435 | 1436 | ||
| 1436 | ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev, | 1437 | ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev, |
| @@ -1440,6 +1441,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
| 1440 | ATH10K_SKB_CB(bcn)->paddr); | 1441 | ATH10K_SKB_CB(bcn)->paddr); |
| 1441 | if (ret) { | 1442 | if (ret) { |
| 1442 | ath10k_warn("failed to map beacon: %d\n", ret); | 1443 | ath10k_warn("failed to map beacon: %d\n", ret); |
| 1444 | dev_kfree_skb_any(bcn); | ||
| 1443 | goto skip; | 1445 | goto skip; |
| 1444 | } | 1446 | } |
| 1445 | 1447 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 09285084bcd3..0e26f4a34fda 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
| @@ -1759,7 +1759,7 @@ static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi) | |||
| 1759 | } | 1759 | } |
| 1760 | 1760 | ||
| 1761 | static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, | 1761 | static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, |
| 1762 | u8 *mac, struct station_info *sinfo) | 1762 | const u8 *mac, struct station_info *sinfo) |
| 1763 | { | 1763 | { |
| 1764 | struct ath6kl *ar = ath6kl_priv(dev); | 1764 | struct ath6kl *ar = ath6kl_priv(dev); |
| 1765 | struct ath6kl_vif *vif = netdev_priv(dev); | 1765 | struct ath6kl_vif *vif = netdev_priv(dev); |
| @@ -2974,7 +2974,7 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
| 2974 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 2974 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
| 2975 | 2975 | ||
| 2976 | static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, | 2976 | static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, |
| 2977 | u8 *mac) | 2977 | const u8 *mac) |
| 2978 | { | 2978 | { |
| 2979 | struct ath6kl *ar = ath6kl_priv(dev); | 2979 | struct ath6kl *ar = ath6kl_priv(dev); |
| 2980 | struct ath6kl_vif *vif = netdev_priv(dev); | 2980 | struct ath6kl_vif *vif = netdev_priv(dev); |
| @@ -2985,7 +2985,8 @@ static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 2985 | } | 2985 | } |
| 2986 | 2986 | ||
| 2987 | static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, | 2987 | static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, |
| 2988 | u8 *mac, struct station_parameters *params) | 2988 | const u8 *mac, |
| 2989 | struct station_parameters *params) | ||
| 2989 | { | 2990 | { |
| 2990 | struct ath6kl *ar = ath6kl_priv(dev); | 2991 | struct ath6kl *ar = ath6kl_priv(dev); |
| 2991 | struct ath6kl_vif *vif = netdev_priv(dev); | 2992 | struct ath6kl_vif *vif = netdev_priv(dev); |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 0c0e1e36e40f..4d7f9e4712e9 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
| @@ -2320,7 +2320,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index, | |||
| 2320 | return ret; | 2320 | return ret; |
| 2321 | } | 2321 | } |
| 2322 | 2322 | ||
| 2323 | int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk) | 2323 | int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk) |
| 2324 | { | 2324 | { |
| 2325 | struct sk_buff *skb; | 2325 | struct sk_buff *skb; |
| 2326 | struct wmi_add_krk_cmd *cmd; | 2326 | struct wmi_add_krk_cmd *cmd; |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 1f05ecd97c91..7809afbb3e93 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
| @@ -2616,7 +2616,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index, | |||
| 2616 | u8 *key_material, | 2616 | u8 *key_material, |
| 2617 | u8 key_op_ctrl, u8 *mac_addr, | 2617 | u8 key_op_ctrl, u8 *mac_addr, |
| 2618 | enum wmi_sync_flag sync_flag); | 2618 | enum wmi_sync_flag sync_flag); |
| 2619 | int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk); | 2619 | int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk); |
| 2620 | int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index); | 2620 | int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index); |
| 2621 | int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid, | 2621 | int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid, |
| 2622 | const u8 *pmkid, bool set); | 2622 | const u8 *pmkid, bool set); |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 8e1c7b0fe76c..8fcd586d1c39 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
| @@ -53,7 +53,8 @@ obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o | |||
| 53 | obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o | 53 | obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o |
| 54 | ath9k_common-y:= common.o \ | 54 | ath9k_common-y:= common.o \ |
| 55 | common-init.o \ | 55 | common-init.o \ |
| 56 | common-beacon.o | 56 | common-beacon.o \ |
| 57 | common-debug.o | ||
| 57 | 58 | ||
| 58 | ath9k_htc-y += htc_hst.o \ | 59 | ath9k_htc-y += htc_hst.o \ |
| 59 | hif_usb.o \ | 60 | hif_usb.o \ |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 33a2ae77b595..b20469425865 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
| @@ -23,8 +23,8 @@ | |||
| 23 | #include <linux/leds.h> | 23 | #include <linux/leds.h> |
| 24 | #include <linux/completion.h> | 24 | #include <linux/completion.h> |
| 25 | 25 | ||
| 26 | #include "debug.h" | ||
| 27 | #include "common.h" | 26 | #include "common.h" |
| 27 | #include "debug.h" | ||
| 28 | #include "mci.h" | 28 | #include "mci.h" |
| 29 | #include "dfs.h" | 29 | #include "dfs.h" |
| 30 | #include "spectral.h" | 30 | #include "spectral.h" |
| @@ -274,6 +274,7 @@ struct ath_node { | |||
| 274 | #ifdef CONFIG_ATH9K_STATION_STATISTICS | 274 | #ifdef CONFIG_ATH9K_STATION_STATISTICS |
| 275 | struct ath_rx_rate_stats rx_rate_stats; | 275 | struct ath_rx_rate_stats rx_rate_stats; |
| 276 | #endif | 276 | #endif |
| 277 | u8 key_idx[4]; | ||
| 277 | }; | 278 | }; |
| 278 | 279 | ||
| 279 | struct ath_tx_control { | 280 | struct ath_tx_control { |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index bd9e634879e6..e387f0b2954a 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
| @@ -537,8 +537,6 @@ static void ath9k_cache_beacon_config(struct ath_softc *sc, | |||
| 537 | cur_conf->dtim_period = bss_conf->dtim_period; | 537 | cur_conf->dtim_period = bss_conf->dtim_period; |
| 538 | cur_conf->dtim_count = 1; | 538 | cur_conf->dtim_count = 1; |
| 539 | cur_conf->ibss_creator = bss_conf->ibss_creator; | 539 | cur_conf->ibss_creator = bss_conf->ibss_creator; |
| 540 | cur_conf->bmiss_timeout = | ||
| 541 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; | ||
| 542 | 540 | ||
| 543 | /* | 541 | /* |
| 544 | * It looks like mac80211 may end up using beacon interval of zero in | 542 | * It looks like mac80211 may end up using beacon interval of zero in |
| @@ -549,6 +547,9 @@ static void ath9k_cache_beacon_config(struct ath_softc *sc, | |||
| 549 | if (cur_conf->beacon_interval == 0) | 547 | if (cur_conf->beacon_interval == 0) |
| 550 | cur_conf->beacon_interval = 100; | 548 | cur_conf->beacon_interval = 100; |
| 551 | 549 | ||
| 550 | cur_conf->bmiss_timeout = | ||
| 551 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; | ||
| 552 | |||
| 552 | /* | 553 | /* |
| 553 | * We don't parse dtim period from mac80211 during the driver | 554 | * We don't parse dtim period from mac80211 during the driver |
| 554 | * initialization as it breaks association with hidden-ssid | 555 | * initialization as it breaks association with hidden-ssid |
diff --git a/drivers/net/wireless/ath/ath9k/common-debug.c b/drivers/net/wireless/ath/ath9k/common-debug.c new file mode 100644 index 000000000000..3b289f933405 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/common-debug.c | |||
| @@ -0,0 +1,253 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "common.h" | ||
| 18 | |||
| 19 | static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf, | ||
| 20 | size_t count, loff_t *ppos) | ||
| 21 | { | ||
| 22 | struct ath_hw *ah = file->private_data; | ||
| 23 | u32 len = 0, size = 6000; | ||
| 24 | char *buf; | ||
| 25 | size_t retval; | ||
| 26 | |||
| 27 | buf = kzalloc(size, GFP_KERNEL); | ||
| 28 | if (buf == NULL) | ||
| 29 | return -ENOMEM; | ||
| 30 | |||
| 31 | len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size); | ||
| 32 | |||
| 33 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 34 | kfree(buf); | ||
| 35 | |||
| 36 | return retval; | ||
| 37 | } | ||
| 38 | |||
| 39 | static const struct file_operations fops_modal_eeprom = { | ||
| 40 | .read = read_file_modal_eeprom, | ||
| 41 | .open = simple_open, | ||
| 42 | .owner = THIS_MODULE, | ||
| 43 | .llseek = default_llseek, | ||
| 44 | }; | ||
| 45 | |||
| 46 | |||
| 47 | void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy, | ||
| 48 | struct ath_hw *ah) | ||
| 49 | { | ||
| 50 | debugfs_create_file("modal_eeprom", S_IRUSR, debugfs_phy, ah, | ||
| 51 | &fops_modal_eeprom); | ||
| 52 | } | ||
| 53 | EXPORT_SYMBOL(ath9k_cmn_debug_modal_eeprom); | ||
| 54 | |||
| 55 | static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, | ||
| 56 | size_t count, loff_t *ppos) | ||
| 57 | { | ||
| 58 | struct ath_hw *ah = file->private_data; | ||
| 59 | u32 len = 0, size = 1500; | ||
| 60 | ssize_t retval = 0; | ||
| 61 | char *buf; | ||
| 62 | |||
| 63 | buf = kzalloc(size, GFP_KERNEL); | ||
| 64 | if (!buf) | ||
| 65 | return -ENOMEM; | ||
| 66 | |||
| 67 | len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size); | ||
| 68 | |||
| 69 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 70 | kfree(buf); | ||
| 71 | |||
| 72 | return retval; | ||
| 73 | } | ||
| 74 | |||
| 75 | static const struct file_operations fops_base_eeprom = { | ||
| 76 | .read = read_file_base_eeprom, | ||
| 77 | .open = simple_open, | ||
| 78 | .owner = THIS_MODULE, | ||
| 79 | .llseek = default_llseek, | ||
| 80 | }; | ||
| 81 | |||
| 82 | void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy, | ||
| 83 | struct ath_hw *ah) | ||
| 84 | { | ||
| 85 | debugfs_create_file("base_eeprom", S_IRUSR, debugfs_phy, ah, | ||
| 86 | &fops_base_eeprom); | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL(ath9k_cmn_debug_base_eeprom); | ||
| 89 | |||
| 90 | void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats, | ||
| 91 | struct ath_rx_status *rs) | ||
| 92 | { | ||
| 93 | #define RX_PHY_ERR_INC(c) rxstats->phy_err_stats[c]++ | ||
| 94 | #define RX_CMN_STAT_INC(c) (rxstats->c++) | ||
| 95 | |||
| 96 | RX_CMN_STAT_INC(rx_pkts_all); | ||
| 97 | rxstats->rx_bytes_all += rs->rs_datalen; | ||
| 98 | |||
| 99 | if (rs->rs_status & ATH9K_RXERR_CRC) | ||
| 100 | RX_CMN_STAT_INC(crc_err); | ||
| 101 | if (rs->rs_status & ATH9K_RXERR_DECRYPT) | ||
| 102 | RX_CMN_STAT_INC(decrypt_crc_err); | ||
| 103 | if (rs->rs_status & ATH9K_RXERR_MIC) | ||
| 104 | RX_CMN_STAT_INC(mic_err); | ||
| 105 | if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE) | ||
| 106 | RX_CMN_STAT_INC(pre_delim_crc_err); | ||
| 107 | if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST) | ||
| 108 | RX_CMN_STAT_INC(post_delim_crc_err); | ||
| 109 | if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY) | ||
| 110 | RX_CMN_STAT_INC(decrypt_busy_err); | ||
| 111 | |||
| 112 | if (rs->rs_status & ATH9K_RXERR_PHY) { | ||
| 113 | RX_CMN_STAT_INC(phy_err); | ||
| 114 | if (rs->rs_phyerr < ATH9K_PHYERR_MAX) | ||
| 115 | RX_PHY_ERR_INC(rs->rs_phyerr); | ||
| 116 | } | ||
| 117 | |||
| 118 | #undef RX_CMN_STAT_INC | ||
| 119 | #undef RX_PHY_ERR_INC | ||
| 120 | } | ||
| 121 | EXPORT_SYMBOL(ath9k_cmn_debug_stat_rx); | ||
| 122 | |||
| 123 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | ||
| 124 | size_t count, loff_t *ppos) | ||
| 125 | { | ||
| 126 | #define RXS_ERR(s, e) \ | ||
| 127 | do { \ | ||
| 128 | len += scnprintf(buf + len, size - len, \ | ||
| 129 | "%18s : %10u\n", s, \ | ||
| 130 | rxstats->e); \ | ||
| 131 | } while (0) | ||
| 132 | |||
| 133 | struct ath_rx_stats *rxstats = file->private_data; | ||
| 134 | char *buf; | ||
| 135 | unsigned int len = 0, size = 1600; | ||
| 136 | ssize_t retval = 0; | ||
| 137 | |||
| 138 | buf = kzalloc(size, GFP_KERNEL); | ||
| 139 | if (buf == NULL) | ||
| 140 | return -ENOMEM; | ||
| 141 | |||
| 142 | RXS_ERR("PKTS-ALL", rx_pkts_all); | ||
| 143 | RXS_ERR("BYTES-ALL", rx_bytes_all); | ||
| 144 | RXS_ERR("BEACONS", rx_beacons); | ||
| 145 | RXS_ERR("FRAGS", rx_frags); | ||
| 146 | RXS_ERR("SPECTRAL", rx_spectral); | ||
| 147 | |||
| 148 | RXS_ERR("CRC ERR", crc_err); | ||
| 149 | RXS_ERR("DECRYPT CRC ERR", decrypt_crc_err); | ||
| 150 | RXS_ERR("PHY ERR", phy_err); | ||
| 151 | RXS_ERR("MIC ERR", mic_err); | ||
| 152 | RXS_ERR("PRE-DELIM CRC ERR", pre_delim_crc_err); | ||
| 153 | RXS_ERR("POST-DELIM CRC ERR", post_delim_crc_err); | ||
| 154 | RXS_ERR("DECRYPT BUSY ERR", decrypt_busy_err); | ||
| 155 | RXS_ERR("LENGTH-ERR", rx_len_err); | ||
| 156 | RXS_ERR("OOM-ERR", rx_oom_err); | ||
| 157 | RXS_ERR("RATE-ERR", rx_rate_err); | ||
| 158 | RXS_ERR("TOO-MANY-FRAGS", rx_too_many_frags_err); | ||
| 159 | |||
| 160 | if (len > size) | ||
| 161 | len = size; | ||
| 162 | |||
| 163 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 164 | kfree(buf); | ||
| 165 | |||
| 166 | return retval; | ||
| 167 | |||
| 168 | #undef RXS_ERR | ||
| 169 | } | ||
| 170 | |||
| 171 | static const struct file_operations fops_recv = { | ||
| 172 | .read = read_file_recv, | ||
| 173 | .open = simple_open, | ||
| 174 | .owner = THIS_MODULE, | ||
| 175 | .llseek = default_llseek, | ||
| 176 | }; | ||
| 177 | |||
| 178 | void ath9k_cmn_debug_recv(struct dentry *debugfs_phy, | ||
| 179 | struct ath_rx_stats *rxstats) | ||
| 180 | { | ||
| 181 | debugfs_create_file("recv", S_IRUSR, debugfs_phy, rxstats, | ||
| 182 | &fops_recv); | ||
| 183 | } | ||
| 184 | EXPORT_SYMBOL(ath9k_cmn_debug_recv); | ||
| 185 | |||
| 186 | static ssize_t read_file_phy_err(struct file *file, char __user *user_buf, | ||
| 187 | size_t count, loff_t *ppos) | ||
| 188 | { | ||
| 189 | #define PHY_ERR(s, p) \ | ||
| 190 | len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \ | ||
| 191 | rxstats->phy_err_stats[p]); | ||
| 192 | |||
| 193 | struct ath_rx_stats *rxstats = file->private_data; | ||
| 194 | char *buf; | ||
| 195 | unsigned int len = 0, size = 1600; | ||
| 196 | ssize_t retval = 0; | ||
| 197 | |||
| 198 | buf = kzalloc(size, GFP_KERNEL); | ||
| 199 | if (buf == NULL) | ||
| 200 | return -ENOMEM; | ||
| 201 | |||
| 202 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); | ||
| 203 | PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING); | ||
| 204 | PHY_ERR("PARITY ERR", ATH9K_PHYERR_PARITY); | ||
| 205 | PHY_ERR("RATE ERR", ATH9K_PHYERR_RATE); | ||
| 206 | PHY_ERR("LENGTH ERR", ATH9K_PHYERR_LENGTH); | ||
| 207 | PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR); | ||
| 208 | PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE); | ||
| 209 | PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR); | ||
| 210 | PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING); | ||
| 211 | PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); | ||
| 212 | PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); | ||
| 213 | PHY_ERR("OFDM-LENGTH ERR", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); | ||
| 214 | PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP); | ||
| 215 | PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE); | ||
| 216 | PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART); | ||
| 217 | PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); | ||
| 218 | PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING); | ||
| 219 | PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC); | ||
| 220 | PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL); | ||
| 221 | PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); | ||
| 222 | PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); | ||
| 223 | PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); | ||
| 224 | PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP); | ||
| 225 | PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR); | ||
| 226 | PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | ||
| 227 | PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); | ||
| 228 | |||
| 229 | if (len > size) | ||
| 230 | len = size; | ||
| 231 | |||
| 232 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 233 | kfree(buf); | ||
| 234 | |||
| 235 | return retval; | ||
| 236 | |||
| 237 | #undef PHY_ERR | ||
| 238 | } | ||
| 239 | |||
| 240 | static const struct file_operations fops_phy_err = { | ||
| 241 | .read = read_file_phy_err, | ||
| 242 | .open = simple_open, | ||
| 243 | .owner = THIS_MODULE, | ||
| 244 | .llseek = default_llseek, | ||
| 245 | }; | ||
| 246 | |||
| 247 | void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy, | ||
| 248 | struct ath_rx_stats *rxstats) | ||
| 249 | { | ||
| 250 | debugfs_create_file("phy_err", S_IRUSR, debugfs_phy, rxstats, | ||
| 251 | &fops_phy_err); | ||
| 252 | } | ||
| 253 | EXPORT_SYMBOL(ath9k_cmn_debug_phy_err); | ||
diff --git a/drivers/net/wireless/ath/ath9k/common-debug.h b/drivers/net/wireless/ath/ath9k/common-debug.h new file mode 100644 index 000000000000..7c9788490f7f --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/common-debug.h | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | |||
| 18 | |||
| 19 | /** | ||
| 20 | * struct ath_rx_stats - RX Statistics | ||
| 21 | * @rx_pkts_all: No. of total frames received, including ones that | ||
| 22 | may have had errors. | ||
| 23 | * @rx_bytes_all: No. of total bytes received, including ones that | ||
| 24 | may have had errors. | ||
| 25 | * @crc_err: No. of frames with incorrect CRC value | ||
| 26 | * @decrypt_crc_err: No. of frames whose CRC check failed after | ||
| 27 | decryption process completed | ||
| 28 | * @phy_err: No. of frames whose reception failed because the PHY | ||
| 29 | encountered an error | ||
| 30 | * @mic_err: No. of frames with incorrect TKIP MIC verification failure | ||
| 31 | * @pre_delim_crc_err: Pre-Frame delimiter CRC error detections | ||
| 32 | * @post_delim_crc_err: Post-Frame delimiter CRC error detections | ||
| 33 | * @decrypt_busy_err: Decryption interruptions counter | ||
| 34 | * @phy_err_stats: Individual PHY error statistics | ||
| 35 | * @rx_len_err: No. of frames discarded due to bad length. | ||
| 36 | * @rx_oom_err: No. of frames dropped due to OOM issues. | ||
| 37 | * @rx_rate_err: No. of frames dropped due to rate errors. | ||
| 38 | * @rx_too_many_frags_err: Frames dropped due to too-many-frags received. | ||
| 39 | * @rx_beacons: No. of beacons received. | ||
| 40 | * @rx_frags: No. of rx-fragements received. | ||
| 41 | * @rx_spectral: No of spectral packets received. | ||
| 42 | */ | ||
| 43 | struct ath_rx_stats { | ||
| 44 | u32 rx_pkts_all; | ||
| 45 | u32 rx_bytes_all; | ||
| 46 | u32 crc_err; | ||
| 47 | u32 decrypt_crc_err; | ||
| 48 | u32 phy_err; | ||
| 49 | u32 mic_err; | ||
| 50 | u32 pre_delim_crc_err; | ||
| 51 | u32 post_delim_crc_err; | ||
| 52 | u32 decrypt_busy_err; | ||
| 53 | u32 phy_err_stats[ATH9K_PHYERR_MAX]; | ||
| 54 | u32 rx_len_err; | ||
| 55 | u32 rx_oom_err; | ||
| 56 | u32 rx_rate_err; | ||
| 57 | u32 rx_too_many_frags_err; | ||
| 58 | u32 rx_beacons; | ||
| 59 | u32 rx_frags; | ||
| 60 | u32 rx_spectral; | ||
| 61 | }; | ||
| 62 | |||
| 63 | void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy, | ||
| 64 | struct ath_hw *ah); | ||
| 65 | void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy, | ||
| 66 | struct ath_hw *ah); | ||
| 67 | void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats, | ||
| 68 | struct ath_rx_status *rs); | ||
| 69 | void ath9k_cmn_debug_recv(struct dentry *debugfs_phy, | ||
| 70 | struct ath_rx_stats *rxstats); | ||
| 71 | void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy, | ||
| 72 | struct ath_rx_stats *rxstats); | ||
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index ca38116838f0..ffc454b18637 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | #include "common-init.h" | 24 | #include "common-init.h" |
| 25 | #include "common-beacon.h" | 25 | #include "common-beacon.h" |
| 26 | #include "common-debug.h" | ||
| 26 | 27 | ||
| 27 | /* Common header for Atheros 802.11n base driver cores */ | 28 | /* Common header for Atheros 802.11n base driver cores */ |
| 28 | 29 | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 780ff1bee6f6..6cc42be48d4e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
| @@ -948,151 +948,11 @@ static const struct file_operations fops_reset = { | |||
| 948 | .llseek = default_llseek, | 948 | .llseek = default_llseek, |
| 949 | }; | 949 | }; |
| 950 | 950 | ||
| 951 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | ||
| 952 | size_t count, loff_t *ppos) | ||
| 953 | { | ||
| 954 | #define RXS_ERR(s, e) \ | ||
| 955 | do { \ | ||
| 956 | len += scnprintf(buf + len, size - len, \ | ||
| 957 | "%18s : %10u\n", s, \ | ||
| 958 | sc->debug.stats.rxstats.e);\ | ||
| 959 | } while (0) | ||
| 960 | |||
| 961 | struct ath_softc *sc = file->private_data; | ||
| 962 | char *buf; | ||
| 963 | unsigned int len = 0, size = 1600; | ||
| 964 | ssize_t retval = 0; | ||
| 965 | |||
| 966 | buf = kzalloc(size, GFP_KERNEL); | ||
| 967 | if (buf == NULL) | ||
| 968 | return -ENOMEM; | ||
| 969 | |||
| 970 | RXS_ERR("PKTS-ALL", rx_pkts_all); | ||
| 971 | RXS_ERR("BYTES-ALL", rx_bytes_all); | ||
| 972 | RXS_ERR("BEACONS", rx_beacons); | ||
| 973 | RXS_ERR("FRAGS", rx_frags); | ||
| 974 | RXS_ERR("SPECTRAL", rx_spectral); | ||
| 975 | |||
| 976 | RXS_ERR("CRC ERR", crc_err); | ||
| 977 | RXS_ERR("DECRYPT CRC ERR", decrypt_crc_err); | ||
| 978 | RXS_ERR("PHY ERR", phy_err); | ||
| 979 | RXS_ERR("MIC ERR", mic_err); | ||
| 980 | RXS_ERR("PRE-DELIM CRC ERR", pre_delim_crc_err); | ||
| 981 | RXS_ERR("POST-DELIM CRC ERR", post_delim_crc_err); | ||
| 982 | RXS_ERR("DECRYPT BUSY ERR", decrypt_busy_err); | ||
| 983 | RXS_ERR("LENGTH-ERR", rx_len_err); | ||
| 984 | RXS_ERR("OOM-ERR", rx_oom_err); | ||
| 985 | RXS_ERR("RATE-ERR", rx_rate_err); | ||
| 986 | RXS_ERR("TOO-MANY-FRAGS", rx_too_many_frags_err); | ||
| 987 | |||
| 988 | if (len > size) | ||
| 989 | len = size; | ||
| 990 | |||
| 991 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 992 | kfree(buf); | ||
| 993 | |||
| 994 | return retval; | ||
| 995 | |||
| 996 | #undef RXS_ERR | ||
| 997 | } | ||
| 998 | |||
| 999 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) | 951 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) |
| 1000 | { | 952 | { |
| 1001 | #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ | 953 | ath9k_cmn_debug_stat_rx(&sc->debug.stats.rxstats, rs); |
| 1002 | |||
| 1003 | RX_STAT_INC(rx_pkts_all); | ||
| 1004 | sc->debug.stats.rxstats.rx_bytes_all += rs->rs_datalen; | ||
| 1005 | |||
| 1006 | if (rs->rs_status & ATH9K_RXERR_CRC) | ||
| 1007 | RX_STAT_INC(crc_err); | ||
| 1008 | if (rs->rs_status & ATH9K_RXERR_DECRYPT) | ||
| 1009 | RX_STAT_INC(decrypt_crc_err); | ||
| 1010 | if (rs->rs_status & ATH9K_RXERR_MIC) | ||
| 1011 | RX_STAT_INC(mic_err); | ||
| 1012 | if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE) | ||
| 1013 | RX_STAT_INC(pre_delim_crc_err); | ||
| 1014 | if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST) | ||
| 1015 | RX_STAT_INC(post_delim_crc_err); | ||
| 1016 | if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY) | ||
| 1017 | RX_STAT_INC(decrypt_busy_err); | ||
| 1018 | |||
| 1019 | if (rs->rs_status & ATH9K_RXERR_PHY) { | ||
| 1020 | RX_STAT_INC(phy_err); | ||
| 1021 | if (rs->rs_phyerr < ATH9K_PHYERR_MAX) | ||
| 1022 | RX_PHY_ERR_INC(rs->rs_phyerr); | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | #undef RX_PHY_ERR_INC | ||
| 1026 | } | 954 | } |
| 1027 | 955 | ||
| 1028 | static const struct file_operations fops_recv = { | ||
| 1029 | .read = read_file_recv, | ||
| 1030 | .open = simple_open, | ||
| 1031 | .owner = THIS_MODULE, | ||
| 1032 | .llseek = default_llseek, | ||
| 1033 | }; | ||
| 1034 | |||
| 1035 | static ssize_t read_file_phy_err(struct file *file, char __user *user_buf, | ||
| 1036 | size_t count, loff_t *ppos) | ||
| 1037 | { | ||
| 1038 | #define PHY_ERR(s, p) \ | ||
| 1039 | len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \ | ||
| 1040 | sc->debug.stats.rxstats.phy_err_stats[p]); | ||
| 1041 | |||
| 1042 | struct ath_softc *sc = file->private_data; | ||
| 1043 | char *buf; | ||
| 1044 | unsigned int len = 0, size = 1600; | ||
| 1045 | ssize_t retval = 0; | ||
| 1046 | |||
| 1047 | buf = kzalloc(size, GFP_KERNEL); | ||
| 1048 | if (buf == NULL) | ||
| 1049 | return -ENOMEM; | ||
| 1050 | |||
| 1051 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); | ||
| 1052 | PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING); | ||
| 1053 | PHY_ERR("PARITY ERR", ATH9K_PHYERR_PARITY); | ||
| 1054 | PHY_ERR("RATE ERR", ATH9K_PHYERR_RATE); | ||
| 1055 | PHY_ERR("LENGTH ERR", ATH9K_PHYERR_LENGTH); | ||
| 1056 | PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR); | ||
| 1057 | PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE); | ||
| 1058 | PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR); | ||
| 1059 | PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING); | ||
| 1060 | PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); | ||
| 1061 | PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); | ||
| 1062 | PHY_ERR("OFDM-LENGTH ERR", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); | ||
| 1063 | PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP); | ||
| 1064 | PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE); | ||
| 1065 | PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART); | ||
| 1066 | PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); | ||
| 1067 | PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING); | ||
| 1068 | PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC); | ||
| 1069 | PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL); | ||
| 1070 | PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); | ||
| 1071 | PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); | ||
| 1072 | PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); | ||
| 1073 | PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP); | ||
| 1074 | PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR); | ||
| 1075 | PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | ||
| 1076 | PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); | ||
| 1077 | |||
| 1078 | if (len > size) | ||
| 1079 | len = size; | ||
| 1080 | |||
| 1081 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 1082 | kfree(buf); | ||
| 1083 | |||
| 1084 | return retval; | ||
| 1085 | |||
| 1086 | #undef PHY_ERR | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | static const struct file_operations fops_phy_err = { | ||
| 1090 | .read = read_file_phy_err, | ||
| 1091 | .open = simple_open, | ||
| 1092 | .owner = THIS_MODULE, | ||
| 1093 | .llseek = default_llseek, | ||
| 1094 | }; | ||
| 1095 | |||
| 1096 | static ssize_t read_file_regidx(struct file *file, char __user *user_buf, | 956 | static ssize_t read_file_regidx(struct file *file, char __user *user_buf, |
| 1097 | size_t count, loff_t *ppos) | 957 | size_t count, loff_t *ppos) |
| 1098 | { | 958 | { |
| @@ -1268,62 +1128,6 @@ static const struct file_operations fops_dump_nfcal = { | |||
| 1268 | .llseek = default_llseek, | 1128 | .llseek = default_llseek, |
| 1269 | }; | 1129 | }; |
| 1270 | 1130 | ||
| 1271 | static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, | ||
| 1272 | size_t count, loff_t *ppos) | ||
| 1273 | { | ||
| 1274 | struct ath_softc *sc = file->private_data; | ||
| 1275 | struct ath_hw *ah = sc->sc_ah; | ||
| 1276 | u32 len = 0, size = 1500; | ||
| 1277 | ssize_t retval = 0; | ||
| 1278 | char *buf; | ||
| 1279 | |||
| 1280 | buf = kzalloc(size, GFP_KERNEL); | ||
| 1281 | if (!buf) | ||
| 1282 | return -ENOMEM; | ||
| 1283 | |||
| 1284 | len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size); | ||
| 1285 | |||
| 1286 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 1287 | kfree(buf); | ||
| 1288 | |||
| 1289 | return retval; | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | static const struct file_operations fops_base_eeprom = { | ||
| 1293 | .read = read_file_base_eeprom, | ||
| 1294 | .open = simple_open, | ||
| 1295 | .owner = THIS_MODULE, | ||
| 1296 | .llseek = default_llseek, | ||
| 1297 | }; | ||
| 1298 | |||
| 1299 | static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf, | ||
| 1300 | size_t count, loff_t *ppos) | ||
| 1301 | { | ||
| 1302 | struct ath_softc *sc = file->private_data; | ||
| 1303 | struct ath_hw *ah = sc->sc_ah; | ||
| 1304 | u32 len = 0, size = 6000; | ||
| 1305 | char *buf; | ||
| 1306 | size_t retval; | ||
| 1307 | |||
| 1308 | buf = kzalloc(size, GFP_KERNEL); | ||
| 1309 | if (buf == NULL) | ||
| 1310 | return -ENOMEM; | ||
| 1311 | |||
| 1312 | len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size); | ||
| 1313 | |||
| 1314 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 1315 | kfree(buf); | ||
| 1316 | |||
| 1317 | return retval; | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | static const struct file_operations fops_modal_eeprom = { | ||
| 1321 | .read = read_file_modal_eeprom, | ||
| 1322 | .open = simple_open, | ||
| 1323 | .owner = THIS_MODULE, | ||
| 1324 | .llseek = default_llseek, | ||
| 1325 | }; | ||
| 1326 | |||
| 1327 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 1131 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
| 1328 | static ssize_t read_file_btcoex(struct file *file, char __user *user_buf, | 1132 | static ssize_t read_file_btcoex(struct file *file, char __user *user_buf, |
| 1329 | size_t count, loff_t *ppos) | 1133 | size_t count, loff_t *ppos) |
| @@ -1524,10 +1328,10 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
| 1524 | &fops_misc); | 1328 | &fops_misc); |
| 1525 | debugfs_create_file("reset", S_IRUSR, sc->debug.debugfs_phy, sc, | 1329 | debugfs_create_file("reset", S_IRUSR, sc->debug.debugfs_phy, sc, |
| 1526 | &fops_reset); | 1330 | &fops_reset); |
| 1527 | debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, sc, | 1331 | |
| 1528 | &fops_recv); | 1332 | ath9k_cmn_debug_recv(sc->debug.debugfs_phy, &sc->debug.stats.rxstats); |
| 1529 | debugfs_create_file("phy_err", S_IRUSR, sc->debug.debugfs_phy, sc, | 1333 | ath9k_cmn_debug_phy_err(sc->debug.debugfs_phy, &sc->debug.stats.rxstats); |
| 1530 | &fops_phy_err); | 1334 | |
| 1531 | debugfs_create_u8("rx_chainmask", S_IRUSR, sc->debug.debugfs_phy, | 1335 | debugfs_create_u8("rx_chainmask", S_IRUSR, sc->debug.debugfs_phy, |
| 1532 | &ah->rxchainmask); | 1336 | &ah->rxchainmask); |
| 1533 | debugfs_create_u8("tx_chainmask", S_IRUSR, sc->debug.debugfs_phy, | 1337 | debugfs_create_u8("tx_chainmask", S_IRUSR, sc->debug.debugfs_phy, |
| @@ -1547,10 +1351,10 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
| 1547 | &fops_regdump); | 1351 | &fops_regdump); |
| 1548 | debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc, | 1352 | debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc, |
| 1549 | &fops_dump_nfcal); | 1353 | &fops_dump_nfcal); |
| 1550 | debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, | 1354 | |
| 1551 | &fops_base_eeprom); | 1355 | ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah); |
| 1552 | debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, | 1356 | ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah); |
| 1553 | &fops_modal_eeprom); | 1357 | |
| 1554 | debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, | 1358 | debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, |
| 1555 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); | 1359 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); |
| 1556 | debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, | 1360 | debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 559a68c2709c..53ae15bd0c9d 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
| @@ -221,50 +221,6 @@ struct ath_rx_rate_stats { | |||
| 221 | } cck_stats[4]; | 221 | } cck_stats[4]; |
| 222 | }; | 222 | }; |
| 223 | 223 | ||
| 224 | /** | ||
| 225 | * struct ath_rx_stats - RX Statistics | ||
| 226 | * @rx_pkts_all: No. of total frames received, including ones that | ||
| 227 | may have had errors. | ||
| 228 | * @rx_bytes_all: No. of total bytes received, including ones that | ||
| 229 | may have had errors. | ||
| 230 | * @crc_err: No. of frames with incorrect CRC value | ||
| 231 | * @decrypt_crc_err: No. of frames whose CRC check failed after | ||
| 232 | decryption process completed | ||
| 233 | * @phy_err: No. of frames whose reception failed because the PHY | ||
| 234 | encountered an error | ||
| 235 | * @mic_err: No. of frames with incorrect TKIP MIC verification failure | ||
| 236 | * @pre_delim_crc_err: Pre-Frame delimiter CRC error detections | ||
| 237 | * @post_delim_crc_err: Post-Frame delimiter CRC error detections | ||
| 238 | * @decrypt_busy_err: Decryption interruptions counter | ||
| 239 | * @phy_err_stats: Individual PHY error statistics | ||
| 240 | * @rx_len_err: No. of frames discarded due to bad length. | ||
| 241 | * @rx_oom_err: No. of frames dropped due to OOM issues. | ||
| 242 | * @rx_rate_err: No. of frames dropped due to rate errors. | ||
| 243 | * @rx_too_many_frags_err: Frames dropped due to too-many-frags received. | ||
| 244 | * @rx_beacons: No. of beacons received. | ||
| 245 | * @rx_frags: No. of rx-fragements received. | ||
| 246 | * @rx_spectral: No of spectral packets received. | ||
| 247 | */ | ||
| 248 | struct ath_rx_stats { | ||
| 249 | u32 rx_pkts_all; | ||
| 250 | u32 rx_bytes_all; | ||
| 251 | u32 crc_err; | ||
| 252 | u32 decrypt_crc_err; | ||
| 253 | u32 phy_err; | ||
| 254 | u32 mic_err; | ||
| 255 | u32 pre_delim_crc_err; | ||
| 256 | u32 post_delim_crc_err; | ||
| 257 | u32 decrypt_busy_err; | ||
| 258 | u32 phy_err_stats[ATH9K_PHYERR_MAX]; | ||
| 259 | u32 rx_len_err; | ||
| 260 | u32 rx_oom_err; | ||
| 261 | u32 rx_rate_err; | ||
| 262 | u32 rx_too_many_frags_err; | ||
| 263 | u32 rx_beacons; | ||
| 264 | u32 rx_frags; | ||
| 265 | u32 rx_spectral; | ||
| 266 | }; | ||
| 267 | |||
| 268 | #define ANT_MAIN 0 | 224 | #define ANT_MAIN 0 |
| 269 | #define ANT_ALT 1 | 225 | #define ANT_ALT 1 |
| 270 | 226 | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c index 857bb28b3894..e0c740dcfea8 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.c +++ b/drivers/net/wireless/ath/ath9k/dfs.c | |||
| @@ -178,12 +178,14 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | |||
| 178 | pe.ts = mactime; | 178 | pe.ts = mactime; |
| 179 | if (ath9k_postprocess_radar_event(sc, &ard, &pe)) { | 179 | if (ath9k_postprocess_radar_event(sc, &ard, &pe)) { |
| 180 | struct dfs_pattern_detector *pd = sc->dfs_detector; | 180 | struct dfs_pattern_detector *pd = sc->dfs_detector; |
| 181 | static u64 last_ts; | 181 | #ifdef CONFIG_ATH9K_DEBUGFS |
| 182 | ath_dbg(common, DFS, | 182 | ath_dbg(common, DFS, |
| 183 | "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, " | 183 | "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, " |
| 184 | "width=%d, rssi=%d, delta_ts=%llu\n", | 184 | "width=%d, rssi=%d, delta_ts=%llu\n", |
| 185 | pe.freq, pe.ts, pe.width, pe.rssi, pe.ts-last_ts); | 185 | pe.freq, pe.ts, pe.width, pe.rssi, |
| 186 | last_ts = pe.ts; | 186 | pe.ts - sc->debug.stats.dfs_stats.last_ts); |
| 187 | sc->debug.stats.dfs_stats.last_ts = pe.ts; | ||
| 188 | #endif | ||
| 187 | DFS_STAT_INC(sc, pulses_processed); | 189 | DFS_STAT_INC(sc, pulses_processed); |
| 188 | if (pd != NULL && pd->add_pulse(pd, &pe)) { | 190 | if (pd != NULL && pd->add_pulse(pd, &pe)) { |
| 189 | DFS_STAT_INC(sc, radar_detected); | 191 | DFS_STAT_INC(sc, radar_detected); |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.h b/drivers/net/wireless/ath/ath9k/dfs_debug.h index 7936c9126a20..d9486867a5e0 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.h +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.h | |||
| @@ -51,6 +51,7 @@ struct ath_dfs_stats { | |||
| 51 | /* pattern detection stats */ | 51 | /* pattern detection stats */ |
| 52 | u32 pulses_processed; | 52 | u32 pulses_processed; |
| 53 | u32 radar_detected; | 53 | u32 radar_detected; |
| 54 | u64 last_ts; | ||
| 54 | }; | 55 | }; |
| 55 | 56 | ||
| 56 | #if defined(CONFIG_ATH9K_DFS_DEBUGFS) | 57 | #if defined(CONFIG_ATH9K_DFS_DEBUGFS) |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index dab1f0cab993..09a5d72f3ff5 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
| @@ -325,14 +325,14 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) | |||
| 325 | 325 | ||
| 326 | #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) | 326 | #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) |
| 327 | #define TX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a) | 327 | #define TX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a) |
| 328 | #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) | 328 | #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c++) |
| 329 | #define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c += a) | 329 | #define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c += a) |
| 330 | #define CAB_STAT_INC priv->debug.tx_stats.cab_queued++ | 330 | #define CAB_STAT_INC priv->debug.tx_stats.cab_queued++ |
| 331 | 331 | ||
| 332 | #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) | 332 | #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) |
| 333 | 333 | ||
| 334 | void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | 334 | void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, |
| 335 | struct ath_htc_rx_status *rxs); | 335 | struct ath_rx_status *rs); |
| 336 | 336 | ||
| 337 | struct ath_tx_stats { | 337 | struct ath_tx_stats { |
| 338 | u32 buf_queued; | 338 | u32 buf_queued; |
| @@ -345,25 +345,18 @@ struct ath_tx_stats { | |||
| 345 | u32 queue_stats[IEEE80211_NUM_ACS]; | 345 | u32 queue_stats[IEEE80211_NUM_ACS]; |
| 346 | }; | 346 | }; |
| 347 | 347 | ||
| 348 | struct ath_rx_stats { | 348 | struct ath_skbrx_stats { |
| 349 | u32 skb_allocated; | 349 | u32 skb_allocated; |
| 350 | u32 skb_completed; | 350 | u32 skb_completed; |
| 351 | u32 skb_completed_bytes; | 351 | u32 skb_completed_bytes; |
| 352 | u32 skb_dropped; | 352 | u32 skb_dropped; |
| 353 | u32 err_crc; | ||
| 354 | u32 err_decrypt_crc; | ||
| 355 | u32 err_mic; | ||
| 356 | u32 err_pre_delim; | ||
| 357 | u32 err_post_delim; | ||
| 358 | u32 err_decrypt_busy; | ||
| 359 | u32 err_phy; | ||
| 360 | u32 err_phy_stats[ATH9K_PHYERR_MAX]; | ||
| 361 | }; | 353 | }; |
| 362 | 354 | ||
| 363 | struct ath9k_debug { | 355 | struct ath9k_debug { |
| 364 | struct dentry *debugfs_phy; | 356 | struct dentry *debugfs_phy; |
| 365 | struct ath_tx_stats tx_stats; | 357 | struct ath_tx_stats tx_stats; |
| 366 | struct ath_rx_stats rx_stats; | 358 | struct ath_rx_stats rx_stats; |
| 359 | struct ath_skbrx_stats skbrx_stats; | ||
| 367 | }; | 360 | }; |
| 368 | 361 | ||
| 369 | void ath9k_htc_get_et_strings(struct ieee80211_hw *hw, | 362 | void ath9k_htc_get_et_strings(struct ieee80211_hw *hw, |
| @@ -385,7 +378,7 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw, | |||
| 385 | #define TX_QSTAT_INC(c) do { } while (0) | 378 | #define TX_QSTAT_INC(c) do { } while (0) |
| 386 | 379 | ||
| 387 | static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | 380 | static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, |
| 388 | struct ath_htc_rx_status *rxs) | 381 | struct ath_rx_status *rs) |
| 389 | { | 382 | { |
| 390 | } | 383 | } |
| 391 | 384 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index fb071ee4fcfb..8b529e4b8ac4 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c | |||
| @@ -243,39 +243,14 @@ static const struct file_operations fops_xmit = { | |||
| 243 | }; | 243 | }; |
| 244 | 244 | ||
| 245 | void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | 245 | void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, |
| 246 | struct ath_htc_rx_status *rxs) | 246 | struct ath_rx_status *rs) |
| 247 | { | 247 | { |
| 248 | #define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++ | 248 | ath9k_cmn_debug_stat_rx(&priv->debug.rx_stats, rs); |
| 249 | |||
| 250 | if (rxs->rs_status & ATH9K_RXERR_CRC) | ||
| 251 | priv->debug.rx_stats.err_crc++; | ||
| 252 | if (rxs->rs_status & ATH9K_RXERR_DECRYPT) | ||
| 253 | priv->debug.rx_stats.err_decrypt_crc++; | ||
| 254 | if (rxs->rs_status & ATH9K_RXERR_MIC) | ||
| 255 | priv->debug.rx_stats.err_mic++; | ||
| 256 | if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE) | ||
| 257 | priv->debug.rx_stats.err_pre_delim++; | ||
| 258 | if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST) | ||
| 259 | priv->debug.rx_stats.err_post_delim++; | ||
| 260 | if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY) | ||
| 261 | priv->debug.rx_stats.err_decrypt_busy++; | ||
| 262 | |||
| 263 | if (rxs->rs_status & ATH9K_RXERR_PHY) { | ||
| 264 | priv->debug.rx_stats.err_phy++; | ||
| 265 | if (rxs->rs_phyerr < ATH9K_PHYERR_MAX) | ||
| 266 | RX_PHY_ERR_INC(rxs->rs_phyerr); | ||
| 267 | } | ||
| 268 | |||
| 269 | #undef RX_PHY_ERR_INC | ||
| 270 | } | 249 | } |
| 271 | 250 | ||
| 272 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | 251 | static ssize_t read_file_skb_rx(struct file *file, char __user *user_buf, |
| 273 | size_t count, loff_t *ppos) | 252 | size_t count, loff_t *ppos) |
| 274 | { | 253 | { |
| 275 | #define PHY_ERR(s, p) \ | ||
| 276 | len += scnprintf(buf + len, size - len, "%20s : %10u\n", s, \ | ||
| 277 | priv->debug.rx_stats.err_phy_stats[p]); | ||
| 278 | |||
| 279 | struct ath9k_htc_priv *priv = file->private_data; | 254 | struct ath9k_htc_priv *priv = file->private_data; |
| 280 | char *buf; | 255 | char *buf; |
| 281 | unsigned int len = 0, size = 1500; | 256 | unsigned int len = 0, size = 1500; |
| @@ -287,63 +262,13 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
| 287 | 262 | ||
| 288 | len += scnprintf(buf + len, size - len, | 263 | len += scnprintf(buf + len, size - len, |
| 289 | "%20s : %10u\n", "SKBs allocated", | 264 | "%20s : %10u\n", "SKBs allocated", |
| 290 | priv->debug.rx_stats.skb_allocated); | 265 | priv->debug.skbrx_stats.skb_allocated); |
| 291 | len += scnprintf(buf + len, size - len, | 266 | len += scnprintf(buf + len, size - len, |
| 292 | "%20s : %10u\n", "SKBs completed", | 267 | "%20s : %10u\n", "SKBs completed", |
| 293 | priv->debug.rx_stats.skb_completed); | 268 | priv->debug.skbrx_stats.skb_completed); |
| 294 | len += scnprintf(buf + len, size - len, | 269 | len += scnprintf(buf + len, size - len, |
| 295 | "%20s : %10u\n", "SKBs Dropped", | 270 | "%20s : %10u\n", "SKBs Dropped", |
| 296 | priv->debug.rx_stats.skb_dropped); | 271 | priv->debug.skbrx_stats.skb_dropped); |
| 297 | |||
| 298 | len += scnprintf(buf + len, size - len, | ||
| 299 | "%20s : %10u\n", "CRC ERR", | ||
| 300 | priv->debug.rx_stats.err_crc); | ||
| 301 | len += scnprintf(buf + len, size - len, | ||
| 302 | "%20s : %10u\n", "DECRYPT CRC ERR", | ||
| 303 | priv->debug.rx_stats.err_decrypt_crc); | ||
| 304 | len += scnprintf(buf + len, size - len, | ||
| 305 | "%20s : %10u\n", "MIC ERR", | ||
| 306 | priv->debug.rx_stats.err_mic); | ||
| 307 | len += scnprintf(buf + len, size - len, | ||
| 308 | "%20s : %10u\n", "PRE-DELIM CRC ERR", | ||
| 309 | priv->debug.rx_stats.err_pre_delim); | ||
| 310 | len += scnprintf(buf + len, size - len, | ||
| 311 | "%20s : %10u\n", "POST-DELIM CRC ERR", | ||
| 312 | priv->debug.rx_stats.err_post_delim); | ||
| 313 | len += scnprintf(buf + len, size - len, | ||
| 314 | "%20s : %10u\n", "DECRYPT BUSY ERR", | ||
| 315 | priv->debug.rx_stats.err_decrypt_busy); | ||
| 316 | len += scnprintf(buf + len, size - len, | ||
| 317 | "%20s : %10u\n", "TOTAL PHY ERR", | ||
| 318 | priv->debug.rx_stats.err_phy); | ||
| 319 | |||
| 320 | |||
| 321 | PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); | ||
| 322 | PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); | ||
| 323 | PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); | ||
| 324 | PHY_ERR("RATE", ATH9K_PHYERR_RATE); | ||
| 325 | PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH); | ||
| 326 | PHY_ERR("RADAR", ATH9K_PHYERR_RADAR); | ||
| 327 | PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE); | ||
| 328 | PHY_ERR("TOR", ATH9K_PHYERR_TOR); | ||
| 329 | PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING); | ||
| 330 | PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); | ||
| 331 | PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); | ||
| 332 | PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); | ||
| 333 | PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP); | ||
| 334 | PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE); | ||
| 335 | PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART); | ||
| 336 | PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT); | ||
| 337 | PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING); | ||
| 338 | PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC); | ||
| 339 | PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL); | ||
| 340 | PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE); | ||
| 341 | PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART); | ||
| 342 | PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); | ||
| 343 | PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP); | ||
| 344 | PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR); | ||
| 345 | PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | ||
| 346 | PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); | ||
| 347 | 272 | ||
| 348 | if (len > size) | 273 | if (len > size) |
| 349 | len = size; | 274 | len = size; |
| @@ -352,12 +277,10 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
| 352 | kfree(buf); | 277 | kfree(buf); |
| 353 | 278 | ||
| 354 | return retval; | 279 | return retval; |
| 355 | |||
| 356 | #undef PHY_ERR | ||
| 357 | } | 280 | } |
| 358 | 281 | ||
| 359 | static const struct file_operations fops_recv = { | 282 | static const struct file_operations fops_skb_rx = { |
| 360 | .read = read_file_recv, | 283 | .read = read_file_skb_rx, |
| 361 | .open = simple_open, | 284 | .open = simple_open, |
| 362 | .owner = THIS_MODULE, | 285 | .owner = THIS_MODULE, |
| 363 | .llseek = default_llseek, | 286 | .llseek = default_llseek, |
| @@ -486,423 +409,6 @@ static const struct file_operations fops_debug = { | |||
| 486 | .llseek = default_llseek, | 409 | .llseek = default_llseek, |
| 487 | }; | 410 | }; |
| 488 | 411 | ||
| 489 | static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, | ||
| 490 | size_t count, loff_t *ppos) | ||
| 491 | { | ||
| 492 | struct ath9k_htc_priv *priv = file->private_data; | ||
| 493 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
| 494 | struct base_eep_header *pBase = NULL; | ||
| 495 | unsigned int len = 0, size = 1500; | ||
| 496 | ssize_t retval = 0; | ||
| 497 | char *buf; | ||
| 498 | |||
| 499 | pBase = ath9k_htc_get_eeprom_base(priv); | ||
| 500 | |||
| 501 | if (pBase == NULL) { | ||
| 502 | ath_err(common, "Unknown EEPROM type\n"); | ||
| 503 | return 0; | ||
| 504 | } | ||
| 505 | |||
| 506 | buf = kzalloc(size, GFP_KERNEL); | ||
| 507 | if (buf == NULL) | ||
| 508 | return -ENOMEM; | ||
| 509 | |||
| 510 | len += scnprintf(buf + len, size - len, | ||
| 511 | "%20s : %10d\n", "Major Version", | ||
| 512 | pBase->version >> 12); | ||
| 513 | len += scnprintf(buf + len, size - len, | ||
| 514 | "%20s : %10d\n", "Minor Version", | ||
| 515 | pBase->version & 0xFFF); | ||
| 516 | len += scnprintf(buf + len, size - len, | ||
| 517 | "%20s : %10d\n", "Checksum", | ||
| 518 | pBase->checksum); | ||
| 519 | len += scnprintf(buf + len, size - len, | ||
| 520 | "%20s : %10d\n", "Length", | ||
| 521 | pBase->length); | ||
| 522 | len += scnprintf(buf + len, size - len, | ||
| 523 | "%20s : %10d\n", "RegDomain1", | ||
| 524 | pBase->regDmn[0]); | ||
| 525 | len += scnprintf(buf + len, size - len, | ||
| 526 | "%20s : %10d\n", "RegDomain2", | ||
| 527 | pBase->regDmn[1]); | ||
| 528 | len += scnprintf(buf + len, size - len, | ||
| 529 | "%20s : %10d\n", | ||
| 530 | "TX Mask", pBase->txMask); | ||
| 531 | len += scnprintf(buf + len, size - len, | ||
| 532 | "%20s : %10d\n", | ||
| 533 | "RX Mask", pBase->rxMask); | ||
| 534 | len += scnprintf(buf + len, size - len, | ||
| 535 | "%20s : %10d\n", | ||
| 536 | "Allow 5GHz", | ||
| 537 | !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); | ||
| 538 | len += scnprintf(buf + len, size - len, | ||
| 539 | "%20s : %10d\n", | ||
| 540 | "Allow 2GHz", | ||
| 541 | !!(pBase->opCapFlags & AR5416_OPFLAGS_11G)); | ||
| 542 | len += scnprintf(buf + len, size - len, | ||
| 543 | "%20s : %10d\n", | ||
| 544 | "Disable 2GHz HT20", | ||
| 545 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT20)); | ||
| 546 | len += scnprintf(buf + len, size - len, | ||
| 547 | "%20s : %10d\n", | ||
| 548 | "Disable 2GHz HT40", | ||
| 549 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT40)); | ||
| 550 | len += scnprintf(buf + len, size - len, | ||
| 551 | "%20s : %10d\n", | ||
| 552 | "Disable 5Ghz HT20", | ||
| 553 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT20)); | ||
| 554 | len += scnprintf(buf + len, size - len, | ||
| 555 | "%20s : %10d\n", | ||
| 556 | "Disable 5Ghz HT40", | ||
| 557 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40)); | ||
| 558 | len += scnprintf(buf + len, size - len, | ||
| 559 | "%20s : %10d\n", | ||
| 560 | "Big Endian", | ||
| 561 | !!(pBase->eepMisc & 0x01)); | ||
| 562 | len += scnprintf(buf + len, size - len, | ||
| 563 | "%20s : %10d\n", | ||
| 564 | "Cal Bin Major Ver", | ||
| 565 | (pBase->binBuildNumber >> 24) & 0xFF); | ||
| 566 | len += scnprintf(buf + len, size - len, | ||
| 567 | "%20s : %10d\n", | ||
| 568 | "Cal Bin Minor Ver", | ||
| 569 | (pBase->binBuildNumber >> 16) & 0xFF); | ||
| 570 | len += scnprintf(buf + len, size - len, | ||
| 571 | "%20s : %10d\n", | ||
| 572 | "Cal Bin Build", | ||
| 573 | (pBase->binBuildNumber >> 8) & 0xFF); | ||
| 574 | |||
| 575 | /* | ||
| 576 | * UB91 specific data. | ||
| 577 | */ | ||
| 578 | if (AR_SREV_9271(priv->ah)) { | ||
| 579 | struct base_eep_header_4k *pBase4k = | ||
| 580 | &priv->ah->eeprom.map4k.baseEepHeader; | ||
| 581 | |||
| 582 | len += scnprintf(buf + len, size - len, | ||
| 583 | "%20s : %10d\n", | ||
| 584 | "TX Gain type", | ||
| 585 | pBase4k->txGainType); | ||
| 586 | } | ||
| 587 | |||
| 588 | /* | ||
| 589 | * UB95 specific data. | ||
| 590 | */ | ||
| 591 | if (priv->ah->hw_version.usbdev == AR9287_USB) { | ||
| 592 | struct base_eep_ar9287_header *pBase9287 = | ||
| 593 | &priv->ah->eeprom.map9287.baseEepHeader; | ||
| 594 | |||
| 595 | len += scnprintf(buf + len, size - len, | ||
| 596 | "%20s : %10ddB\n", | ||
| 597 | "Power Table Offset", | ||
| 598 | pBase9287->pwrTableOffset); | ||
| 599 | |||
| 600 | len += scnprintf(buf + len, size - len, | ||
| 601 | "%20s : %10d\n", | ||
| 602 | "OpenLoop Power Ctrl", | ||
| 603 | pBase9287->openLoopPwrCntl); | ||
| 604 | } | ||
| 605 | |||
| 606 | len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", | ||
| 607 | pBase->macAddr); | ||
| 608 | if (len > size) | ||
| 609 | len = size; | ||
| 610 | |||
| 611 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 612 | kfree(buf); | ||
| 613 | |||
| 614 | return retval; | ||
| 615 | } | ||
| 616 | |||
| 617 | static const struct file_operations fops_base_eeprom = { | ||
| 618 | .read = read_file_base_eeprom, | ||
| 619 | .open = simple_open, | ||
| 620 | .owner = THIS_MODULE, | ||
| 621 | .llseek = default_llseek, | ||
| 622 | }; | ||
| 623 | |||
| 624 | static ssize_t read_4k_modal_eeprom(struct file *file, | ||
| 625 | char __user *user_buf, | ||
| 626 | size_t count, loff_t *ppos) | ||
| 627 | { | ||
| 628 | #define PR_EEP(_s, _val) \ | ||
| 629 | do { \ | ||
| 630 | len += scnprintf(buf + len, size - len, "%20s : %10d\n",\ | ||
| 631 | _s, (_val)); \ | ||
| 632 | } while (0) | ||
| 633 | |||
| 634 | struct ath9k_htc_priv *priv = file->private_data; | ||
| 635 | struct modal_eep_4k_header *pModal = &priv->ah->eeprom.map4k.modalHeader; | ||
| 636 | unsigned int len = 0, size = 2048; | ||
| 637 | ssize_t retval = 0; | ||
| 638 | char *buf; | ||
| 639 | |||
| 640 | buf = kzalloc(size, GFP_KERNEL); | ||
| 641 | if (buf == NULL) | ||
| 642 | return -ENOMEM; | ||
| 643 | |||
| 644 | PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); | ||
| 645 | PR_EEP("Ant. Common Control", pModal->antCtrlCommon); | ||
| 646 | PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); | ||
| 647 | PR_EEP("Switch Settle", pModal->switchSettling); | ||
| 648 | PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); | ||
| 649 | PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); | ||
| 650 | PR_EEP("ADC Desired size", pModal->adcDesiredSize); | ||
| 651 | PR_EEP("PGA Desired size", pModal->pgaDesiredSize); | ||
| 652 | PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]); | ||
| 653 | PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); | ||
| 654 | PR_EEP("txEndToRxOn", pModal->txEndToRxOn); | ||
| 655 | PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); | ||
| 656 | PR_EEP("CCA Threshold)", pModal->thresh62); | ||
| 657 | PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); | ||
| 658 | PR_EEP("xpdGain", pModal->xpdGain); | ||
| 659 | PR_EEP("External PD", pModal->xpd); | ||
| 660 | PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); | ||
| 661 | PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); | ||
| 662 | PR_EEP("pdGainOverlap", pModal->pdGainOverlap); | ||
| 663 | PR_EEP("O/D Bias Version", pModal->version); | ||
| 664 | PR_EEP("CCK OutputBias", pModal->ob_0); | ||
| 665 | PR_EEP("BPSK OutputBias", pModal->ob_1); | ||
| 666 | PR_EEP("QPSK OutputBias", pModal->ob_2); | ||
| 667 | PR_EEP("16QAM OutputBias", pModal->ob_3); | ||
| 668 | PR_EEP("64QAM OutputBias", pModal->ob_4); | ||
| 669 | PR_EEP("CCK Driver1_Bias", pModal->db1_0); | ||
| 670 | PR_EEP("BPSK Driver1_Bias", pModal->db1_1); | ||
| 671 | PR_EEP("QPSK Driver1_Bias", pModal->db1_2); | ||
| 672 | PR_EEP("16QAM Driver1_Bias", pModal->db1_3); | ||
| 673 | PR_EEP("64QAM Driver1_Bias", pModal->db1_4); | ||
| 674 | PR_EEP("CCK Driver2_Bias", pModal->db2_0); | ||
| 675 | PR_EEP("BPSK Driver2_Bias", pModal->db2_1); | ||
| 676 | PR_EEP("QPSK Driver2_Bias", pModal->db2_2); | ||
| 677 | PR_EEP("16QAM Driver2_Bias", pModal->db2_3); | ||
| 678 | PR_EEP("64QAM Driver2_Bias", pModal->db2_4); | ||
| 679 | PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); | ||
| 680 | PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); | ||
| 681 | PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); | ||
| 682 | PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); | ||
| 683 | PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); | ||
| 684 | PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); | ||
| 685 | PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); | ||
| 686 | PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]); | ||
| 687 | PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]); | ||
| 688 | PR_EEP("Ant. Diversity ctl1", pModal->antdiv_ctl1); | ||
| 689 | PR_EEP("Ant. Diversity ctl2", pModal->antdiv_ctl2); | ||
| 690 | PR_EEP("TX Diversity", pModal->tx_diversity); | ||
| 691 | |||
| 692 | if (len > size) | ||
| 693 | len = size; | ||
| 694 | |||
| 695 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 696 | kfree(buf); | ||
| 697 | |||
| 698 | return retval; | ||
| 699 | |||
| 700 | #undef PR_EEP | ||
| 701 | } | ||
| 702 | |||
| 703 | static ssize_t read_def_modal_eeprom(struct file *file, | ||
| 704 | char __user *user_buf, | ||
| 705 | size_t count, loff_t *ppos) | ||
| 706 | { | ||
| 707 | #define PR_EEP(_s, _val) \ | ||
| 708 | do { \ | ||
| 709 | if (pBase->opCapFlags & AR5416_OPFLAGS_11G) { \ | ||
| 710 | pModal = &priv->ah->eeprom.def.modalHeader[1]; \ | ||
| 711 | len += scnprintf(buf + len, size - len, "%20s : %8d%7s", \ | ||
| 712 | _s, (_val), "|"); \ | ||
| 713 | } \ | ||
| 714 | if (pBase->opCapFlags & AR5416_OPFLAGS_11A) { \ | ||
| 715 | pModal = &priv->ah->eeprom.def.modalHeader[0]; \ | ||
| 716 | len += scnprintf(buf + len, size - len, "%9d\n",\ | ||
| 717 | (_val)); \ | ||
| 718 | } \ | ||
| 719 | } while (0) | ||
| 720 | |||
| 721 | struct ath9k_htc_priv *priv = file->private_data; | ||
| 722 | struct base_eep_header *pBase = &priv->ah->eeprom.def.baseEepHeader; | ||
| 723 | struct modal_eep_header *pModal = NULL; | ||
| 724 | unsigned int len = 0, size = 3500; | ||
| 725 | ssize_t retval = 0; | ||
| 726 | char *buf; | ||
| 727 | |||
| 728 | buf = kzalloc(size, GFP_KERNEL); | ||
| 729 | if (buf == NULL) | ||
| 730 | return -ENOMEM; | ||
| 731 | |||
| 732 | len += scnprintf(buf + len, size - len, | ||
| 733 | "%31s %15s\n", "2G", "5G"); | ||
| 734 | len += scnprintf(buf + len, size - len, | ||
| 735 | "%32s %16s\n", "====", "====\n"); | ||
| 736 | |||
| 737 | PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); | ||
| 738 | PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]); | ||
| 739 | PR_EEP("Chain2 Ant. Control", pModal->antCtrlChain[2]); | ||
| 740 | PR_EEP("Ant. Common Control", pModal->antCtrlCommon); | ||
| 741 | PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); | ||
| 742 | PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]); | ||
| 743 | PR_EEP("Chain2 Ant. Gain", pModal->antennaGainCh[2]); | ||
| 744 | PR_EEP("Switch Settle", pModal->switchSettling); | ||
| 745 | PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); | ||
| 746 | PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]); | ||
| 747 | PR_EEP("Chain2 TxRxAtten", pModal->txRxAttenCh[2]); | ||
| 748 | PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); | ||
| 749 | PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]); | ||
| 750 | PR_EEP("Chain2 RxTxMargin", pModal->rxTxMarginCh[2]); | ||
| 751 | PR_EEP("ADC Desired size", pModal->adcDesiredSize); | ||
| 752 | PR_EEP("PGA Desired size", pModal->pgaDesiredSize); | ||
| 753 | PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]); | ||
| 754 | PR_EEP("Chain1 xlna Gain", pModal->xlnaGainCh[1]); | ||
| 755 | PR_EEP("Chain2 xlna Gain", pModal->xlnaGainCh[2]); | ||
| 756 | PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); | ||
| 757 | PR_EEP("txEndToRxOn", pModal->txEndToRxOn); | ||
| 758 | PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); | ||
| 759 | PR_EEP("CCA Threshold)", pModal->thresh62); | ||
| 760 | PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); | ||
| 761 | PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]); | ||
| 762 | PR_EEP("Chain2 NF Threshold", pModal->noiseFloorThreshCh[2]); | ||
| 763 | PR_EEP("xpdGain", pModal->xpdGain); | ||
| 764 | PR_EEP("External PD", pModal->xpd); | ||
| 765 | PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); | ||
| 766 | PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]); | ||
| 767 | PR_EEP("Chain2 I Coefficient", pModal->iqCalICh[2]); | ||
| 768 | PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); | ||
| 769 | PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]); | ||
| 770 | PR_EEP("Chain2 Q Coefficient", pModal->iqCalQCh[2]); | ||
| 771 | PR_EEP("pdGainOverlap", pModal->pdGainOverlap); | ||
| 772 | PR_EEP("Chain0 OutputBias", pModal->ob); | ||
| 773 | PR_EEP("Chain0 DriverBias", pModal->db); | ||
| 774 | PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); | ||
| 775 | PR_EEP("2chain pwr decrease", pModal->pwrDecreaseFor2Chain); | ||
| 776 | PR_EEP("3chain pwr decrease", pModal->pwrDecreaseFor3Chain); | ||
| 777 | PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); | ||
| 778 | PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); | ||
| 779 | PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); | ||
| 780 | PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); | ||
| 781 | PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]); | ||
| 782 | PR_EEP("Chain2 bswAtten", pModal->bswAtten[2]); | ||
| 783 | PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); | ||
| 784 | PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]); | ||
| 785 | PR_EEP("Chain2 bswMargin", pModal->bswMargin[2]); | ||
| 786 | PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); | ||
| 787 | PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]); | ||
| 788 | PR_EEP("Chain1 xatten2Db", pModal->xatten2Db[1]); | ||
| 789 | PR_EEP("Chain2 xatten2Db", pModal->xatten2Db[2]); | ||
| 790 | PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]); | ||
| 791 | PR_EEP("Chain1 xatten2Margin", pModal->xatten2Margin[1]); | ||
| 792 | PR_EEP("Chain2 xatten2Margin", pModal->xatten2Margin[2]); | ||
| 793 | PR_EEP("Chain1 OutputBias", pModal->ob_ch1); | ||
| 794 | PR_EEP("Chain1 DriverBias", pModal->db_ch1); | ||
| 795 | PR_EEP("LNA Control", pModal->lna_ctl); | ||
| 796 | PR_EEP("XPA Bias Freq0", pModal->xpaBiasLvlFreq[0]); | ||
| 797 | PR_EEP("XPA Bias Freq1", pModal->xpaBiasLvlFreq[1]); | ||
| 798 | PR_EEP("XPA Bias Freq2", pModal->xpaBiasLvlFreq[2]); | ||
| 799 | |||
| 800 | if (len > size) | ||
| 801 | len = size; | ||
| 802 | |||
| 803 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 804 | kfree(buf); | ||
| 805 | |||
| 806 | return retval; | ||
| 807 | |||
| 808 | #undef PR_EEP | ||
| 809 | } | ||
| 810 | |||
| 811 | static ssize_t read_9287_modal_eeprom(struct file *file, | ||
| 812 | char __user *user_buf, | ||
| 813 | size_t count, loff_t *ppos) | ||
| 814 | { | ||
| 815 | #define PR_EEP(_s, _val) \ | ||
| 816 | do { \ | ||
| 817 | len += scnprintf(buf + len, size - len, "%20s : %10d\n",\ | ||
| 818 | _s, (_val)); \ | ||
| 819 | } while (0) | ||
| 820 | |||
| 821 | struct ath9k_htc_priv *priv = file->private_data; | ||
| 822 | struct modal_eep_ar9287_header *pModal = &priv->ah->eeprom.map9287.modalHeader; | ||
| 823 | unsigned int len = 0, size = 3000; | ||
| 824 | ssize_t retval = 0; | ||
| 825 | char *buf; | ||
| 826 | |||
| 827 | buf = kzalloc(size, GFP_KERNEL); | ||
| 828 | if (buf == NULL) | ||
| 829 | return -ENOMEM; | ||
| 830 | |||
| 831 | PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); | ||
| 832 | PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]); | ||
| 833 | PR_EEP("Ant. Common Control", pModal->antCtrlCommon); | ||
| 834 | PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); | ||
| 835 | PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]); | ||
| 836 | PR_EEP("Switch Settle", pModal->switchSettling); | ||
| 837 | PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); | ||
| 838 | PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]); | ||
| 839 | PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); | ||
| 840 | PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]); | ||
| 841 | PR_EEP("ADC Desired size", pModal->adcDesiredSize); | ||
| 842 | PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); | ||
| 843 | PR_EEP("txEndToRxOn", pModal->txEndToRxOn); | ||
| 844 | PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); | ||
| 845 | PR_EEP("CCA Threshold)", pModal->thresh62); | ||
| 846 | PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); | ||
| 847 | PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]); | ||
| 848 | PR_EEP("xpdGain", pModal->xpdGain); | ||
| 849 | PR_EEP("External PD", pModal->xpd); | ||
| 850 | PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); | ||
| 851 | PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]); | ||
| 852 | PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); | ||
| 853 | PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]); | ||
| 854 | PR_EEP("pdGainOverlap", pModal->pdGainOverlap); | ||
| 855 | PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); | ||
| 856 | PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); | ||
| 857 | PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); | ||
| 858 | PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); | ||
| 859 | PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); | ||
| 860 | PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]); | ||
| 861 | PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); | ||
| 862 | PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]); | ||
| 863 | PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); | ||
| 864 | PR_EEP("AR92x7 Version", pModal->version); | ||
| 865 | PR_EEP("DriverBias1", pModal->db1); | ||
| 866 | PR_EEP("DriverBias2", pModal->db1); | ||
| 867 | PR_EEP("CCK OutputBias", pModal->ob_cck); | ||
| 868 | PR_EEP("PSK OutputBias", pModal->ob_psk); | ||
| 869 | PR_EEP("QAM OutputBias", pModal->ob_qam); | ||
| 870 | PR_EEP("PAL_OFF OutputBias", pModal->ob_pal_off); | ||
| 871 | |||
| 872 | if (len > size) | ||
| 873 | len = size; | ||
| 874 | |||
| 875 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 876 | kfree(buf); | ||
| 877 | |||
| 878 | return retval; | ||
| 879 | |||
| 880 | #undef PR_EEP | ||
| 881 | } | ||
| 882 | |||
| 883 | static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf, | ||
| 884 | size_t count, loff_t *ppos) | ||
| 885 | { | ||
| 886 | struct ath9k_htc_priv *priv = file->private_data; | ||
| 887 | |||
| 888 | if (AR_SREV_9271(priv->ah)) | ||
| 889 | return read_4k_modal_eeprom(file, user_buf, count, ppos); | ||
| 890 | else if (priv->ah->hw_version.usbdev == AR9280_USB) | ||
| 891 | return read_def_modal_eeprom(file, user_buf, count, ppos); | ||
| 892 | else if (priv->ah->hw_version.usbdev == AR9287_USB) | ||
| 893 | return read_9287_modal_eeprom(file, user_buf, count, ppos); | ||
| 894 | |||
| 895 | return 0; | ||
| 896 | } | ||
| 897 | |||
| 898 | static const struct file_operations fops_modal_eeprom = { | ||
| 899 | .read = read_file_modal_eeprom, | ||
| 900 | .open = simple_open, | ||
| 901 | .owner = THIS_MODULE, | ||
| 902 | .llseek = default_llseek, | ||
| 903 | }; | ||
| 904 | |||
| 905 | |||
| 906 | /* Ethtool support for get-stats */ | 412 | /* Ethtool support for get-stats */ |
| 907 | #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO" | 413 | #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO" |
| 908 | static const char ath9k_htc_gstrings_stats[][ETH_GSTRING_LEN] = { | 414 | static const char ath9k_htc_gstrings_stats[][ETH_GSTRING_LEN] = { |
| @@ -947,6 +453,8 @@ int ath9k_htc_get_et_sset_count(struct ieee80211_hw *hw, | |||
| 947 | 453 | ||
| 948 | #define STXBASE priv->debug.tx_stats | 454 | #define STXBASE priv->debug.tx_stats |
| 949 | #define SRXBASE priv->debug.rx_stats | 455 | #define SRXBASE priv->debug.rx_stats |
| 456 | #define SKBTXBASE priv->debug.tx_stats | ||
| 457 | #define SKBRXBASE priv->debug.skbrx_stats | ||
| 950 | #define ASTXQ(a) \ | 458 | #define ASTXQ(a) \ |
| 951 | data[i++] = STXBASE.a[IEEE80211_AC_BE]; \ | 459 | data[i++] = STXBASE.a[IEEE80211_AC_BE]; \ |
| 952 | data[i++] = STXBASE.a[IEEE80211_AC_BK]; \ | 460 | data[i++] = STXBASE.a[IEEE80211_AC_BK]; \ |
| @@ -960,24 +468,24 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw, | |||
| 960 | struct ath9k_htc_priv *priv = hw->priv; | 468 | struct ath9k_htc_priv *priv = hw->priv; |
| 961 | int i = 0; | 469 | int i = 0; |
| 962 | 470 | ||
| 963 | data[i++] = STXBASE.skb_success; | 471 | data[i++] = SKBTXBASE.skb_success; |
| 964 | data[i++] = STXBASE.skb_success_bytes; | 472 | data[i++] = SKBTXBASE.skb_success_bytes; |
| 965 | data[i++] = SRXBASE.skb_completed; | 473 | data[i++] = SKBRXBASE.skb_completed; |
| 966 | data[i++] = SRXBASE.skb_completed_bytes; | 474 | data[i++] = SKBRXBASE.skb_completed_bytes; |
| 967 | 475 | ||
| 968 | ASTXQ(queue_stats); | 476 | ASTXQ(queue_stats); |
| 969 | 477 | ||
| 970 | data[i++] = SRXBASE.err_crc; | 478 | data[i++] = SRXBASE.crc_err; |
| 971 | data[i++] = SRXBASE.err_decrypt_crc; | 479 | data[i++] = SRXBASE.decrypt_crc_err; |
| 972 | data[i++] = SRXBASE.err_phy; | 480 | data[i++] = SRXBASE.phy_err; |
| 973 | data[i++] = SRXBASE.err_mic; | 481 | data[i++] = SRXBASE.mic_err; |
| 974 | data[i++] = SRXBASE.err_pre_delim; | 482 | data[i++] = SRXBASE.pre_delim_crc_err; |
| 975 | data[i++] = SRXBASE.err_post_delim; | 483 | data[i++] = SRXBASE.post_delim_crc_err; |
| 976 | data[i++] = SRXBASE.err_decrypt_busy; | 484 | data[i++] = SRXBASE.decrypt_busy_err; |
| 977 | 485 | ||
| 978 | data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_RADAR]; | 486 | data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_RADAR]; |
| 979 | data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_OFDM_TIMING]; | 487 | data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_OFDM_TIMING]; |
| 980 | data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_CCK_TIMING]; | 488 | data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_CCK_TIMING]; |
| 981 | 489 | ||
| 982 | WARN_ON(i != ATH9K_HTC_SSTATS_LEN); | 490 | WARN_ON(i != ATH9K_HTC_SSTATS_LEN); |
| 983 | } | 491 | } |
| @@ -1001,18 +509,21 @@ int ath9k_htc_init_debug(struct ath_hw *ah) | |||
| 1001 | priv, &fops_tgt_rx_stats); | 509 | priv, &fops_tgt_rx_stats); |
| 1002 | debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy, | 510 | debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy, |
| 1003 | priv, &fops_xmit); | 511 | priv, &fops_xmit); |
| 1004 | debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy, | 512 | debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy, |
| 1005 | priv, &fops_recv); | 513 | priv, &fops_skb_rx); |
| 514 | |||
| 515 | ath9k_cmn_debug_recv(priv->debug.debugfs_phy, &priv->debug.rx_stats); | ||
| 516 | ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, &priv->debug.rx_stats); | ||
| 517 | |||
| 1006 | debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, | 518 | debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, |
| 1007 | priv, &fops_slot); | 519 | priv, &fops_slot); |
| 1008 | debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy, | 520 | debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy, |
| 1009 | priv, &fops_queue); | 521 | priv, &fops_queue); |
| 1010 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy, | 522 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy, |
| 1011 | priv, &fops_debug); | 523 | priv, &fops_debug); |
| 1012 | debugfs_create_file("base_eeprom", S_IRUSR, priv->debug.debugfs_phy, | 524 | |
| 1013 | priv, &fops_base_eeprom); | 525 | ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah); |
| 1014 | debugfs_create_file("modal_eeprom", S_IRUSR, priv->debug.debugfs_phy, | 526 | ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah); |
| 1015 | priv, &fops_modal_eeprom); | ||
| 1016 | 527 | ||
| 1017 | return 0; | 528 | return 0; |
| 1018 | } | 529 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 289f3d8924b5..bb86eb2ffc95 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
| @@ -996,8 +996,6 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
| 996 | goto rx_next; | 996 | goto rx_next; |
| 997 | } | 997 | } |
| 998 | 998 | ||
| 999 | ath9k_htc_err_stat_rx(priv, rxstatus); | ||
| 1000 | |||
| 1001 | /* Get the RX status information */ | 999 | /* Get the RX status information */ |
| 1002 | 1000 | ||
| 1003 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); | 1001 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); |
| @@ -1005,6 +1003,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
| 1005 | /* Copy everything from ath_htc_rx_status (HTC_RX_FRAME_HEADER). | 1003 | /* Copy everything from ath_htc_rx_status (HTC_RX_FRAME_HEADER). |
| 1006 | * After this, we can drop this part of skb. */ | 1004 | * After this, we can drop this part of skb. */ |
| 1007 | rx_status_htc_to_ath(&rx_stats, rxstatus); | 1005 | rx_status_htc_to_ath(&rx_stats, rxstatus); |
| 1006 | ath9k_htc_err_stat_rx(priv, &rx_stats); | ||
| 1008 | rx_status->mactime = be64_to_cpu(rxstatus->rs_tstamp); | 1007 | rx_status->mactime = be64_to_cpu(rxstatus->rs_tstamp); |
| 1009 | skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); | 1008 | skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); |
| 1010 | 1009 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c8a9dfab1fee..2a8ed8375ec0 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include "ar9003_mac.h" | 26 | #include "ar9003_mac.h" |
| 27 | #include "ar9003_mci.h" | 27 | #include "ar9003_mci.h" |
| 28 | #include "ar9003_phy.h" | 28 | #include "ar9003_phy.h" |
| 29 | #include "debug.h" | ||
| 30 | #include "ath9k.h" | 29 | #include "ath9k.h" |
| 31 | 30 | ||
| 32 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); | 31 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); |
| @@ -246,6 +245,8 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) | |||
| 246 | return; | 245 | return; |
| 247 | case AR9300_DEVID_AR953X: | 246 | case AR9300_DEVID_AR953X: |
| 248 | ah->hw_version.macVersion = AR_SREV_VERSION_9531; | 247 | ah->hw_version.macVersion = AR_SREV_VERSION_9531; |
| 248 | if (ah->get_mac_revision) | ||
| 249 | ah->hw_version.macRev = ah->get_mac_revision(); | ||
| 249 | return; | 250 | return; |
| 250 | } | 251 | } |
| 251 | 252 | ||
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 4243509616bd..1af77081181e 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
| @@ -508,7 +508,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
| 508 | sc->tx99_power = MAX_RATE_POWER + 1; | 508 | sc->tx99_power = MAX_RATE_POWER + 1; |
| 509 | init_waitqueue_head(&sc->tx_wait); | 509 | init_waitqueue_head(&sc->tx_wait); |
| 510 | 510 | ||
| 511 | if (!pdata) { | 511 | if (!pdata || pdata->use_eeprom) { |
| 512 | ah->ah_flags |= AH_USE_EEPROM; | 512 | ah->ah_flags |= AH_USE_EEPROM; |
| 513 | sc->sc_ah->led_pin = -1; | 513 | sc->sc_ah->led_pin = -1; |
| 514 | } else { | 514 | } else { |
| @@ -714,7 +714,8 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
| 714 | if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) | 714 | if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) |
| 715 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | 715 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; |
| 716 | 716 | ||
| 717 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; | 717 | hw->wiphy->features |= (NL80211_FEATURE_ACTIVE_MONITOR | |
| 718 | NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE); | ||
| 718 | 719 | ||
| 719 | if (!config_enabled(CONFIG_ATH9K_TX99)) { | 720 | if (!config_enabled(CONFIG_ATH9K_TX99)) { |
| 720 | hw->wiphy->interface_modes = | 721 | hw->wiphy->interface_modes = |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 51ce36f108f9..275205ab5f15 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
| @@ -958,3 +958,25 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah) | |||
| 958 | return; | 958 | return; |
| 959 | } | 959 | } |
| 960 | EXPORT_SYMBOL(ath9k_hw_set_interrupts); | 960 | EXPORT_SYMBOL(ath9k_hw_set_interrupts); |
| 961 | |||
| 962 | #define ATH9K_HW_MAX_DCU 10 | ||
| 963 | #define ATH9K_HW_SLICE_PER_DCU 16 | ||
| 964 | #define ATH9K_HW_BIT_IN_SLICE 16 | ||
| 965 | void ath9k_hw_set_tx_filter(struct ath_hw *ah, u8 destidx, bool set) | ||
| 966 | { | ||
| 967 | int dcu_idx; | ||
| 968 | u32 filter; | ||
| 969 | |||
| 970 | for (dcu_idx = 0; dcu_idx < 10; dcu_idx++) { | ||
| 971 | filter = SM(set, AR_D_TXBLK_WRITE_COMMAND); | ||
| 972 | filter |= SM(dcu_idx, AR_D_TXBLK_WRITE_DCU); | ||
| 973 | filter |= SM((destidx / ATH9K_HW_SLICE_PER_DCU), | ||
| 974 | AR_D_TXBLK_WRITE_SLICE); | ||
| 975 | filter |= BIT(destidx % ATH9K_HW_BIT_IN_SLICE); | ||
| 976 | ath_dbg(ath9k_hw_common(ah), PS, | ||
| 977 | "DCU%d staid %d set %d txfilter %08x\n", | ||
| 978 | dcu_idx, destidx, set, filter); | ||
| 979 | REG_WRITE(ah, AR_D_TXBLK_BASE, filter); | ||
| 980 | } | ||
| 981 | } | ||
| 982 | EXPORT_SYMBOL(ath9k_hw_set_tx_filter); | ||
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 89df634e81f9..da7686757535 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
| @@ -729,6 +729,7 @@ void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning); | |||
| 729 | void ath9k_hw_abortpcurecv(struct ath_hw *ah); | 729 | void ath9k_hw_abortpcurecv(struct ath_hw *ah); |
| 730 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset); | 730 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset); |
| 731 | int ath9k_hw_beaconq_setup(struct ath_hw *ah); | 731 | int ath9k_hw_beaconq_setup(struct ath_hw *ah); |
| 732 | void ath9k_hw_set_tx_filter(struct ath_hw *ah, u8 destidx, bool set); | ||
| 732 | 733 | ||
| 733 | /* Interrupt Handling */ | 734 | /* Interrupt Handling */ |
| 734 | bool ath9k_hw_intrpend(struct ath_hw *ah); | 735 | bool ath9k_hw_intrpend(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 8d7b9b66fefa..6965ceac7bc6 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -421,6 +421,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
| 421 | an->sc = sc; | 421 | an->sc = sc; |
| 422 | an->sta = sta; | 422 | an->sta = sta; |
| 423 | an->vif = vif; | 423 | an->vif = vif; |
| 424 | memset(&an->key_idx, 0, sizeof(an->key_idx)); | ||
| 424 | 425 | ||
| 425 | ath_tx_node_init(sc, an); | 426 | ath_tx_node_init(sc, an); |
| 426 | } | 427 | } |
| @@ -1461,8 +1462,10 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, | |||
| 1461 | return 0; | 1462 | return 0; |
| 1462 | 1463 | ||
| 1463 | key = ath_key_config(common, vif, sta, &ps_key); | 1464 | key = ath_key_config(common, vif, sta, &ps_key); |
| 1464 | if (key > 0) | 1465 | if (key > 0) { |
| 1465 | an->ps_key = key; | 1466 | an->ps_key = key; |
| 1467 | an->key_idx[0] = key; | ||
| 1468 | } | ||
| 1466 | 1469 | ||
| 1467 | return 0; | 1470 | return 0; |
| 1468 | } | 1471 | } |
| @@ -1480,6 +1483,7 @@ static void ath9k_del_ps_key(struct ath_softc *sc, | |||
| 1480 | 1483 | ||
| 1481 | ath_key_delete(common, &ps_key); | 1484 | ath_key_delete(common, &ps_key); |
| 1482 | an->ps_key = 0; | 1485 | an->ps_key = 0; |
| 1486 | an->key_idx[0] = 0; | ||
| 1483 | } | 1487 | } |
| 1484 | 1488 | ||
| 1485 | static int ath9k_sta_remove(struct ieee80211_hw *hw, | 1489 | static int ath9k_sta_remove(struct ieee80211_hw *hw, |
| @@ -1494,6 +1498,19 @@ static int ath9k_sta_remove(struct ieee80211_hw *hw, | |||
| 1494 | return 0; | 1498 | return 0; |
| 1495 | } | 1499 | } |
| 1496 | 1500 | ||
| 1501 | static void ath9k_sta_set_tx_filter(struct ath_hw *ah, | ||
| 1502 | struct ath_node *an, | ||
| 1503 | bool set) | ||
| 1504 | { | ||
| 1505 | int i; | ||
| 1506 | |||
| 1507 | for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) { | ||
| 1508 | if (!an->key_idx[i]) | ||
| 1509 | continue; | ||
| 1510 | ath9k_hw_set_tx_filter(ah, an->key_idx[i], set); | ||
| 1511 | } | ||
| 1512 | } | ||
| 1513 | |||
| 1497 | static void ath9k_sta_notify(struct ieee80211_hw *hw, | 1514 | static void ath9k_sta_notify(struct ieee80211_hw *hw, |
| 1498 | struct ieee80211_vif *vif, | 1515 | struct ieee80211_vif *vif, |
| 1499 | enum sta_notify_cmd cmd, | 1516 | enum sta_notify_cmd cmd, |
| @@ -1506,8 +1523,10 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, | |||
| 1506 | case STA_NOTIFY_SLEEP: | 1523 | case STA_NOTIFY_SLEEP: |
| 1507 | an->sleeping = true; | 1524 | an->sleeping = true; |
| 1508 | ath_tx_aggr_sleep(sta, sc, an); | 1525 | ath_tx_aggr_sleep(sta, sc, an); |
| 1526 | ath9k_sta_set_tx_filter(sc->sc_ah, an, true); | ||
| 1509 | break; | 1527 | break; |
| 1510 | case STA_NOTIFY_AWAKE: | 1528 | case STA_NOTIFY_AWAKE: |
| 1529 | ath9k_sta_set_tx_filter(sc->sc_ah, an, false); | ||
| 1511 | an->sleeping = false; | 1530 | an->sleeping = false; |
| 1512 | ath_tx_aggr_wakeup(sc, an); | 1531 | ath_tx_aggr_wakeup(sc, an); |
| 1513 | break; | 1532 | break; |
| @@ -1563,7 +1582,8 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
| 1563 | { | 1582 | { |
| 1564 | struct ath_softc *sc = hw->priv; | 1583 | struct ath_softc *sc = hw->priv; |
| 1565 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1584 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 1566 | int ret = 0; | 1585 | struct ath_node *an = NULL; |
| 1586 | int ret = 0, i; | ||
| 1567 | 1587 | ||
| 1568 | if (ath9k_modparam_nohwcrypt) | 1588 | if (ath9k_modparam_nohwcrypt) |
| 1569 | return -ENOSPC; | 1589 | return -ENOSPC; |
| @@ -1585,13 +1605,16 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
| 1585 | 1605 | ||
| 1586 | mutex_lock(&sc->mutex); | 1606 | mutex_lock(&sc->mutex); |
| 1587 | ath9k_ps_wakeup(sc); | 1607 | ath9k_ps_wakeup(sc); |
| 1588 | ath_dbg(common, CONFIG, "Set HW Key\n"); | 1608 | ath_dbg(common, CONFIG, "Set HW Key %d\n", cmd); |
| 1609 | if (sta) | ||
| 1610 | an = (struct ath_node *)sta->drv_priv; | ||
| 1589 | 1611 | ||
| 1590 | switch (cmd) { | 1612 | switch (cmd) { |
| 1591 | case SET_KEY: | 1613 | case SET_KEY: |
| 1592 | if (sta) | 1614 | if (sta) |
| 1593 | ath9k_del_ps_key(sc, vif, sta); | 1615 | ath9k_del_ps_key(sc, vif, sta); |
| 1594 | 1616 | ||
| 1617 | key->hw_key_idx = 0; | ||
| 1595 | ret = ath_key_config(common, vif, sta, key); | 1618 | ret = ath_key_config(common, vif, sta, key); |
| 1596 | if (ret >= 0) { | 1619 | if (ret >= 0) { |
| 1597 | key->hw_key_idx = ret; | 1620 | key->hw_key_idx = ret; |
| @@ -1604,9 +1627,27 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
| 1604 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; | 1627 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; |
| 1605 | ret = 0; | 1628 | ret = 0; |
| 1606 | } | 1629 | } |
| 1630 | if (an && key->hw_key_idx) { | ||
| 1631 | for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) { | ||
| 1632 | if (an->key_idx[i]) | ||
| 1633 | continue; | ||
| 1634 | an->key_idx[i] = key->hw_key_idx; | ||
| 1635 | break; | ||
| 1636 | } | ||
| 1637 | WARN_ON(i == ARRAY_SIZE(an->key_idx)); | ||
| 1638 | } | ||
| 1607 | break; | 1639 | break; |
| 1608 | case DISABLE_KEY: | 1640 | case DISABLE_KEY: |
| 1609 | ath_key_delete(common, key); | 1641 | ath_key_delete(common, key); |
| 1642 | if (an) { | ||
| 1643 | for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) { | ||
| 1644 | if (an->key_idx[i] != key->hw_key_idx) | ||
| 1645 | continue; | ||
| 1646 | an->key_idx[i] = 0; | ||
| 1647 | break; | ||
| 1648 | } | ||
| 1649 | } | ||
| 1650 | key->hw_key_idx = 0; | ||
| 1610 | break; | 1651 | break; |
| 1611 | default: | 1652 | default: |
| 1612 | ret = -EINVAL; | 1653 | ret = -EINVAL; |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 914dbc6b1720..4dec09e565ed 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
| @@ -686,7 +686,7 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) | |||
| 686 | struct ath_softc *sc = (struct ath_softc *) common->priv; | 686 | struct ath_softc *sc = (struct ath_softc *) common->priv; |
| 687 | struct ath9k_platform_data *pdata = sc->dev->platform_data; | 687 | struct ath9k_platform_data *pdata = sc->dev->platform_data; |
| 688 | 688 | ||
| 689 | if (pdata) { | 689 | if (pdata && !pdata->use_eeprom) { |
| 690 | if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { | 690 | if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { |
| 691 | ath_err(common, | 691 | ath_err(common, |
| 692 | "%s: eeprom read failed, offset %08x is out of range\n", | 692 | "%s: eeprom read failed, offset %08x is out of range\n", |
| @@ -914,6 +914,7 @@ static int ath_pci_suspend(struct device *device) | |||
| 914 | */ | 914 | */ |
| 915 | ath9k_stop_btcoex(sc); | 915 | ath9k_stop_btcoex(sc); |
| 916 | ath9k_hw_disable(sc->sc_ah); | 916 | ath9k_hw_disable(sc->sc_ah); |
| 917 | del_timer_sync(&sc->sleep_timer); | ||
| 917 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); | 918 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); |
| 918 | 919 | ||
| 919 | return 0; | 920 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 441c71448e4c..43ae199601f7 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
| @@ -538,8 +538,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
| 538 | sc->ps_flags &= ~PS_BEACON_SYNC; | 538 | sc->ps_flags &= ~PS_BEACON_SYNC; |
| 539 | ath_dbg(common, PS, | 539 | ath_dbg(common, PS, |
| 540 | "Reconfigure beacon timers based on synchronized timestamp\n"); | 540 | "Reconfigure beacon timers based on synchronized timestamp\n"); |
| 541 | ath9k_set_beacon(sc); | 541 | if (!(WARN_ON_ONCE(sc->cur_beacon_conf.beacon_interval == 0))) |
| 542 | 542 | ath9k_set_beacon(sc); | |
| 543 | if (sc->p2p_ps_vif) | 543 | if (sc->p2p_ps_vif) |
| 544 | ath9k_update_p2p_ps(sc, sc->p2p_ps_vif->vif); | 544 | ath9k_update_p2p_ps(sc, sc->p2p_ps_vif->vif); |
| 545 | } | 545 | } |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index b1fd3fa84983..f1bbce3f7774 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
| @@ -505,9 +505,6 @@ | |||
| 505 | #define AR_D_QCUMASK 0x000003FF | 505 | #define AR_D_QCUMASK 0x000003FF |
| 506 | #define AR_D_QCUMASK_RESV0 0xFFFFFC00 | 506 | #define AR_D_QCUMASK_RESV0 0xFFFFFC00 |
| 507 | 507 | ||
| 508 | #define AR_D_TXBLK_CMD 0x1038 | ||
| 509 | #define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) | ||
| 510 | |||
| 511 | #define AR_D0_LCL_IFS 0x1040 | 508 | #define AR_D0_LCL_IFS 0x1040 |
| 512 | #define AR_D1_LCL_IFS 0x1044 | 509 | #define AR_D1_LCL_IFS 0x1044 |
| 513 | #define AR_D2_LCL_IFS 0x1048 | 510 | #define AR_D2_LCL_IFS 0x1048 |
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index ca115f33746f..f35c7f30f9a6 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c | |||
| @@ -1076,8 +1076,14 @@ static int carl9170_usb_probe(struct usb_interface *intf, | |||
| 1076 | 1076 | ||
| 1077 | carl9170_set_state(ar, CARL9170_STOPPED); | 1077 | carl9170_set_state(ar, CARL9170_STOPPED); |
| 1078 | 1078 | ||
| 1079 | return request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME, | 1079 | err = request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME, |
| 1080 | &ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2); | 1080 | &ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2); |
| 1081 | if (err) { | ||
| 1082 | usb_put_dev(udev); | ||
| 1083 | usb_put_dev(udev); | ||
| 1084 | carl9170_free(ar); | ||
| 1085 | } | ||
| 1086 | return err; | ||
| 1081 | } | 1087 | } |
| 1082 | 1088 | ||
| 1083 | static void carl9170_usb_disconnect(struct usb_interface *intf) | 1089 | static void carl9170_usb_disconnect(struct usb_interface *intf) |
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c index a1a69c5db409..650be79c7ac9 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.c +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c | |||
| @@ -73,9 +73,52 @@ static const struct radar_types etsi_radar_types_v15 = { | |||
| 73 | .radar_types = etsi_radar_ref_types_v15, | 73 | .radar_types = etsi_radar_ref_types_v15, |
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| 76 | /* for now, we support ETSI radar types, FCC and JP are TODO */ | 76 | #define FCC_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB) \ |
| 77 | { \ | ||
| 78 | ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \ | ||
| 79 | PMIN - PRI_TOLERANCE, \ | ||
| 80 | PMAX * PRF + PRI_TOLERANCE, PRF, PPB * PRF, \ | ||
| 81 | PPB_THRESH(PPB), PRI_TOLERANCE, \ | ||
| 82 | } | ||
| 83 | |||
| 84 | static const struct radar_detector_specs fcc_radar_ref_types[] = { | ||
| 85 | FCC_PATTERN(0, 0, 1, 1428, 1428, 1, 18), | ||
| 86 | FCC_PATTERN(1, 0, 5, 150, 230, 1, 23), | ||
| 87 | FCC_PATTERN(2, 6, 10, 200, 500, 1, 16), | ||
| 88 | FCC_PATTERN(3, 11, 20, 200, 500, 1, 12), | ||
| 89 | FCC_PATTERN(4, 50, 100, 1000, 2000, 20, 1), | ||
| 90 | FCC_PATTERN(5, 0, 1, 333, 333, 1, 9), | ||
| 91 | }; | ||
| 92 | |||
| 93 | static const struct radar_types fcc_radar_types = { | ||
| 94 | .region = NL80211_DFS_FCC, | ||
| 95 | .num_radar_types = ARRAY_SIZE(fcc_radar_ref_types), | ||
| 96 | .radar_types = fcc_radar_ref_types, | ||
| 97 | }; | ||
| 98 | |||
| 99 | #define JP_PATTERN FCC_PATTERN | ||
| 100 | static const struct radar_detector_specs jp_radar_ref_types[] = { | ||
| 101 | JP_PATTERN(0, 0, 1, 1428, 1428, 1, 18), | ||
| 102 | JP_PATTERN(1, 2, 3, 3846, 3846, 1, 18), | ||
| 103 | JP_PATTERN(2, 0, 1, 1388, 1388, 1, 18), | ||
| 104 | JP_PATTERN(3, 1, 2, 4000, 4000, 1, 18), | ||
| 105 | JP_PATTERN(4, 0, 5, 150, 230, 1, 23), | ||
| 106 | JP_PATTERN(5, 6, 10, 200, 500, 1, 16), | ||
| 107 | JP_PATTERN(6, 11, 20, 200, 500, 1, 12), | ||
| 108 | JP_PATTERN(7, 50, 100, 1000, 2000, 20, 1), | ||
| 109 | JP_PATTERN(5, 0, 1, 333, 333, 1, 9), | ||
| 110 | }; | ||
| 111 | |||
| 112 | static const struct radar_types jp_radar_types = { | ||
| 113 | .region = NL80211_DFS_JP, | ||
| 114 | .num_radar_types = ARRAY_SIZE(jp_radar_ref_types), | ||
| 115 | .radar_types = jp_radar_ref_types, | ||
| 116 | }; | ||
| 117 | |||
| 77 | static const struct radar_types *dfs_domains[] = { | 118 | static const struct radar_types *dfs_domains[] = { |
| 78 | &etsi_radar_types_v15, | 119 | &etsi_radar_types_v15, |
| 120 | &fcc_radar_types, | ||
| 121 | &jp_radar_types, | ||
| 79 | }; | 122 | }; |
| 80 | 123 | ||
| 81 | /** | 124 | /** |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 4806a49cb61b..6e699d050d1e 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
| @@ -172,7 +172,7 @@ static int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, | |||
| 172 | 172 | ||
| 173 | static int wil_cfg80211_get_station(struct wiphy *wiphy, | 173 | static int wil_cfg80211_get_station(struct wiphy *wiphy, |
| 174 | struct net_device *ndev, | 174 | struct net_device *ndev, |
| 175 | u8 *mac, struct station_info *sinfo) | 175 | const u8 *mac, struct station_info *sinfo) |
| 176 | { | 176 | { |
| 177 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 177 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
| 178 | int rc; | 178 | int rc; |
| @@ -671,7 +671,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | |||
| 671 | } | 671 | } |
| 672 | 672 | ||
| 673 | static int wil_cfg80211_del_station(struct wiphy *wiphy, | 673 | static int wil_cfg80211_del_station(struct wiphy *wiphy, |
| 674 | struct net_device *dev, u8 *mac) | 674 | struct net_device *dev, const u8 *mac) |
| 675 | { | 675 | { |
| 676 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 676 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
| 677 | 677 | ||
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 1b265fd19de2..670cc6de3b4c 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
| @@ -81,7 +81,7 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) | |||
| 81 | memset(&sta->stats, 0, sizeof(sta->stats)); | 81 | memset(&sta->stats, 0, sizeof(sta->stats)); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) | 84 | static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) |
| 85 | { | 85 | { |
| 86 | int cid = -ENOENT; | 86 | int cid = -ENOENT; |
| 87 | struct net_device *ndev = wil_to_ndev(wil); | 87 | struct net_device *ndev = wil_to_ndev(wil); |
| @@ -252,7 +252,7 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
| 252 | return 0; | 252 | return 0; |
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid) | 255 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) |
| 256 | { | 256 | { |
| 257 | del_timer_sync(&wil->connect_timer); | 257 | del_timer_sync(&wil->connect_timer); |
| 258 | _wil6210_disconnect(wil, bssid); | 258 | _wil6210_disconnect(wil, bssid); |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index d3b8659ca32e..3427ac4a4fa1 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
| @@ -508,7 +508,7 @@ void wil_wdev_free(struct wil6210_priv *wil); | |||
| 508 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); | 508 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); |
| 509 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); | 509 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); |
| 510 | int wmi_pcp_stop(struct wil6210_priv *wil); | 510 | int wmi_pcp_stop(struct wil6210_priv *wil); |
| 511 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); | 511 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid); |
| 512 | 512 | ||
| 513 | int wil_rx_init(struct wil6210_priv *wil); | 513 | int wil_rx_init(struct wil6210_priv *wil); |
| 514 | void wil_rx_fini(struct wil6210_priv *wil); | 514 | void wil_rx_fini(struct wil6210_priv *wil); |
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 088d544ec63f..e3f67b8d3f80 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | config B43 | 1 | config B43 |
| 2 | tristate "Broadcom 43xx wireless support (mac80211 stack)" | 2 | tristate "Broadcom 43xx wireless support (mac80211 stack)" |
| 3 | depends on SSB_POSSIBLE && MAC80211 && HAS_DMA | 3 | depends on (BCMA_POSSIBLE || SSB_POSSIBLE) && MAC80211 && HAS_DMA |
| 4 | select SSB | 4 | select BCMA if B43_BCMA |
| 5 | select SSB if B43_SSB | ||
| 5 | select FW_LOADER | 6 | select FW_LOADER |
| 6 | ---help--- | 7 | ---help--- |
| 7 | b43 is a driver for the Broadcom 43xx series wireless devices. | 8 | b43 is a driver for the Broadcom 43xx series wireless devices. |
| @@ -27,14 +28,33 @@ config B43 | |||
| 27 | If unsure, say M. | 28 | If unsure, say M. |
| 28 | 29 | ||
| 29 | config B43_BCMA | 30 | config B43_BCMA |
| 30 | bool "Support for BCMA bus" | 31 | bool |
| 31 | depends on B43 && (BCMA = y || BCMA = B43) | ||
| 32 | default y | ||
| 33 | 32 | ||
| 34 | config B43_SSB | 33 | config B43_SSB |
| 35 | bool | 34 | bool |
| 36 | depends on B43 && (SSB = y || SSB = B43) | 35 | |
| 37 | default y | 36 | choice |
| 37 | prompt "Supported bus types" | ||
| 38 | depends on B43 | ||
| 39 | default B43_BCMA_AND_SSB | ||
| 40 | |||
| 41 | config B43_BUSES_BCMA_AND_SSB | ||
| 42 | bool "BCMA and SSB" | ||
| 43 | depends on BCMA_POSSIBLE && SSB_POSSIBLE | ||
| 44 | select B43_BCMA | ||
| 45 | select B43_SSB | ||
| 46 | |||
| 47 | config B43_BUSES_BCMA | ||
| 48 | bool "BCMA only" | ||
| 49 | depends on BCMA_POSSIBLE | ||
| 50 | select B43_BCMA | ||
| 51 | |||
| 52 | config B43_BUSES_SSB | ||
| 53 | bool "SSB only" | ||
| 54 | depends on SSB_POSSIBLE | ||
| 55 | select B43_SSB | ||
| 56 | |||
| 57 | endchoice | ||
| 38 | 58 | ||
| 39 | # Auto-select SSB PCI-HOST support, if possible | 59 | # Auto-select SSB PCI-HOST support, if possible |
| 40 | config B43_PCI_AUTOSELECT | 60 | config B43_PCI_AUTOSELECT |
| @@ -53,7 +73,7 @@ config B43_PCICORE_AUTOSELECT | |||
| 53 | 73 | ||
| 54 | config B43_PCMCIA | 74 | config B43_PCMCIA |
| 55 | bool "Broadcom 43xx PCMCIA device support" | 75 | bool "Broadcom 43xx PCMCIA device support" |
| 56 | depends on B43 && SSB_PCMCIAHOST_POSSIBLE | 76 | depends on B43 && B43_SSB && SSB_PCMCIAHOST_POSSIBLE |
| 57 | select SSB_PCMCIAHOST | 77 | select SSB_PCMCIAHOST |
| 58 | ---help--- | 78 | ---help--- |
| 59 | Broadcom 43xx PCMCIA device support. | 79 | Broadcom 43xx PCMCIA device support. |
| @@ -73,7 +93,7 @@ config B43_PCMCIA | |||
| 73 | 93 | ||
| 74 | config B43_SDIO | 94 | config B43_SDIO |
| 75 | bool "Broadcom 43xx SDIO device support" | 95 | bool "Broadcom 43xx SDIO device support" |
| 76 | depends on B43 && SSB_SDIOHOST_POSSIBLE | 96 | depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE |
| 77 | select SSB_SDIOHOST | 97 | select SSB_SDIOHOST |
| 78 | ---help--- | 98 | ---help--- |
| 79 | Broadcom 43xx device support for Soft-MAC SDIO devices. | 99 | Broadcom 43xx device support for Soft-MAC SDIO devices. |
| @@ -98,7 +118,7 @@ config B43_BCMA_PIO | |||
| 98 | 118 | ||
| 99 | config B43_PIO | 119 | config B43_PIO |
| 100 | bool | 120 | bool |
| 101 | depends on B43 | 121 | depends on B43 && B43_SSB |
| 102 | select SSB_BLOCKIO | 122 | select SSB_BLOCKIO |
| 103 | default y | 123 | default y |
| 104 | 124 | ||
| @@ -116,7 +136,7 @@ config B43_PHY_N | |||
| 116 | 136 | ||
| 117 | config B43_PHY_LP | 137 | config B43_PHY_LP |
| 118 | bool "Support for low-power (LP-PHY) devices" | 138 | bool "Support for low-power (LP-PHY) devices" |
| 119 | depends on B43 | 139 | depends on B43 && B43_SSB |
| 120 | default y | 140 | default y |
| 121 | ---help--- | 141 | ---help--- |
| 122 | Support for the LP-PHY. | 142 | Support for the LP-PHY. |
diff --git a/drivers/net/wireless/b43/bus.h b/drivers/net/wireless/b43/bus.h index 184c95659279..f3205c6988bc 100644 --- a/drivers/net/wireless/b43/bus.h +++ b/drivers/net/wireless/b43/bus.h | |||
| @@ -5,7 +5,9 @@ enum b43_bus_type { | |||
| 5 | #ifdef CONFIG_B43_BCMA | 5 | #ifdef CONFIG_B43_BCMA |
| 6 | B43_BUS_BCMA, | 6 | B43_BUS_BCMA, |
| 7 | #endif | 7 | #endif |
| 8 | #ifdef CONFIG_B43_SSB | ||
| 8 | B43_BUS_SSB, | 9 | B43_BUS_SSB, |
| 10 | #endif | ||
| 9 | }; | 11 | }; |
| 10 | 12 | ||
| 11 | struct b43_bus_dev { | 13 | struct b43_bus_dev { |
| @@ -52,13 +54,21 @@ struct b43_bus_dev { | |||
| 52 | 54 | ||
| 53 | static inline bool b43_bus_host_is_pcmcia(struct b43_bus_dev *dev) | 55 | static inline bool b43_bus_host_is_pcmcia(struct b43_bus_dev *dev) |
| 54 | { | 56 | { |
| 57 | #ifdef CONFIG_B43_SSB | ||
| 55 | return (dev->bus_type == B43_BUS_SSB && | 58 | return (dev->bus_type == B43_BUS_SSB && |
| 56 | dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA); | 59 | dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA); |
| 60 | #else | ||
| 61 | return false; | ||
| 62 | #endif | ||
| 57 | } | 63 | } |
| 58 | static inline bool b43_bus_host_is_sdio(struct b43_bus_dev *dev) | 64 | static inline bool b43_bus_host_is_sdio(struct b43_bus_dev *dev) |
| 59 | { | 65 | { |
| 66 | #ifdef CONFIG_B43_SSB | ||
| 60 | return (dev->bus_type == B43_BUS_SSB && | 67 | return (dev->bus_type == B43_BUS_SSB && |
| 61 | dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO); | 68 | dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO); |
| 69 | #else | ||
| 70 | return false; | ||
| 71 | #endif | ||
| 62 | } | 72 | } |
| 63 | 73 | ||
| 64 | struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core); | 74 | struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core); |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 32e08d35c06e..3d67e6b08e1c 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -182,7 +182,7 @@ static struct ieee80211_rate __b43_ratetable[] = { | |||
| 182 | #define b43_g_ratetable (__b43_ratetable + 0) | 182 | #define b43_g_ratetable (__b43_ratetable + 0) |
| 183 | #define b43_g_ratetable_size 12 | 183 | #define b43_g_ratetable_size 12 |
| 184 | 184 | ||
| 185 | #define CHAN4G(_channel, _freq, _flags) { \ | 185 | #define CHAN2G(_channel, _freq, _flags) { \ |
| 186 | .band = IEEE80211_BAND_2GHZ, \ | 186 | .band = IEEE80211_BAND_2GHZ, \ |
| 187 | .center_freq = (_freq), \ | 187 | .center_freq = (_freq), \ |
| 188 | .hw_value = (_channel), \ | 188 | .hw_value = (_channel), \ |
| @@ -191,23 +191,31 @@ static struct ieee80211_rate __b43_ratetable[] = { | |||
| 191 | .max_power = 30, \ | 191 | .max_power = 30, \ |
| 192 | } | 192 | } |
| 193 | static struct ieee80211_channel b43_2ghz_chantable[] = { | 193 | static struct ieee80211_channel b43_2ghz_chantable[] = { |
| 194 | CHAN4G(1, 2412, 0), | 194 | CHAN2G(1, 2412, 0), |
| 195 | CHAN4G(2, 2417, 0), | 195 | CHAN2G(2, 2417, 0), |
| 196 | CHAN4G(3, 2422, 0), | 196 | CHAN2G(3, 2422, 0), |
| 197 | CHAN4G(4, 2427, 0), | 197 | CHAN2G(4, 2427, 0), |
| 198 | CHAN4G(5, 2432, 0), | 198 | CHAN2G(5, 2432, 0), |
| 199 | CHAN4G(6, 2437, 0), | 199 | CHAN2G(6, 2437, 0), |
| 200 | CHAN4G(7, 2442, 0), | 200 | CHAN2G(7, 2442, 0), |
| 201 | CHAN4G(8, 2447, 0), | 201 | CHAN2G(8, 2447, 0), |
| 202 | CHAN4G(9, 2452, 0), | 202 | CHAN2G(9, 2452, 0), |
| 203 | CHAN4G(10, 2457, 0), | 203 | CHAN2G(10, 2457, 0), |
| 204 | CHAN4G(11, 2462, 0), | 204 | CHAN2G(11, 2462, 0), |
| 205 | CHAN4G(12, 2467, 0), | 205 | CHAN2G(12, 2467, 0), |
| 206 | CHAN4G(13, 2472, 0), | 206 | CHAN2G(13, 2472, 0), |
| 207 | CHAN4G(14, 2484, 0), | 207 | CHAN2G(14, 2484, 0), |
| 208 | }; | 208 | }; |
| 209 | #undef CHAN4G | 209 | #undef CHAN2G |
| 210 | 210 | ||
| 211 | #define CHAN4G(_channel, _flags) { \ | ||
| 212 | .band = IEEE80211_BAND_5GHZ, \ | ||
| 213 | .center_freq = 4000 + (5 * (_channel)), \ | ||
| 214 | .hw_value = (_channel), \ | ||
| 215 | .flags = (_flags), \ | ||
| 216 | .max_antenna_gain = 0, \ | ||
| 217 | .max_power = 30, \ | ||
| 218 | } | ||
| 211 | #define CHAN5G(_channel, _flags) { \ | 219 | #define CHAN5G(_channel, _flags) { \ |
| 212 | .band = IEEE80211_BAND_5GHZ, \ | 220 | .band = IEEE80211_BAND_5GHZ, \ |
| 213 | .center_freq = 5000 + (5 * (_channel)), \ | 221 | .center_freq = 5000 + (5 * (_channel)), \ |
| @@ -217,6 +225,18 @@ static struct ieee80211_channel b43_2ghz_chantable[] = { | |||
| 217 | .max_power = 30, \ | 225 | .max_power = 30, \ |
| 218 | } | 226 | } |
| 219 | static struct ieee80211_channel b43_5ghz_nphy_chantable[] = { | 227 | static struct ieee80211_channel b43_5ghz_nphy_chantable[] = { |
| 228 | CHAN4G(184, 0), CHAN4G(186, 0), | ||
| 229 | CHAN4G(188, 0), CHAN4G(190, 0), | ||
| 230 | CHAN4G(192, 0), CHAN4G(194, 0), | ||
| 231 | CHAN4G(196, 0), CHAN4G(198, 0), | ||
| 232 | CHAN4G(200, 0), CHAN4G(202, 0), | ||
| 233 | CHAN4G(204, 0), CHAN4G(206, 0), | ||
| 234 | CHAN4G(208, 0), CHAN4G(210, 0), | ||
| 235 | CHAN4G(212, 0), CHAN4G(214, 0), | ||
| 236 | CHAN4G(216, 0), CHAN4G(218, 0), | ||
| 237 | CHAN4G(220, 0), CHAN4G(222, 0), | ||
| 238 | CHAN4G(224, 0), CHAN4G(226, 0), | ||
| 239 | CHAN4G(228, 0), | ||
| 220 | CHAN5G(32, 0), CHAN5G(34, 0), | 240 | CHAN5G(32, 0), CHAN5G(34, 0), |
| 221 | CHAN5G(36, 0), CHAN5G(38, 0), | 241 | CHAN5G(36, 0), CHAN5G(38, 0), |
| 222 | CHAN5G(40, 0), CHAN5G(42, 0), | 242 | CHAN5G(40, 0), CHAN5G(42, 0), |
| @@ -260,18 +280,7 @@ static struct ieee80211_channel b43_5ghz_nphy_chantable[] = { | |||
| 260 | CHAN5G(170, 0), CHAN5G(172, 0), | 280 | CHAN5G(170, 0), CHAN5G(172, 0), |
| 261 | CHAN5G(174, 0), CHAN5G(176, 0), | 281 | CHAN5G(174, 0), CHAN5G(176, 0), |
| 262 | CHAN5G(178, 0), CHAN5G(180, 0), | 282 | CHAN5G(178, 0), CHAN5G(180, 0), |
| 263 | CHAN5G(182, 0), CHAN5G(184, 0), | 283 | CHAN5G(182, 0), |
| 264 | CHAN5G(186, 0), CHAN5G(188, 0), | ||
| 265 | CHAN5G(190, 0), CHAN5G(192, 0), | ||
| 266 | CHAN5G(194, 0), CHAN5G(196, 0), | ||
| 267 | CHAN5G(198, 0), CHAN5G(200, 0), | ||
| 268 | CHAN5G(202, 0), CHAN5G(204, 0), | ||
| 269 | CHAN5G(206, 0), CHAN5G(208, 0), | ||
| 270 | CHAN5G(210, 0), CHAN5G(212, 0), | ||
| 271 | CHAN5G(214, 0), CHAN5G(216, 0), | ||
| 272 | CHAN5G(218, 0), CHAN5G(220, 0), | ||
| 273 | CHAN5G(222, 0), CHAN5G(224, 0), | ||
| 274 | CHAN5G(226, 0), CHAN5G(228, 0), | ||
| 275 | }; | 284 | }; |
| 276 | 285 | ||
| 277 | static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { | 286 | static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { |
| @@ -295,6 +304,7 @@ static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { | |||
| 295 | CHAN5G(208, 0), CHAN5G(212, 0), | 304 | CHAN5G(208, 0), CHAN5G(212, 0), |
| 296 | CHAN5G(216, 0), | 305 | CHAN5G(216, 0), |
| 297 | }; | 306 | }; |
| 307 | #undef CHAN4G | ||
| 298 | #undef CHAN5G | 308 | #undef CHAN5G |
| 299 | 309 | ||
| 300 | static struct ieee80211_supported_band b43_band_5GHz_nphy = { | 310 | static struct ieee80211_supported_band b43_band_5GHz_nphy = { |
| @@ -1175,18 +1185,7 @@ static void b43_bcma_phy_reset(struct b43_wldev *dev) | |||
| 1175 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags); | 1185 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags); |
| 1176 | udelay(2); | 1186 | udelay(2); |
| 1177 | 1187 | ||
| 1178 | /* Take PHY out of reset */ | 1188 | b43_phy_take_out_of_reset(dev); |
| 1179 | flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
| 1180 | flags &= ~B43_BCMA_IOCTL_PHY_RESET; | ||
| 1181 | flags |= BCMA_IOCTL_FGC; | ||
| 1182 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags); | ||
| 1183 | udelay(1); | ||
| 1184 | |||
| 1185 | /* Do not force clock anymore */ | ||
| 1186 | flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
| 1187 | flags &= ~BCMA_IOCTL_FGC; | ||
| 1188 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags); | ||
| 1189 | udelay(1); | ||
| 1190 | } | 1189 | } |
| 1191 | 1190 | ||
| 1192 | static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) | 1191 | static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) |
| @@ -1208,10 +1207,9 @@ static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) | |||
| 1208 | } | 1207 | } |
| 1209 | #endif | 1208 | #endif |
| 1210 | 1209 | ||
| 1210 | #ifdef CONFIG_B43_SSB | ||
| 1211 | static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode) | 1211 | static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode) |
| 1212 | { | 1212 | { |
| 1213 | struct ssb_device *sdev = dev->dev->sdev; | ||
| 1214 | u32 tmslow; | ||
| 1215 | u32 flags = 0; | 1213 | u32 flags = 0; |
| 1216 | 1214 | ||
| 1217 | if (gmode) | 1215 | if (gmode) |
| @@ -1223,18 +1221,9 @@ static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode) | |||
| 1223 | b43_device_enable(dev, flags); | 1221 | b43_device_enable(dev, flags); |
| 1224 | msleep(2); /* Wait for the PLL to turn on. */ | 1222 | msleep(2); /* Wait for the PLL to turn on. */ |
| 1225 | 1223 | ||
| 1226 | /* Now take the PHY out of Reset again */ | 1224 | b43_phy_take_out_of_reset(dev); |
| 1227 | tmslow = ssb_read32(sdev, SSB_TMSLOW); | ||
| 1228 | tmslow |= SSB_TMSLOW_FGC; | ||
| 1229 | tmslow &= ~B43_TMSLOW_PHYRESET; | ||
| 1230 | ssb_write32(sdev, SSB_TMSLOW, tmslow); | ||
| 1231 | ssb_read32(sdev, SSB_TMSLOW); /* flush */ | ||
| 1232 | msleep(1); | ||
| 1233 | tmslow &= ~SSB_TMSLOW_FGC; | ||
| 1234 | ssb_write32(sdev, SSB_TMSLOW, tmslow); | ||
| 1235 | ssb_read32(sdev, SSB_TMSLOW); /* flush */ | ||
| 1236 | msleep(1); | ||
| 1237 | } | 1225 | } |
| 1226 | #endif | ||
| 1238 | 1227 | ||
| 1239 | void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode) | 1228 | void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode) |
| 1240 | { | 1229 | { |
| @@ -2709,32 +2698,37 @@ static int b43_upload_initvals(struct b43_wldev *dev) | |||
| 2709 | struct b43_firmware *fw = &dev->fw; | 2698 | struct b43_firmware *fw = &dev->fw; |
| 2710 | const struct b43_iv *ivals; | 2699 | const struct b43_iv *ivals; |
| 2711 | size_t count; | 2700 | size_t count; |
| 2712 | int err; | ||
| 2713 | 2701 | ||
| 2714 | hdr = (const struct b43_fw_header *)(fw->initvals.data->data); | 2702 | hdr = (const struct b43_fw_header *)(fw->initvals.data->data); |
| 2715 | ivals = (const struct b43_iv *)(fw->initvals.data->data + hdr_len); | 2703 | ivals = (const struct b43_iv *)(fw->initvals.data->data + hdr_len); |
| 2716 | count = be32_to_cpu(hdr->size); | 2704 | count = be32_to_cpu(hdr->size); |
| 2717 | err = b43_write_initvals(dev, ivals, count, | 2705 | return b43_write_initvals(dev, ivals, count, |
| 2718 | fw->initvals.data->size - hdr_len); | 2706 | fw->initvals.data->size - hdr_len); |
| 2719 | if (err) | 2707 | } |
| 2720 | goto out; | ||
| 2721 | if (fw->initvals_band.data) { | ||
| 2722 | hdr = (const struct b43_fw_header *)(fw->initvals_band.data->data); | ||
| 2723 | ivals = (const struct b43_iv *)(fw->initvals_band.data->data + hdr_len); | ||
| 2724 | count = be32_to_cpu(hdr->size); | ||
| 2725 | err = b43_write_initvals(dev, ivals, count, | ||
| 2726 | fw->initvals_band.data->size - hdr_len); | ||
| 2727 | if (err) | ||
| 2728 | goto out; | ||
| 2729 | } | ||
| 2730 | out: | ||
| 2731 | 2708 | ||
| 2732 | return err; | 2709 | static int b43_upload_initvals_band(struct b43_wldev *dev) |
| 2710 | { | ||
| 2711 | const size_t hdr_len = sizeof(struct b43_fw_header); | ||
| 2712 | const struct b43_fw_header *hdr; | ||
| 2713 | struct b43_firmware *fw = &dev->fw; | ||
| 2714 | const struct b43_iv *ivals; | ||
| 2715 | size_t count; | ||
| 2716 | |||
| 2717 | if (!fw->initvals_band.data) | ||
| 2718 | return 0; | ||
| 2719 | |||
| 2720 | hdr = (const struct b43_fw_header *)(fw->initvals_band.data->data); | ||
| 2721 | ivals = (const struct b43_iv *)(fw->initvals_band.data->data + hdr_len); | ||
| 2722 | count = be32_to_cpu(hdr->size); | ||
| 2723 | return b43_write_initvals(dev, ivals, count, | ||
| 2724 | fw->initvals_band.data->size - hdr_len); | ||
| 2733 | } | 2725 | } |
| 2734 | 2726 | ||
| 2735 | /* Initialize the GPIOs | 2727 | /* Initialize the GPIOs |
| 2736 | * http://bcm-specs.sipsolutions.net/GPIO | 2728 | * http://bcm-specs.sipsolutions.net/GPIO |
| 2737 | */ | 2729 | */ |
| 2730 | |||
| 2731 | #ifdef CONFIG_B43_SSB | ||
| 2738 | static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev) | 2732 | static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev) |
| 2739 | { | 2733 | { |
| 2740 | struct ssb_bus *bus = dev->dev->sdev->bus; | 2734 | struct ssb_bus *bus = dev->dev->sdev->bus; |
| @@ -2745,10 +2739,13 @@ static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev) | |||
| 2745 | return bus->chipco.dev; | 2739 | return bus->chipco.dev; |
| 2746 | #endif | 2740 | #endif |
| 2747 | } | 2741 | } |
| 2742 | #endif | ||
| 2748 | 2743 | ||
| 2749 | static int b43_gpio_init(struct b43_wldev *dev) | 2744 | static int b43_gpio_init(struct b43_wldev *dev) |
| 2750 | { | 2745 | { |
| 2746 | #ifdef CONFIG_B43_SSB | ||
| 2751 | struct ssb_device *gpiodev; | 2747 | struct ssb_device *gpiodev; |
| 2748 | #endif | ||
| 2752 | u32 mask, set; | 2749 | u32 mask, set; |
| 2753 | 2750 | ||
| 2754 | b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0); | 2751 | b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0); |
| @@ -2807,7 +2804,9 @@ static int b43_gpio_init(struct b43_wldev *dev) | |||
| 2807 | /* Turn off all GPIO stuff. Call this on module unload, for example. */ | 2804 | /* Turn off all GPIO stuff. Call this on module unload, for example. */ |
| 2808 | static void b43_gpio_cleanup(struct b43_wldev *dev) | 2805 | static void b43_gpio_cleanup(struct b43_wldev *dev) |
| 2809 | { | 2806 | { |
| 2807 | #ifdef CONFIG_B43_SSB | ||
| 2810 | struct ssb_device *gpiodev; | 2808 | struct ssb_device *gpiodev; |
| 2809 | #endif | ||
| 2811 | 2810 | ||
| 2812 | switch (dev->dev->bus_type) { | 2811 | switch (dev->dev->bus_type) { |
| 2813 | #ifdef CONFIG_B43_BCMA | 2812 | #ifdef CONFIG_B43_BCMA |
| @@ -3091,6 +3090,10 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
| 3091 | if (err) | 3090 | if (err) |
| 3092 | goto err_gpio_clean; | 3091 | goto err_gpio_clean; |
| 3093 | 3092 | ||
| 3093 | err = b43_upload_initvals_band(dev); | ||
| 3094 | if (err) | ||
| 3095 | goto err_gpio_clean; | ||
| 3096 | |||
| 3094 | /* Turn the Analog on and initialize the PHY. */ | 3097 | /* Turn the Analog on and initialize the PHY. */ |
| 3095 | phy->ops->switch_analog(dev, 1); | 3098 | phy->ops->switch_analog(dev, 1); |
| 3096 | err = b43_phy_init(dev); | 3099 | err = b43_phy_init(dev); |
| @@ -3690,37 +3693,6 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, | |||
| 3690 | mutex_unlock(&wl->mutex); | 3693 | mutex_unlock(&wl->mutex); |
| 3691 | } | 3694 | } |
| 3692 | 3695 | ||
| 3693 | static void b43_put_phy_into_reset(struct b43_wldev *dev) | ||
| 3694 | { | ||
| 3695 | u32 tmp; | ||
| 3696 | |||
| 3697 | switch (dev->dev->bus_type) { | ||
| 3698 | #ifdef CONFIG_B43_BCMA | ||
| 3699 | case B43_BUS_BCMA: | ||
| 3700 | b43err(dev->wl, | ||
| 3701 | "Putting PHY into reset not supported on BCMA\n"); | ||
| 3702 | break; | ||
| 3703 | #endif | ||
| 3704 | #ifdef CONFIG_B43_SSB | ||
| 3705 | case B43_BUS_SSB: | ||
| 3706 | tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); | ||
| 3707 | tmp &= ~B43_TMSLOW_GMODE; | ||
| 3708 | tmp |= B43_TMSLOW_PHYRESET; | ||
| 3709 | tmp |= SSB_TMSLOW_FGC; | ||
| 3710 | ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); | ||
| 3711 | msleep(1); | ||
| 3712 | |||
| 3713 | tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); | ||
| 3714 | tmp &= ~SSB_TMSLOW_FGC; | ||
| 3715 | tmp |= B43_TMSLOW_PHYRESET; | ||
| 3716 | ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); | ||
| 3717 | msleep(1); | ||
| 3718 | |||
| 3719 | break; | ||
| 3720 | #endif | ||
| 3721 | } | ||
| 3722 | } | ||
| 3723 | |||
| 3724 | static const char *band_to_string(enum ieee80211_band band) | 3696 | static const char *band_to_string(enum ieee80211_band band) |
| 3725 | { | 3697 | { |
| 3726 | switch (band) { | 3698 | switch (band) { |
| @@ -3736,89 +3708,73 @@ static const char *band_to_string(enum ieee80211_band band) | |||
| 3736 | } | 3708 | } |
| 3737 | 3709 | ||
| 3738 | /* Expects wl->mutex locked */ | 3710 | /* Expects wl->mutex locked */ |
| 3739 | static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan) | 3711 | static int b43_switch_band(struct b43_wldev *dev, |
| 3712 | struct ieee80211_channel *chan) | ||
| 3740 | { | 3713 | { |
| 3741 | struct b43_wldev *up_dev = NULL; | 3714 | struct b43_phy *phy = &dev->phy; |
| 3742 | struct b43_wldev *down_dev; | 3715 | bool gmode; |
| 3743 | int err; | 3716 | u32 tmp; |
| 3744 | bool uninitialized_var(gmode); | ||
| 3745 | int prev_status; | ||
| 3746 | 3717 | ||
| 3747 | /* Find a device and PHY which supports the band. */ | ||
| 3748 | switch (chan->band) { | 3718 | switch (chan->band) { |
| 3749 | case IEEE80211_BAND_5GHZ: | 3719 | case IEEE80211_BAND_5GHZ: |
| 3750 | if (wl->current_dev->phy.supports_5ghz) { | 3720 | gmode = false; |
| 3751 | up_dev = wl->current_dev; | ||
| 3752 | gmode = false; | ||
| 3753 | } | ||
| 3754 | break; | 3721 | break; |
| 3755 | case IEEE80211_BAND_2GHZ: | 3722 | case IEEE80211_BAND_2GHZ: |
| 3756 | if (wl->current_dev->phy.supports_2ghz) { | 3723 | gmode = true; |
| 3757 | up_dev = wl->current_dev; | ||
| 3758 | gmode = true; | ||
| 3759 | } | ||
| 3760 | break; | 3724 | break; |
| 3761 | default: | 3725 | default: |
| 3762 | B43_WARN_ON(1); | 3726 | B43_WARN_ON(1); |
| 3763 | return -EINVAL; | 3727 | return -EINVAL; |
| 3764 | } | 3728 | } |
| 3765 | 3729 | ||
| 3766 | if (!up_dev) { | 3730 | if (!((gmode && phy->supports_2ghz) || |
| 3767 | b43err(wl, "Could not find a device for %s-GHz band operation\n", | 3731 | (!gmode && phy->supports_5ghz))) { |
| 3732 | b43err(dev->wl, "This device doesn't support %s-GHz band\n", | ||
| 3768 | band_to_string(chan->band)); | 3733 | band_to_string(chan->band)); |
| 3769 | return -ENODEV; | 3734 | return -ENODEV; |
| 3770 | } | 3735 | } |
| 3771 | if (!!wl->current_dev->phy.gmode == !!gmode) { | 3736 | |
| 3737 | if (!!phy->gmode == !!gmode) { | ||
| 3772 | /* This device is already running. */ | 3738 | /* This device is already running. */ |
| 3773 | return 0; | 3739 | return 0; |
| 3774 | } | 3740 | } |
| 3775 | b43dbg(wl, "Switching to %s-GHz band\n", | 3741 | |
| 3742 | b43dbg(dev->wl, "Switching to %s GHz band\n", | ||
| 3776 | band_to_string(chan->band)); | 3743 | band_to_string(chan->band)); |
| 3777 | down_dev = wl->current_dev; | ||
| 3778 | 3744 | ||
| 3779 | prev_status = b43_status(down_dev); | 3745 | b43_software_rfkill(dev, true); |
| 3780 | /* Shutdown the currently running core. */ | ||
| 3781 | if (prev_status >= B43_STAT_STARTED) | ||
| 3782 | down_dev = b43_wireless_core_stop(down_dev); | ||
| 3783 | if (prev_status >= B43_STAT_INITIALIZED) | ||
| 3784 | b43_wireless_core_exit(down_dev); | ||
| 3785 | 3746 | ||
| 3786 | if (down_dev != up_dev) { | 3747 | phy->gmode = gmode; |
| 3787 | /* We switch to a different core, so we put PHY into | 3748 | b43_phy_put_into_reset(dev); |
| 3788 | * RESET on the old core. */ | 3749 | switch (dev->dev->bus_type) { |
| 3789 | b43_put_phy_into_reset(down_dev); | 3750 | #ifdef CONFIG_B43_BCMA |
| 3751 | case B43_BUS_BCMA: | ||
| 3752 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
| 3753 | if (gmode) | ||
| 3754 | tmp |= B43_BCMA_IOCTL_GMODE; | ||
| 3755 | else | ||
| 3756 | tmp &= ~B43_BCMA_IOCTL_GMODE; | ||
| 3757 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
| 3758 | break; | ||
| 3759 | #endif | ||
| 3760 | #ifdef CONFIG_B43_SSB | ||
| 3761 | case B43_BUS_SSB: | ||
| 3762 | tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); | ||
| 3763 | if (gmode) | ||
| 3764 | tmp |= B43_TMSLOW_GMODE; | ||
| 3765 | else | ||
| 3766 | tmp &= ~B43_TMSLOW_GMODE; | ||
| 3767 | ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); | ||
| 3768 | break; | ||
| 3769 | #endif | ||
| 3790 | } | 3770 | } |
| 3771 | b43_phy_take_out_of_reset(dev); | ||
| 3791 | 3772 | ||
| 3792 | /* Now start the new core. */ | 3773 | b43_upload_initvals_band(dev); |
| 3793 | up_dev->phy.gmode = gmode; | ||
| 3794 | if (prev_status >= B43_STAT_INITIALIZED) { | ||
| 3795 | err = b43_wireless_core_init(up_dev); | ||
| 3796 | if (err) { | ||
| 3797 | b43err(wl, "Fatal: Could not initialize device for " | ||
| 3798 | "selected %s-GHz band\n", | ||
| 3799 | band_to_string(chan->band)); | ||
| 3800 | goto init_failure; | ||
| 3801 | } | ||
| 3802 | } | ||
| 3803 | if (prev_status >= B43_STAT_STARTED) { | ||
| 3804 | err = b43_wireless_core_start(up_dev); | ||
| 3805 | if (err) { | ||
| 3806 | b43err(wl, "Fatal: Could not start device for " | ||
| 3807 | "selected %s-GHz band\n", | ||
| 3808 | band_to_string(chan->band)); | ||
| 3809 | b43_wireless_core_exit(up_dev); | ||
| 3810 | goto init_failure; | ||
| 3811 | } | ||
| 3812 | } | ||
| 3813 | B43_WARN_ON(b43_status(up_dev) != prev_status); | ||
| 3814 | 3774 | ||
| 3815 | wl->current_dev = up_dev; | 3775 | b43_phy_init(dev); |
| 3816 | 3776 | ||
| 3817 | return 0; | 3777 | return 0; |
| 3818 | init_failure: | ||
| 3819 | /* Whoops, failed to init the new core. No core is operating now. */ | ||
| 3820 | wl->current_dev = NULL; | ||
| 3821 | return err; | ||
| 3822 | } | 3778 | } |
| 3823 | 3779 | ||
| 3824 | /* Write the short and long frame retry limit values. */ | 3780 | /* Write the short and long frame retry limit values. */ |
| @@ -3851,8 +3807,10 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) | |||
| 3851 | 3807 | ||
| 3852 | dev = wl->current_dev; | 3808 | dev = wl->current_dev; |
| 3853 | 3809 | ||
| 3810 | b43_mac_suspend(dev); | ||
| 3811 | |||
| 3854 | /* Switch the band (if necessary). This might change the active core. */ | 3812 | /* Switch the band (if necessary). This might change the active core. */ |
| 3855 | err = b43_switch_band(wl, conf->chandef.chan); | 3813 | err = b43_switch_band(dev, conf->chandef.chan); |
| 3856 | if (err) | 3814 | if (err) |
| 3857 | goto out_unlock_mutex; | 3815 | goto out_unlock_mutex; |
| 3858 | 3816 | ||
| @@ -3871,8 +3829,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) | |||
| 3871 | else | 3829 | else |
| 3872 | phy->is_40mhz = false; | 3830 | phy->is_40mhz = false; |
| 3873 | 3831 | ||
| 3874 | b43_mac_suspend(dev); | ||
| 3875 | |||
| 3876 | if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) | 3832 | if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) |
| 3877 | b43_set_retry_limits(dev, conf->short_frame_max_tx_count, | 3833 | b43_set_retry_limits(dev, conf->short_frame_max_tx_count, |
| 3878 | conf->long_frame_max_tx_count); | 3834 | conf->long_frame_max_tx_count); |
| @@ -4582,8 +4538,12 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) | |||
| 4582 | struct ssb_bus *bus; | 4538 | struct ssb_bus *bus; |
| 4583 | u32 tmp; | 4539 | u32 tmp; |
| 4584 | 4540 | ||
| 4541 | #ifdef CONFIG_B43_SSB | ||
| 4585 | if (dev->dev->bus_type != B43_BUS_SSB) | 4542 | if (dev->dev->bus_type != B43_BUS_SSB) |
| 4586 | return; | 4543 | return; |
| 4544 | #else | ||
| 4545 | return; | ||
| 4546 | #endif | ||
| 4587 | 4547 | ||
| 4588 | bus = dev->dev->sdev->bus; | 4548 | bus = dev->dev->sdev->bus; |
| 4589 | 4549 | ||
| @@ -4738,7 +4698,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
| 4738 | } | 4698 | } |
| 4739 | if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW) | 4699 | if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW) |
| 4740 | hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */ | 4700 | hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */ |
| 4741 | #ifdef CONFIG_SSB_DRIVER_PCICORE | 4701 | #if defined(CONFIG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE) |
| 4742 | if (dev->dev->bus_type == B43_BUS_SSB && | 4702 | if (dev->dev->bus_type == B43_BUS_SSB && |
| 4743 | dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && | 4703 | dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && |
| 4744 | dev->dev->sdev->bus->pcicore.dev->id.revision <= 10) | 4704 | dev->dev->sdev->bus->pcicore.dev->id.revision <= 10) |
| @@ -5129,10 +5089,81 @@ static void b43_wireless_core_detach(struct b43_wldev *dev) | |||
| 5129 | b43_phy_free(dev); | 5089 | b43_phy_free(dev); |
| 5130 | } | 5090 | } |
| 5131 | 5091 | ||
| 5092 | static void b43_supported_bands(struct b43_wldev *dev, bool *have_2ghz_phy, | ||
| 5093 | bool *have_5ghz_phy) | ||
| 5094 | { | ||
| 5095 | u16 dev_id = 0; | ||
| 5096 | |||
| 5097 | #ifdef CONFIG_B43_BCMA | ||
| 5098 | if (dev->dev->bus_type == B43_BUS_BCMA && | ||
| 5099 | dev->dev->bdev->bus->hosttype == BCMA_HOSTTYPE_PCI) | ||
| 5100 | dev_id = dev->dev->bdev->bus->host_pci->device; | ||
| 5101 | #endif | ||
| 5102 | #ifdef CONFIG_B43_SSB | ||
| 5103 | if (dev->dev->bus_type == B43_BUS_SSB && | ||
| 5104 | dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) | ||
| 5105 | dev_id = dev->dev->sdev->bus->host_pci->device; | ||
| 5106 | #endif | ||
| 5107 | /* Override with SPROM value if available */ | ||
| 5108 | if (dev->dev->bus_sprom->dev_id) | ||
| 5109 | dev_id = dev->dev->bus_sprom->dev_id; | ||
| 5110 | |||
| 5111 | /* Note: below IDs can be "virtual" (not maching e.g. real PCI ID) */ | ||
| 5112 | switch (dev_id) { | ||
| 5113 | case 0x4324: /* BCM4306 */ | ||
| 5114 | case 0x4312: /* BCM4311 */ | ||
| 5115 | case 0x4319: /* BCM4318 */ | ||
| 5116 | case 0x4328: /* BCM4321 */ | ||
| 5117 | case 0x432b: /* BCM4322 */ | ||
| 5118 | case 0x4350: /* BCM43222 */ | ||
| 5119 | case 0x4353: /* BCM43224 */ | ||
| 5120 | case 0x0576: /* BCM43224 */ | ||
| 5121 | case 0x435f: /* BCM6362 */ | ||
| 5122 | case 0x4331: /* BCM4331 */ | ||
| 5123 | case 0x4359: /* BCM43228 */ | ||
| 5124 | case 0x43a0: /* BCM4360 */ | ||
| 5125 | case 0x43b1: /* BCM4352 */ | ||
| 5126 | /* Dual band devices */ | ||
| 5127 | *have_2ghz_phy = true; | ||
| 5128 | *have_5ghz_phy = true; | ||
| 5129 | return; | ||
| 5130 | case 0x4321: /* BCM4306 */ | ||
| 5131 | case 0x4313: /* BCM4311 */ | ||
| 5132 | case 0x431a: /* BCM4318 */ | ||
| 5133 | case 0x432a: /* BCM4321 */ | ||
| 5134 | case 0x432d: /* BCM4322 */ | ||
| 5135 | case 0x4352: /* BCM43222 */ | ||
| 5136 | case 0x4333: /* BCM4331 */ | ||
| 5137 | case 0x43a2: /* BCM4360 */ | ||
| 5138 | case 0x43b3: /* BCM4352 */ | ||
| 5139 | /* 5 GHz only devices */ | ||
| 5140 | *have_2ghz_phy = false; | ||
| 5141 | *have_5ghz_phy = true; | ||
| 5142 | return; | ||
| 5143 | } | ||
| 5144 | |||
| 5145 | /* As a fallback, try to guess using PHY type */ | ||
| 5146 | switch (dev->phy.type) { | ||
| 5147 | case B43_PHYTYPE_A: | ||
| 5148 | *have_2ghz_phy = false; | ||
| 5149 | *have_5ghz_phy = true; | ||
| 5150 | return; | ||
| 5151 | case B43_PHYTYPE_G: | ||
| 5152 | case B43_PHYTYPE_N: | ||
| 5153 | case B43_PHYTYPE_LP: | ||
| 5154 | case B43_PHYTYPE_HT: | ||
| 5155 | case B43_PHYTYPE_LCN: | ||
| 5156 | *have_2ghz_phy = true; | ||
| 5157 | *have_5ghz_phy = false; | ||
| 5158 | return; | ||
| 5159 | } | ||
| 5160 | |||
| 5161 | B43_WARN_ON(1); | ||
| 5162 | } | ||
| 5163 | |||
| 5132 | static int b43_wireless_core_attach(struct b43_wldev *dev) | 5164 | static int b43_wireless_core_attach(struct b43_wldev *dev) |
| 5133 | { | 5165 | { |
| 5134 | struct b43_wl *wl = dev->wl; | 5166 | struct b43_wl *wl = dev->wl; |
| 5135 | struct pci_dev *pdev = NULL; | ||
| 5136 | int err; | 5167 | int err; |
| 5137 | u32 tmp; | 5168 | u32 tmp; |
| 5138 | bool have_2ghz_phy = false, have_5ghz_phy = false; | 5169 | bool have_2ghz_phy = false, have_5ghz_phy = false; |
| @@ -5144,19 +5175,13 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
| 5144 | * that in core_init(), too. | 5175 | * that in core_init(), too. |
| 5145 | */ | 5176 | */ |
| 5146 | 5177 | ||
| 5147 | #ifdef CONFIG_B43_SSB | ||
| 5148 | if (dev->dev->bus_type == B43_BUS_SSB && | ||
| 5149 | dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) | ||
| 5150 | pdev = dev->dev->sdev->bus->host_pci; | ||
| 5151 | #endif | ||
| 5152 | |||
| 5153 | err = b43_bus_powerup(dev, 0); | 5178 | err = b43_bus_powerup(dev, 0); |
| 5154 | if (err) { | 5179 | if (err) { |
| 5155 | b43err(wl, "Bus powerup failed\n"); | 5180 | b43err(wl, "Bus powerup failed\n"); |
| 5156 | goto out; | 5181 | goto out; |
| 5157 | } | 5182 | } |
| 5158 | 5183 | ||
| 5159 | /* Get the PHY type. */ | 5184 | /* Try to guess supported bands for the first init needs */ |
| 5160 | switch (dev->dev->bus_type) { | 5185 | switch (dev->dev->bus_type) { |
| 5161 | #ifdef CONFIG_B43_BCMA | 5186 | #ifdef CONFIG_B43_BCMA |
| 5162 | case B43_BUS_BCMA: | 5187 | case B43_BUS_BCMA: |
| @@ -5180,48 +5205,29 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
| 5180 | dev->phy.gmode = have_2ghz_phy; | 5205 | dev->phy.gmode = have_2ghz_phy; |
| 5181 | b43_wireless_core_reset(dev, dev->phy.gmode); | 5206 | b43_wireless_core_reset(dev, dev->phy.gmode); |
| 5182 | 5207 | ||
| 5208 | /* Get the PHY type. */ | ||
| 5183 | err = b43_phy_versioning(dev); | 5209 | err = b43_phy_versioning(dev); |
| 5184 | if (err) | 5210 | if (err) |
| 5185 | goto err_powerdown; | 5211 | goto err_powerdown; |
| 5186 | /* Check if this device supports multiband. */ | 5212 | |
| 5187 | if (!pdev || | 5213 | /* Get real info about supported bands */ |
| 5188 | (pdev->device != 0x4312 && | 5214 | b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy); |
| 5189 | pdev->device != 0x4319 && pdev->device != 0x4324)) { | 5215 | |
| 5190 | /* No multiband support. */ | 5216 | /* We don't support 5 GHz on some PHYs yet */ |
| 5191 | have_2ghz_phy = false; | 5217 | switch (dev->phy.type) { |
| 5218 | case B43_PHYTYPE_A: | ||
| 5219 | case B43_PHYTYPE_N: | ||
| 5220 | case B43_PHYTYPE_LP: | ||
| 5221 | case B43_PHYTYPE_HT: | ||
| 5222 | b43warn(wl, "5 GHz band is unsupported on this PHY\n"); | ||
| 5192 | have_5ghz_phy = false; | 5223 | have_5ghz_phy = false; |
| 5193 | switch (dev->phy.type) { | ||
| 5194 | case B43_PHYTYPE_A: | ||
| 5195 | have_5ghz_phy = true; | ||
| 5196 | break; | ||
| 5197 | case B43_PHYTYPE_LP: //FIXME not always! | ||
| 5198 | #if 0 //FIXME enabling 5GHz causes a NULL pointer dereference | ||
| 5199 | have_5ghz_phy = 1; | ||
| 5200 | #endif | ||
| 5201 | case B43_PHYTYPE_G: | ||
| 5202 | case B43_PHYTYPE_N: | ||
| 5203 | case B43_PHYTYPE_HT: | ||
| 5204 | case B43_PHYTYPE_LCN: | ||
| 5205 | have_2ghz_phy = true; | ||
| 5206 | break; | ||
| 5207 | default: | ||
| 5208 | B43_WARN_ON(1); | ||
| 5209 | } | ||
| 5210 | } | 5224 | } |
| 5211 | if (dev->phy.type == B43_PHYTYPE_A) { | 5225 | |
| 5212 | /* FIXME */ | 5226 | if (!have_2ghz_phy && !have_5ghz_phy) { |
| 5213 | b43err(wl, "IEEE 802.11a devices are unsupported\n"); | 5227 | b43err(wl, "b43 can't support any band on this device\n"); |
| 5214 | err = -EOPNOTSUPP; | 5228 | err = -EOPNOTSUPP; |
| 5215 | goto err_powerdown; | 5229 | goto err_powerdown; |
| 5216 | } | 5230 | } |
| 5217 | if (1 /* disable A-PHY */) { | ||
| 5218 | /* FIXME: For now we disable the A-PHY on multi-PHY devices. */ | ||
| 5219 | if (dev->phy.type != B43_PHYTYPE_N && | ||
| 5220 | dev->phy.type != B43_PHYTYPE_LP) { | ||
| 5221 | have_2ghz_phy = true; | ||
| 5222 | have_5ghz_phy = false; | ||
| 5223 | } | ||
| 5224 | } | ||
| 5225 | 5231 | ||
| 5226 | err = b43_phy_allocate(dev); | 5232 | err = b43_phy_allocate(dev); |
| 5227 | if (err) | 5233 | if (err) |
| @@ -5310,6 +5316,7 @@ static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl) | |||
| 5310 | (pdev->subsystem_vendor == PCI_VENDOR_ID_##_subvendor) && \ | 5316 | (pdev->subsystem_vendor == PCI_VENDOR_ID_##_subvendor) && \ |
| 5311 | (pdev->subsystem_device == _subdevice) ) | 5317 | (pdev->subsystem_device == _subdevice) ) |
| 5312 | 5318 | ||
| 5319 | #ifdef CONFIG_B43_SSB | ||
| 5313 | static void b43_sprom_fixup(struct ssb_bus *bus) | 5320 | static void b43_sprom_fixup(struct ssb_bus *bus) |
| 5314 | { | 5321 | { |
| 5315 | struct pci_dev *pdev; | 5322 | struct pci_dev *pdev; |
| @@ -5341,6 +5348,7 @@ static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl) | |||
| 5341 | ssb_set_devtypedata(dev->sdev, NULL); | 5348 | ssb_set_devtypedata(dev->sdev, NULL); |
| 5342 | ieee80211_free_hw(hw); | 5349 | ieee80211_free_hw(hw); |
| 5343 | } | 5350 | } |
| 5351 | #endif | ||
| 5344 | 5352 | ||
| 5345 | static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) | 5353 | static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) |
| 5346 | { | 5354 | { |
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 3e45989f418d..fb0ddddde16b 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c | |||
| @@ -96,6 +96,7 @@ int b43_phy_init(struct b43_wldev *dev) | |||
| 96 | 96 | ||
| 97 | phy->channel = ops->get_default_chan(dev); | 97 | phy->channel = ops->get_default_chan(dev); |
| 98 | 98 | ||
| 99 | phy->ops->switch_analog(dev, true); | ||
| 99 | b43_software_rfkill(dev, false); | 100 | b43_software_rfkill(dev, false); |
| 100 | err = ops->init(dev); | 101 | err = ops->init(dev); |
| 101 | if (err) { | 102 | if (err) { |
| @@ -312,6 +313,90 @@ void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) | |||
| 312 | } | 313 | } |
| 313 | } | 314 | } |
| 314 | 315 | ||
| 316 | void b43_phy_put_into_reset(struct b43_wldev *dev) | ||
| 317 | { | ||
| 318 | u32 tmp; | ||
| 319 | |||
| 320 | switch (dev->dev->bus_type) { | ||
| 321 | #ifdef CONFIG_B43_BCMA | ||
| 322 | case B43_BUS_BCMA: | ||
| 323 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
| 324 | tmp &= ~B43_BCMA_IOCTL_GMODE; | ||
| 325 | tmp |= B43_BCMA_IOCTL_PHY_RESET; | ||
| 326 | tmp |= BCMA_IOCTL_FGC; | ||
| 327 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
| 328 | udelay(1); | ||
| 329 | |||
| 330 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
| 331 | tmp &= ~BCMA_IOCTL_FGC; | ||
| 332 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
| 333 | udelay(1); | ||
| 334 | break; | ||
| 335 | #endif | ||
| 336 | #ifdef CONFIG_B43_SSB | ||
| 337 | case B43_BUS_SSB: | ||
| 338 | tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); | ||
| 339 | tmp &= ~B43_TMSLOW_GMODE; | ||
| 340 | tmp |= B43_TMSLOW_PHYRESET; | ||
| 341 | tmp |= SSB_TMSLOW_FGC; | ||
| 342 | ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); | ||
| 343 | usleep_range(1000, 2000); | ||
| 344 | |||
| 345 | tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); | ||
| 346 | tmp &= ~SSB_TMSLOW_FGC; | ||
| 347 | ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); | ||
| 348 | usleep_range(1000, 2000); | ||
| 349 | |||
| 350 | break; | ||
| 351 | #endif | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 355 | void b43_phy_take_out_of_reset(struct b43_wldev *dev) | ||
| 356 | { | ||
| 357 | u32 tmp; | ||
| 358 | |||
| 359 | switch (dev->dev->bus_type) { | ||
| 360 | #ifdef CONFIG_B43_BCMA | ||
| 361 | case B43_BUS_BCMA: | ||
| 362 | /* Unset reset bit (with forcing clock) */ | ||
| 363 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
| 364 | tmp &= ~B43_BCMA_IOCTL_PHY_RESET; | ||
| 365 | tmp &= ~B43_BCMA_IOCTL_PHY_CLKEN; | ||
| 366 | tmp |= BCMA_IOCTL_FGC; | ||
| 367 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
| 368 | udelay(1); | ||
| 369 | |||
| 370 | /* Do not force clock anymore */ | ||
| 371 | tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); | ||
| 372 | tmp &= ~BCMA_IOCTL_FGC; | ||
| 373 | tmp |= B43_BCMA_IOCTL_PHY_CLKEN; | ||
| 374 | bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); | ||
| 375 | udelay(1); | ||
| 376 | break; | ||
| 377 | #endif | ||
| 378 | #ifdef CONFIG_B43_SSB | ||
| 379 | case B43_BUS_SSB: | ||
| 380 | /* Unset reset bit (with forcing clock) */ | ||
| 381 | tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); | ||
| 382 | tmp &= ~B43_TMSLOW_PHYRESET; | ||
| 383 | tmp &= ~B43_TMSLOW_PHYCLKEN; | ||
| 384 | tmp |= SSB_TMSLOW_FGC; | ||
| 385 | ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); | ||
| 386 | ssb_read32(dev->dev->sdev, SSB_TMSLOW); /* flush */ | ||
| 387 | usleep_range(1000, 2000); | ||
| 388 | |||
| 389 | tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); | ||
| 390 | tmp &= ~SSB_TMSLOW_FGC; | ||
| 391 | tmp |= B43_TMSLOW_PHYCLKEN; | ||
| 392 | ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); | ||
| 393 | ssb_read32(dev->dev->sdev, SSB_TMSLOW); /* flush */ | ||
| 394 | usleep_range(1000, 2000); | ||
| 395 | break; | ||
| 396 | #endif | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 315 | int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel) | 400 | int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel) |
| 316 | { | 401 | { |
| 317 | struct b43_phy *phy = &(dev->phy); | 402 | struct b43_phy *phy = &(dev->phy); |
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index f1b999349876..47b55855c37d 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h | |||
| @@ -231,7 +231,7 @@ struct b43_phy { | |||
| 231 | /* HT info */ | 231 | /* HT info */ |
| 232 | bool is_40mhz; | 232 | bool is_40mhz; |
| 233 | 233 | ||
| 234 | /* GMODE bit enabled? */ | 234 | /* Is GMODE (2 GHz mode) bit enabled? */ |
| 235 | bool gmode; | 235 | bool gmode; |
| 236 | 236 | ||
| 237 | /* Analog Type */ | 237 | /* Analog Type */ |
| @@ -390,6 +390,9 @@ void b43_phy_lock(struct b43_wldev *dev); | |||
| 390 | */ | 390 | */ |
| 391 | void b43_phy_unlock(struct b43_wldev *dev); | 391 | void b43_phy_unlock(struct b43_wldev *dev); |
| 392 | 392 | ||
| 393 | void b43_phy_put_into_reset(struct b43_wldev *dev); | ||
| 394 | void b43_phy_take_out_of_reset(struct b43_wldev *dev); | ||
| 395 | |||
| 393 | /** | 396 | /** |
| 394 | * b43_switch_channel - Switch to another channel | 397 | * b43_switch_channel - Switch to another channel |
| 395 | */ | 398 | */ |
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c index a07e4cacab77..2ce25607c60d 100644 --- a/drivers/net/wireless/b43/radio_2056.c +++ b/drivers/net/wireless/b43/radio_2056.c | |||
| @@ -9058,6 +9058,231 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev | |||
| 9058 | 9058 | ||
| 9059 | static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev11[] = { | 9059 | static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev11[] = { |
| 9060 | { | 9060 | { |
| 9061 | .freq = 4920, | ||
| 9062 | RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, | ||
| 9063 | 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, | ||
| 9064 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9065 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9066 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9067 | PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216), | ||
| 9068 | }, | ||
| 9069 | { | ||
| 9070 | .freq = 4930, | ||
| 9071 | RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02, | ||
| 9072 | 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, | ||
| 9073 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9074 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9075 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9076 | PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215), | ||
| 9077 | }, | ||
| 9078 | { | ||
| 9079 | .freq = 4940, | ||
| 9080 | RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02, | ||
| 9081 | 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, | ||
| 9082 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9083 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9084 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9085 | PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214), | ||
| 9086 | }, | ||
| 9087 | { | ||
| 9088 | .freq = 4950, | ||
| 9089 | RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02, | ||
| 9090 | 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, | ||
| 9091 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9092 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9093 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9094 | PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213), | ||
| 9095 | }, | ||
| 9096 | { | ||
| 9097 | .freq = 4960, | ||
| 9098 | RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02, | ||
| 9099 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9100 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9101 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9102 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9103 | PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212), | ||
| 9104 | }, | ||
| 9105 | { | ||
| 9106 | .freq = 4970, | ||
| 9107 | RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02, | ||
| 9108 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9109 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9110 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9111 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9112 | PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211), | ||
| 9113 | }, | ||
| 9114 | { | ||
| 9115 | .freq = 4980, | ||
| 9116 | RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02, | ||
| 9117 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9118 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9119 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9120 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9121 | PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f), | ||
| 9122 | }, | ||
| 9123 | { | ||
| 9124 | .freq = 4990, | ||
| 9125 | RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02, | ||
| 9126 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9127 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9128 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9129 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9130 | PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e), | ||
| 9131 | }, | ||
| 9132 | { | ||
| 9133 | .freq = 5000, | ||
| 9134 | RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02, | ||
| 9135 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9136 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9137 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9138 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9139 | PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d), | ||
| 9140 | }, | ||
| 9141 | { | ||
| 9142 | .freq = 5010, | ||
| 9143 | RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02, | ||
| 9144 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9145 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9146 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9147 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9148 | PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c), | ||
| 9149 | }, | ||
| 9150 | { | ||
| 9151 | .freq = 5020, | ||
| 9152 | RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02, | ||
| 9153 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9154 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9155 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9156 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9157 | PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b), | ||
| 9158 | }, | ||
| 9159 | { | ||
| 9160 | .freq = 5030, | ||
| 9161 | RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02, | ||
| 9162 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9163 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9164 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9165 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9166 | PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a), | ||
| 9167 | }, | ||
| 9168 | { | ||
| 9169 | .freq = 5040, | ||
| 9170 | RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02, | ||
| 9171 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9172 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9173 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9174 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9175 | PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209), | ||
| 9176 | }, | ||
| 9177 | { | ||
| 9178 | .freq = 5050, | ||
| 9179 | RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02, | ||
| 9180 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9181 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9182 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9183 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9184 | PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208), | ||
| 9185 | }, | ||
| 9186 | { | ||
| 9187 | .freq = 5060, | ||
| 9188 | RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02, | ||
| 9189 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9190 | 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9191 | 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, | ||
| 9192 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9193 | PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207), | ||
| 9194 | }, | ||
| 9195 | { | ||
| 9196 | .freq = 5070, | ||
| 9197 | RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02, | ||
| 9198 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9199 | 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9200 | 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, | ||
| 9201 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9202 | PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206), | ||
| 9203 | }, | ||
| 9204 | { | ||
| 9205 | .freq = 5080, | ||
| 9206 | RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02, | ||
| 9207 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9208 | 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9209 | 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, | ||
| 9210 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9211 | PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205), | ||
| 9212 | }, | ||
| 9213 | { | ||
| 9214 | .freq = 5090, | ||
| 9215 | RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02, | ||
| 9216 | 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, | ||
| 9217 | 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f, | ||
| 9218 | 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, | ||
| 9219 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9220 | PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204), | ||
| 9221 | }, | ||
| 9222 | { | ||
| 9223 | .freq = 5100, | ||
| 9224 | RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02, | ||
| 9225 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, | ||
| 9226 | 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, | ||
| 9227 | 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, | ||
| 9228 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9229 | PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203), | ||
| 9230 | }, | ||
| 9231 | { | ||
| 9232 | .freq = 5110, | ||
| 9233 | RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02, | ||
| 9234 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, | ||
| 9235 | 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, | ||
| 9236 | 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, | ||
| 9237 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9238 | PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202), | ||
| 9239 | }, | ||
| 9240 | { | ||
| 9241 | .freq = 5120, | ||
| 9242 | RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02, | ||
| 9243 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, | ||
| 9244 | 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, | ||
| 9245 | 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, | ||
| 9246 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9247 | PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201), | ||
| 9248 | }, | ||
| 9249 | { | ||
| 9250 | .freq = 5130, | ||
| 9251 | RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02, | ||
| 9252 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, | ||
| 9253 | 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, | ||
| 9254 | 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, | ||
| 9255 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9256 | PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200), | ||
| 9257 | }, | ||
| 9258 | { | ||
| 9259 | .freq = 5140, | ||
| 9260 | RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02, | ||
| 9261 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, | ||
| 9262 | 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f, | ||
| 9263 | 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, | ||
| 9264 | 0x00, 0x0f, 0x00, 0x6f, 0x00), | ||
| 9265 | PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff), | ||
| 9266 | }, | ||
| 9267 | { | ||
| 9268 | .freq = 5160, | ||
| 9269 | RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02, | ||
| 9270 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, | ||
| 9271 | 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, | ||
| 9272 | 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, | ||
| 9273 | 0x00, 0x0e, 0x00, 0x6f, 0x00), | ||
| 9274 | PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd), | ||
| 9275 | }, | ||
| 9276 | { | ||
| 9277 | .freq = 5170, | ||
| 9278 | RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02, | ||
| 9279 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, | ||
| 9280 | 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e, | ||
| 9281 | 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, | ||
| 9282 | 0x00, 0x0e, 0x00, 0x6f, 0x00), | ||
| 9283 | PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc), | ||
| 9284 | }, | ||
| 9285 | { | ||
| 9061 | .freq = 5180, | 9286 | .freq = 5180, |
| 9062 | RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02, | 9287 | RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02, |
| 9063 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, | 9288 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, |
| @@ -9067,6 +9292,15 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev | |||
| 9067 | PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), | 9292 | PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb), |
| 9068 | }, | 9293 | }, |
| 9069 | { | 9294 | { |
| 9295 | .freq = 5190, | ||
| 9296 | RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02, | ||
| 9297 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, | ||
| 9298 | 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d, | ||
| 9299 | 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, | ||
| 9300 | 0x00, 0x0d, 0x00, 0x6f, 0x00), | ||
| 9301 | PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa), | ||
| 9302 | }, | ||
| 9303 | { | ||
| 9070 | .freq = 5200, | 9304 | .freq = 5200, |
| 9071 | RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02, | 9305 | RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02, |
| 9072 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, | 9306 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, |
| @@ -9076,6 +9310,15 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev | |||
| 9076 | PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), | 9310 | PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9), |
| 9077 | }, | 9311 | }, |
| 9078 | { | 9312 | { |
| 9313 | .freq = 5210, | ||
| 9314 | RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02, | ||
| 9315 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, | ||
| 9316 | 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, | ||
| 9317 | 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, | ||
| 9318 | 0x00, 0x0d, 0x00, 0x6f, 0x00), | ||
| 9319 | PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8), | ||
| 9320 | }, | ||
| 9321 | { | ||
| 9079 | .freq = 5220, | 9322 | .freq = 5220, |
| 9080 | RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02, | 9323 | RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02, |
| 9081 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, | 9324 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, |
| @@ -9085,6 +9328,492 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev | |||
| 9085 | PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), | 9328 | PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7), |
| 9086 | }, | 9329 | }, |
| 9087 | { | 9330 | { |
| 9331 | .freq = 5230, | ||
| 9332 | RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02, | ||
| 9333 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, | ||
| 9334 | 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, | ||
| 9335 | 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, | ||
| 9336 | 0x00, 0x0d, 0x00, 0x6f, 0x00), | ||
| 9337 | PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6), | ||
| 9338 | }, | ||
| 9339 | { | ||
| 9340 | .freq = 5240, | ||
| 9341 | RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02, | ||
| 9342 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, | ||
| 9343 | 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, | ||
| 9344 | 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, | ||
| 9345 | 0x00, 0x0d, 0x00, 0x6f, 0x00), | ||
| 9346 | PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5), | ||
| 9347 | }, | ||
| 9348 | { | ||
| 9349 | .freq = 5250, | ||
| 9350 | RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02, | ||
| 9351 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, | ||
| 9352 | 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d, | ||
| 9353 | 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, | ||
| 9354 | 0x00, 0x0d, 0x00, 0x6f, 0x00), | ||
| 9355 | PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4), | ||
| 9356 | }, | ||
| 9357 | { | ||
| 9358 | .freq = 5260, | ||
| 9359 | RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02, | ||
| 9360 | 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, | ||
| 9361 | 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d, | ||
| 9362 | 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, | ||
| 9363 | 0x00, 0x0d, 0x00, 0x6f, 0x00), | ||
| 9364 | PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3), | ||
| 9365 | }, | ||
| 9366 | { | ||
| 9367 | .freq = 5270, | ||
| 9368 | RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02, | ||
| 9369 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, | ||
| 9370 | 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c, | ||
| 9371 | 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, | ||
| 9372 | 0x00, 0x0c, 0x00, 0x6f, 0x00), | ||
| 9373 | PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2), | ||
| 9374 | }, | ||
| 9375 | { | ||
| 9376 | .freq = 5280, | ||
| 9377 | RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02, | ||
| 9378 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, | ||
| 9379 | 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, | ||
| 9380 | 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, | ||
| 9381 | 0x00, 0x0c, 0x00, 0x6f, 0x00), | ||
| 9382 | PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1), | ||
| 9383 | }, | ||
| 9384 | { | ||
| 9385 | .freq = 5290, | ||
| 9386 | RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02, | ||
| 9387 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, | ||
| 9388 | 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, | ||
| 9389 | 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, | ||
| 9390 | 0x00, 0x0c, 0x00, 0x6f, 0x00), | ||
| 9391 | PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0), | ||
| 9392 | }, | ||
| 9393 | { | ||
| 9394 | .freq = 5300, | ||
| 9395 | RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02, | ||
| 9396 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, | ||
| 9397 | 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, | ||
| 9398 | 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, | ||
| 9399 | 0x00, 0x0c, 0x00, 0x6f, 0x00), | ||
| 9400 | PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0), | ||
| 9401 | }, | ||
| 9402 | { | ||
| 9403 | .freq = 5310, | ||
| 9404 | RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02, | ||
| 9405 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, | ||
| 9406 | 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, | ||
| 9407 | 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, | ||
| 9408 | 0x00, 0x0c, 0x00, 0x6f, 0x00), | ||
| 9409 | PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef), | ||
| 9410 | }, | ||
| 9411 | { | ||
| 9412 | .freq = 5320, | ||
| 9413 | RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02, | ||
| 9414 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, | ||
| 9415 | 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c, | ||
| 9416 | 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, | ||
| 9417 | 0x00, 0x0c, 0x00, 0x6f, 0x00), | ||
| 9418 | PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee), | ||
| 9419 | }, | ||
| 9420 | { | ||
| 9421 | .freq = 5330, | ||
| 9422 | RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02, | ||
| 9423 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, | ||
| 9424 | 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, | ||
| 9425 | 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, | ||
| 9426 | 0x00, 0x0b, 0x00, 0x6f, 0x00), | ||
| 9427 | PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed), | ||
| 9428 | }, | ||
| 9429 | { | ||
| 9430 | .freq = 5340, | ||
| 9431 | RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02, | ||
| 9432 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, | ||
| 9433 | 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, | ||
| 9434 | 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, | ||
| 9435 | 0x00, 0x0b, 0x00, 0x6f, 0x00), | ||
| 9436 | PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec), | ||
| 9437 | }, | ||
| 9438 | { | ||
| 9439 | .freq = 5350, | ||
| 9440 | RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02, | ||
| 9441 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, | ||
| 9442 | 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b, | ||
| 9443 | 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, | ||
| 9444 | 0x00, 0x0b, 0x00, 0x6f, 0x00), | ||
| 9445 | PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb), | ||
| 9446 | }, | ||
| 9447 | { | ||
| 9448 | .freq = 5360, | ||
| 9449 | RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02, | ||
| 9450 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, | ||
| 9451 | 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, | ||
| 9452 | 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, | ||
| 9453 | 0x00, 0x0a, 0x00, 0x6f, 0x00), | ||
| 9454 | PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea), | ||
| 9455 | }, | ||
| 9456 | { | ||
| 9457 | .freq = 5370, | ||
| 9458 | RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02, | ||
| 9459 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, | ||
| 9460 | 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, | ||
| 9461 | 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, | ||
| 9462 | 0x00, 0x0a, 0x00, 0x6f, 0x00), | ||
| 9463 | PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9), | ||
| 9464 | }, | ||
| 9465 | { | ||
| 9466 | .freq = 5380, | ||
| 9467 | RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02, | ||
| 9468 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, | ||
| 9469 | 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, | ||
| 9470 | 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, | ||
| 9471 | 0x00, 0x0a, 0x00, 0x6f, 0x00), | ||
| 9472 | PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8), | ||
| 9473 | }, | ||
| 9474 | { | ||
| 9475 | .freq = 5390, | ||
| 9476 | RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02, | ||
| 9477 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, | ||
| 9478 | 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, | ||
| 9479 | 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, | ||
| 9480 | 0x00, 0x0a, 0x00, 0x6f, 0x00), | ||
| 9481 | PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7), | ||
| 9482 | }, | ||
| 9483 | { | ||
| 9484 | .freq = 5400, | ||
| 9485 | RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02, | ||
| 9486 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, | ||
| 9487 | 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a, | ||
| 9488 | 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, | ||
| 9489 | 0x00, 0x0a, 0x00, 0x6f, 0x00), | ||
| 9490 | PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6), | ||
| 9491 | }, | ||
| 9492 | { | ||
| 9493 | .freq = 5410, | ||
| 9494 | RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02, | ||
| 9495 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, | ||
| 9496 | 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, | ||
| 9497 | 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, | ||
| 9498 | 0x00, 0x0a, 0x00, 0x6f, 0x00), | ||
| 9499 | PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5), | ||
| 9500 | }, | ||
| 9501 | { | ||
| 9502 | .freq = 5420, | ||
| 9503 | RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02, | ||
| 9504 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, | ||
| 9505 | 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, | ||
| 9506 | 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, | ||
| 9507 | 0x00, 0x0a, 0x00, 0x6f, 0x00), | ||
| 9508 | PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5), | ||
| 9509 | }, | ||
| 9510 | { | ||
| 9511 | .freq = 5430, | ||
| 9512 | RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02, | ||
| 9513 | 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, | ||
| 9514 | 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a, | ||
| 9515 | 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, | ||
| 9516 | 0x00, 0x0a, 0x00, 0x6f, 0x00), | ||
| 9517 | PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4), | ||
| 9518 | }, | ||
| 9519 | { | ||
| 9520 | .freq = 5440, | ||
| 9521 | RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02, | ||
| 9522 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, | ||
| 9523 | 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09, | ||
| 9524 | 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, | ||
| 9525 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9526 | PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3), | ||
| 9527 | }, | ||
| 9528 | { | ||
| 9529 | .freq = 5450, | ||
| 9530 | RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02, | ||
| 9531 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, | ||
| 9532 | 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, | ||
| 9533 | 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, | ||
| 9534 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9535 | PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2), | ||
| 9536 | }, | ||
| 9537 | { | ||
| 9538 | .freq = 5460, | ||
| 9539 | RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02, | ||
| 9540 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, | ||
| 9541 | 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, | ||
| 9542 | 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, | ||
| 9543 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9544 | PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1), | ||
| 9545 | }, | ||
| 9546 | { | ||
| 9547 | .freq = 5470, | ||
| 9548 | RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02, | ||
| 9549 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, | ||
| 9550 | 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09, | ||
| 9551 | 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, | ||
| 9552 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9553 | PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0), | ||
| 9554 | }, | ||
| 9555 | { | ||
| 9556 | .freq = 5480, | ||
| 9557 | RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02, | ||
| 9558 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, | ||
| 9559 | 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, | ||
| 9560 | 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, | ||
| 9561 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9562 | PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df), | ||
| 9563 | }, | ||
| 9564 | { | ||
| 9565 | .freq = 5490, | ||
| 9566 | RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02, | ||
| 9567 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, | ||
| 9568 | 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, | ||
| 9569 | 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, | ||
| 9570 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9571 | PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de), | ||
| 9572 | }, | ||
| 9573 | { | ||
| 9574 | .freq = 5500, | ||
| 9575 | RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02, | ||
| 9576 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, | ||
| 9577 | 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, | ||
| 9578 | 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, | ||
| 9579 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9580 | PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd), | ||
| 9581 | }, | ||
| 9582 | { | ||
| 9583 | .freq = 5510, | ||
| 9584 | RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02, | ||
| 9585 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, | ||
| 9586 | 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, | ||
| 9587 | 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, | ||
| 9588 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9589 | PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd), | ||
| 9590 | }, | ||
| 9591 | { | ||
| 9592 | .freq = 5520, | ||
| 9593 | RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02, | ||
| 9594 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, | ||
| 9595 | 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, | ||
| 9596 | 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, | ||
| 9597 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9598 | PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc), | ||
| 9599 | }, | ||
| 9600 | { | ||
| 9601 | .freq = 5530, | ||
| 9602 | RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02, | ||
| 9603 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, | ||
| 9604 | 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, | ||
| 9605 | 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, | ||
| 9606 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9607 | PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db), | ||
| 9608 | }, | ||
| 9609 | { | ||
| 9610 | .freq = 5540, | ||
| 9611 | RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02, | ||
| 9612 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, | ||
| 9613 | 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, | ||
| 9614 | 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, | ||
| 9615 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9616 | PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da), | ||
| 9617 | }, | ||
| 9618 | { | ||
| 9619 | .freq = 5550, | ||
| 9620 | RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02, | ||
| 9621 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, | ||
| 9622 | 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, | ||
| 9623 | 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, | ||
| 9624 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9625 | PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9), | ||
| 9626 | }, | ||
| 9627 | { | ||
| 9628 | .freq = 5560, | ||
| 9629 | RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02, | ||
| 9630 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, | ||
| 9631 | 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, | ||
| 9632 | 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, | ||
| 9633 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9634 | PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8), | ||
| 9635 | }, | ||
| 9636 | { | ||
| 9637 | .freq = 5570, | ||
| 9638 | RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02, | ||
| 9639 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, | ||
| 9640 | 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09, | ||
| 9641 | 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, | ||
| 9642 | 0x00, 0x09, 0x00, 0x6f, 0x00), | ||
| 9643 | PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7), | ||
| 9644 | }, | ||
| 9645 | { | ||
| 9646 | .freq = 5580, | ||
| 9647 | RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02, | ||
| 9648 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, | ||
| 9649 | 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, | ||
| 9650 | 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, | ||
| 9651 | 0x00, 0x08, 0x00, 0x6f, 0x00), | ||
| 9652 | PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7), | ||
| 9653 | }, | ||
| 9654 | { | ||
| 9655 | .freq = 5590, | ||
| 9656 | RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02, | ||
| 9657 | 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, | ||
| 9658 | 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, | ||
| 9659 | 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, | ||
| 9660 | 0x00, 0x08, 0x00, 0x6f, 0x00), | ||
| 9661 | PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6), | ||
| 9662 | }, | ||
| 9663 | { | ||
| 9664 | .freq = 5600, | ||
| 9665 | RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02, | ||
| 9666 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, | ||
| 9667 | 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, | ||
| 9668 | 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, | ||
| 9669 | 0x00, 0x08, 0x00, 0x6f, 0x00), | ||
| 9670 | PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5), | ||
| 9671 | }, | ||
| 9672 | { | ||
| 9673 | .freq = 5610, | ||
| 9674 | RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02, | ||
| 9675 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, | ||
| 9676 | 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08, | ||
| 9677 | 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, | ||
| 9678 | 0x00, 0x08, 0x00, 0x6f, 0x00), | ||
| 9679 | PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4), | ||
| 9680 | }, | ||
| 9681 | { | ||
| 9682 | .freq = 5620, | ||
| 9683 | RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02, | ||
| 9684 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, | ||
| 9685 | 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, | ||
| 9686 | 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, | ||
| 9687 | 0x00, 0x07, 0x00, 0x6f, 0x00), | ||
| 9688 | PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3), | ||
| 9689 | }, | ||
| 9690 | { | ||
| 9691 | .freq = 5630, | ||
| 9692 | RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02, | ||
| 9693 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, | ||
| 9694 | 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, | ||
| 9695 | 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, | ||
| 9696 | 0x00, 0x07, 0x00, 0x6f, 0x00), | ||
| 9697 | PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2), | ||
| 9698 | }, | ||
| 9699 | { | ||
| 9700 | .freq = 5640, | ||
| 9701 | RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02, | ||
| 9702 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, | ||
| 9703 | 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, | ||
| 9704 | 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, | ||
| 9705 | 0x00, 0x07, 0x00, 0x6f, 0x00), | ||
| 9706 | PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2), | ||
| 9707 | }, | ||
| 9708 | { | ||
| 9709 | .freq = 5650, | ||
| 9710 | RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02, | ||
| 9711 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, | ||
| 9712 | 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07, | ||
| 9713 | 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, | ||
| 9714 | 0x00, 0x07, 0x00, 0x6f, 0x00), | ||
| 9715 | PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1), | ||
| 9716 | }, | ||
| 9717 | { | ||
| 9718 | .freq = 5660, | ||
| 9719 | RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02, | ||
| 9720 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, | ||
| 9721 | 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, | ||
| 9722 | 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, | ||
| 9723 | 0x00, 0x06, 0x00, 0x6f, 0x00), | ||
| 9724 | PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0), | ||
| 9725 | }, | ||
| 9726 | { | ||
| 9727 | .freq = 5670, | ||
| 9728 | RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02, | ||
| 9729 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, | ||
| 9730 | 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, | ||
| 9731 | 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, | ||
| 9732 | 0x00, 0x06, 0x00, 0x6f, 0x00), | ||
| 9733 | PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf), | ||
| 9734 | }, | ||
| 9735 | { | ||
| 9736 | .freq = 5680, | ||
| 9737 | RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02, | ||
| 9738 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, | ||
| 9739 | 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, | ||
| 9740 | 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, | ||
| 9741 | 0x00, 0x06, 0x00, 0x6f, 0x00), | ||
| 9742 | PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce), | ||
| 9743 | }, | ||
| 9744 | { | ||
| 9745 | .freq = 5690, | ||
| 9746 | RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02, | ||
| 9747 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, | ||
| 9748 | 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, | ||
| 9749 | 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, | ||
| 9750 | 0x00, 0x06, 0x00, 0x6f, 0x00), | ||
| 9751 | PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce), | ||
| 9752 | }, | ||
| 9753 | { | ||
| 9754 | .freq = 5700, | ||
| 9755 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02, | ||
| 9756 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, | ||
| 9757 | 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, | ||
| 9758 | 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, | ||
| 9759 | 0x00, 0x06, 0x00, 0x6e, 0x00), | ||
| 9760 | PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd), | ||
| 9761 | }, | ||
| 9762 | { | ||
| 9763 | .freq = 5710, | ||
| 9764 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02, | ||
| 9765 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, | ||
| 9766 | 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, | ||
| 9767 | 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, | ||
| 9768 | 0x00, 0x06, 0x00, 0x6e, 0x00), | ||
| 9769 | PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc), | ||
| 9770 | }, | ||
| 9771 | { | ||
| 9772 | .freq = 5720, | ||
| 9773 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02, | ||
| 9774 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, | ||
| 9775 | 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, | ||
| 9776 | 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, | ||
| 9777 | 0x00, 0x06, 0x00, 0x6e, 0x00), | ||
| 9778 | PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb), | ||
| 9779 | }, | ||
| 9780 | { | ||
| 9781 | .freq = 5725, | ||
| 9782 | RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02, | ||
| 9783 | 0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, | ||
| 9784 | 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, | ||
| 9785 | 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, | ||
| 9786 | 0x00, 0x06, 0x00, 0x6e, 0x00), | ||
| 9787 | PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb), | ||
| 9788 | }, | ||
| 9789 | { | ||
| 9790 | .freq = 5730, | ||
| 9791 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02, | ||
| 9792 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, | ||
| 9793 | 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, | ||
| 9794 | 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, | ||
| 9795 | 0x00, 0x06, 0x00, 0x6e, 0x00), | ||
| 9796 | PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca), | ||
| 9797 | }, | ||
| 9798 | { | ||
| 9799 | .freq = 5735, | ||
| 9800 | RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02, | ||
| 9801 | 0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, | ||
| 9802 | 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, | ||
| 9803 | 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, | ||
| 9804 | 0x00, 0x06, 0x00, 0x6d, 0x00), | ||
| 9805 | PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca), | ||
| 9806 | }, | ||
| 9807 | { | ||
| 9808 | .freq = 5740, | ||
| 9809 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02, | ||
| 9810 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, | ||
| 9811 | 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06, | ||
| 9812 | 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, | ||
| 9813 | 0x00, 0x06, 0x00, 0x6d, 0x00), | ||
| 9814 | PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9), | ||
| 9815 | }, | ||
| 9816 | { | ||
| 9088 | .freq = 5745, | 9817 | .freq = 5745, |
| 9089 | RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02, | 9818 | RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02, |
| 9090 | 0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, | 9819 | 0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, |
| @@ -9094,6 +9823,33 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev | |||
| 9094 | PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), | 9823 | PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9), |
| 9095 | }, | 9824 | }, |
| 9096 | { | 9825 | { |
| 9826 | .freq = 5750, | ||
| 9827 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02, | ||
| 9828 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, | ||
| 9829 | 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9830 | 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, | ||
| 9831 | 0x00, 0x05, 0x00, 0x6d, 0x00), | ||
| 9832 | PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9), | ||
| 9833 | }, | ||
| 9834 | { | ||
| 9835 | .freq = 5755, | ||
| 9836 | RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02, | ||
| 9837 | 0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, | ||
| 9838 | 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9839 | 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, | ||
| 9840 | 0x00, 0x05, 0x00, 0x6c, 0x00), | ||
| 9841 | PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8), | ||
| 9842 | }, | ||
| 9843 | { | ||
| 9844 | .freq = 5760, | ||
| 9845 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02, | ||
| 9846 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, | ||
| 9847 | 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9848 | 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, | ||
| 9849 | 0x00, 0x05, 0x00, 0x6c, 0x00), | ||
| 9850 | PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8), | ||
| 9851 | }, | ||
| 9852 | { | ||
| 9097 | .freq = 5765, | 9853 | .freq = 5765, |
| 9098 | RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02, | 9854 | RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02, |
| 9099 | 0x15, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, | 9855 | 0x15, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, |
| @@ -9103,6 +9859,33 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev | |||
| 9103 | PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), | 9859 | PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8), |
| 9104 | }, | 9860 | }, |
| 9105 | { | 9861 | { |
| 9862 | .freq = 5770, | ||
| 9863 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02, | ||
| 9864 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, | ||
| 9865 | 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9866 | 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, | ||
| 9867 | 0x00, 0x05, 0x00, 0x6b, 0x00), | ||
| 9868 | PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7), | ||
| 9869 | }, | ||
| 9870 | { | ||
| 9871 | .freq = 5775, | ||
| 9872 | RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02, | ||
| 9873 | 0x15, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, | ||
| 9874 | 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9875 | 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, | ||
| 9876 | 0x00, 0x05, 0x00, 0x6b, 0x00), | ||
| 9877 | PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7), | ||
| 9878 | }, | ||
| 9879 | { | ||
| 9880 | .freq = 5780, | ||
| 9881 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02, | ||
| 9882 | 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, | ||
| 9883 | 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9884 | 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, | ||
| 9885 | 0x00, 0x05, 0x00, 0x6b, 0x00), | ||
| 9886 | PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6), | ||
| 9887 | }, | ||
| 9888 | { | ||
| 9106 | .freq = 5785, | 9889 | .freq = 5785, |
| 9107 | RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02, | 9890 | RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02, |
| 9108 | 0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, | 9891 | 0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, |
| @@ -9112,6 +9895,33 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev | |||
| 9112 | PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), | 9895 | PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6), |
| 9113 | }, | 9896 | }, |
| 9114 | { | 9897 | { |
| 9898 | .freq = 5790, | ||
| 9899 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02, | ||
| 9900 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, | ||
| 9901 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9902 | 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, | ||
| 9903 | 0x00, 0x05, 0x00, 0x6b, 0x00), | ||
| 9904 | PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6), | ||
| 9905 | }, | ||
| 9906 | { | ||
| 9907 | .freq = 5795, | ||
| 9908 | RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02, | ||
| 9909 | 0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, | ||
| 9910 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9911 | 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 9912 | 0x00, 0x05, 0x00, 0x6b, 0x00), | ||
| 9913 | PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5), | ||
| 9914 | }, | ||
| 9915 | { | ||
| 9916 | .freq = 5800, | ||
| 9917 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02, | ||
| 9918 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, | ||
| 9919 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9920 | 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 9921 | 0x00, 0x05, 0x00, 0x6b, 0x00), | ||
| 9922 | PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5), | ||
| 9923 | }, | ||
| 9924 | { | ||
| 9115 | .freq = 5805, | 9925 | .freq = 5805, |
| 9116 | RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02, | 9926 | RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02, |
| 9117 | 0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, | 9927 | 0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, |
| @@ -9121,6 +9931,33 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev | |||
| 9121 | PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), | 9931 | PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4), |
| 9122 | }, | 9932 | }, |
| 9123 | { | 9933 | { |
| 9934 | .freq = 5810, | ||
| 9935 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02, | ||
| 9936 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, | ||
| 9937 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9938 | 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 9939 | 0x00, 0x05, 0x00, 0x6a, 0x00), | ||
| 9940 | PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4), | ||
| 9941 | }, | ||
| 9942 | { | ||
| 9943 | .freq = 5815, | ||
| 9944 | RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02, | ||
| 9945 | 0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, | ||
| 9946 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9947 | 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 9948 | 0x00, 0x05, 0x00, 0x6a, 0x00), | ||
| 9949 | PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4), | ||
| 9950 | }, | ||
| 9951 | { | ||
| 9952 | .freq = 5820, | ||
| 9953 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02, | ||
| 9954 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, | ||
| 9955 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9956 | 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 9957 | 0x00, 0x05, 0x00, 0x6a, 0x00), | ||
| 9958 | PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3), | ||
| 9959 | }, | ||
| 9960 | { | ||
| 9124 | .freq = 5825, | 9961 | .freq = 5825, |
| 9125 | RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02, | 9962 | RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02, |
| 9126 | 0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, | 9963 | 0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, |
| @@ -9130,6 +9967,87 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev | |||
| 9130 | PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), | 9967 | PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3), |
| 9131 | }, | 9968 | }, |
| 9132 | { | 9969 | { |
| 9970 | .freq = 5830, | ||
| 9971 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02, | ||
| 9972 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, | ||
| 9973 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, | ||
| 9974 | 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 9975 | 0x00, 0x05, 0x00, 0x69, 0x00), | ||
| 9976 | PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2), | ||
| 9977 | }, | ||
| 9978 | { | ||
| 9979 | .freq = 5840, | ||
| 9980 | RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02, | ||
| 9981 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, | ||
| 9982 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, | ||
| 9983 | 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 9984 | 0x00, 0x04, 0x00, 0x69, 0x00), | ||
| 9985 | PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2), | ||
| 9986 | }, | ||
| 9987 | { | ||
| 9988 | .freq = 5850, | ||
| 9989 | RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02, | ||
| 9990 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, | ||
| 9991 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, | ||
| 9992 | 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 9993 | 0x00, 0x04, 0x00, 0x69, 0x00), | ||
| 9994 | PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1), | ||
| 9995 | }, | ||
| 9996 | { | ||
| 9997 | .freq = 5860, | ||
| 9998 | RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02, | ||
| 9999 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, | ||
| 10000 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, | ||
| 10001 | 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 10002 | 0x00, 0x04, 0x00, 0x69, 0x00), | ||
| 10003 | PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0), | ||
| 10004 | }, | ||
| 10005 | { | ||
| 10006 | .freq = 5870, | ||
| 10007 | RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02, | ||
| 10008 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, | ||
| 10009 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, | ||
| 10010 | 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 10011 | 0x00, 0x04, 0x00, 0x68, 0x00), | ||
| 10012 | PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf), | ||
| 10013 | }, | ||
| 10014 | { | ||
| 10015 | .freq = 5880, | ||
| 10016 | RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02, | ||
| 10017 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, | ||
| 10018 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, | ||
| 10019 | 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 10020 | 0x00, 0x04, 0x00, 0x68, 0x00), | ||
| 10021 | PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf), | ||
| 10022 | }, | ||
| 10023 | { | ||
| 10024 | .freq = 5890, | ||
| 10025 | RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02, | ||
| 10026 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, | ||
| 10027 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, | ||
| 10028 | 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 10029 | 0x00, 0x04, 0x00, 0x68, 0x00), | ||
| 10030 | PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be), | ||
| 10031 | }, | ||
| 10032 | { | ||
| 10033 | .freq = 5900, | ||
| 10034 | RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02, | ||
| 10035 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, | ||
| 10036 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, | ||
| 10037 | 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 10038 | 0x00, 0x04, 0x00, 0x68, 0x00), | ||
| 10039 | PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd), | ||
| 10040 | }, | ||
| 10041 | { | ||
| 10042 | .freq = 5910, | ||
| 10043 | RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02, | ||
| 10044 | 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, | ||
| 10045 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, | ||
| 10046 | 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, | ||
| 10047 | 0x00, 0x04, 0x00, 0x68, 0x00), | ||
| 10048 | PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc), | ||
| 10049 | }, | ||
| 10050 | { | ||
| 9133 | .freq = 2412, | 10051 | .freq = 2412, |
| 9134 | RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04, | 10052 | RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04, |
| 9135 | 0x2b, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, | 10053 | 0x2b, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, |
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 31adb8cf0291..4f38f19b8e3d 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
| @@ -408,7 +408,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
| 408 | mac_ctl |= B43_TXH_MAC_HWSEQ; | 408 | mac_ctl |= B43_TXH_MAC_HWSEQ; |
| 409 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | 409 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) |
| 410 | mac_ctl |= B43_TXH_MAC_STMSDU; | 410 | mac_ctl |= B43_TXH_MAC_STMSDU; |
| 411 | if (phy->type == B43_PHYTYPE_A) | 411 | if (!phy->gmode) |
| 412 | mac_ctl |= B43_TXH_MAC_5GHZ; | 412 | mac_ctl |= B43_TXH_MAC_5GHZ; |
| 413 | 413 | ||
| 414 | /* Overwrite rates[0].count to make the retry calculation | 414 | /* Overwrite rates[0].count to make the retry calculation |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 939d6b132922..16f9ab2568a8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
| @@ -186,7 +186,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); | |||
| 186 | void brcmf_txflowblock_if(struct brcmf_if *ifp, | 186 | void brcmf_txflowblock_if(struct brcmf_if *ifp, |
| 187 | enum brcmf_netif_stop_reason reason, bool state); | 187 | enum brcmf_netif_stop_reason reason, bool state); |
| 188 | u32 brcmf_get_chip_info(struct brcmf_if *ifp); | 188 | u32 brcmf_get_chip_info(struct brcmf_if *ifp); |
| 189 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, | 189 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, |
| 190 | bool success); | 190 | bool success); |
| 191 | 191 | ||
| 192 | /* Sets dongle media info (drv_version, mac address). */ | 192 | /* Sets dongle media info (drv_version, mac address). */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index c4535616064e..c5dcd82e884b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
| @@ -99,6 +99,7 @@ struct brcmf_bus { | |||
| 99 | unsigned long tx_realloc; | 99 | unsigned long tx_realloc; |
| 100 | u32 chip; | 100 | u32 chip; |
| 101 | u32 chiprev; | 101 | u32 chiprev; |
| 102 | bool always_use_fws_queue; | ||
| 102 | 103 | ||
| 103 | struct brcmf_bus_ops *ops; | 104 | struct brcmf_bus_ops *ops; |
| 104 | }; | 105 | }; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 6a8983a1fb9c..ed3e32ce8c23 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | |||
| @@ -32,6 +32,9 @@ | |||
| 32 | #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 | 32 | #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 |
| 33 | #define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00" | 33 | #define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00" |
| 34 | 34 | ||
| 35 | /* boost value for RSSI_DELTA in preferred join selection */ | ||
| 36 | #define BRCMF_JOIN_PREF_RSSI_BOOST 8 | ||
| 37 | |||
| 35 | 38 | ||
| 36 | bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, | 39 | bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, |
| 37 | struct sk_buff *pkt, int prec) | 40 | struct sk_buff *pkt, int prec) |
| @@ -246,6 +249,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
| 246 | { | 249 | { |
| 247 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; | 250 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; |
| 248 | u8 buf[BRCMF_DCMD_SMLEN]; | 251 | u8 buf[BRCMF_DCMD_SMLEN]; |
| 252 | struct brcmf_join_pref_params join_pref_params[2]; | ||
| 249 | char *ptr; | 253 | char *ptr; |
| 250 | s32 err; | 254 | s32 err; |
| 251 | 255 | ||
| @@ -298,6 +302,20 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
| 298 | goto done; | 302 | goto done; |
| 299 | } | 303 | } |
| 300 | 304 | ||
| 305 | /* Setup join_pref to select target by RSSI(with boost on 5GHz) */ | ||
| 306 | join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; | ||
| 307 | join_pref_params[0].len = 2; | ||
| 308 | join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; | ||
| 309 | join_pref_params[0].band = WLC_BAND_5G; | ||
| 310 | join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; | ||
| 311 | join_pref_params[1].len = 2; | ||
| 312 | join_pref_params[1].rssi_gain = 0; | ||
| 313 | join_pref_params[1].band = 0; | ||
| 314 | err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, | ||
| 315 | sizeof(join_pref_params)); | ||
| 316 | if (err) | ||
| 317 | brcmf_err("Set join_pref error (%d)\n", err); | ||
| 318 | |||
| 301 | /* Setup event_msgs, enable E_IF */ | 319 | /* Setup event_msgs, enable E_IF */ |
| 302 | err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, | 320 | err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, |
| 303 | BRCMF_EVENTING_MASK_LEN); | 321 | BRCMF_EVENTING_MASK_LEN); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 7d28cd385092..4cacc3d85212 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
| @@ -190,7 +190,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, | |||
| 190 | int ret; | 190 | int ret; |
| 191 | struct brcmf_if *ifp = netdev_priv(ndev); | 191 | struct brcmf_if *ifp = netdev_priv(ndev); |
| 192 | struct brcmf_pub *drvr = ifp->drvr; | 192 | struct brcmf_pub *drvr = ifp->drvr; |
| 193 | struct ethhdr *eh; | 193 | struct ethhdr *eh = (struct ethhdr *)(skb->data); |
| 194 | 194 | ||
| 195 | brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx); | 195 | brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx); |
| 196 | 196 | ||
| @@ -236,6 +236,9 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, | |||
| 236 | goto done; | 236 | goto done; |
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | if (eh->h_proto == htons(ETH_P_PAE)) | ||
| 240 | atomic_inc(&ifp->pend_8021x_cnt); | ||
| 241 | |||
| 239 | ret = brcmf_fws_process_skb(ifp, skb); | 242 | ret = brcmf_fws_process_skb(ifp, skb); |
| 240 | 243 | ||
| 241 | done: | 244 | done: |
| @@ -538,31 +541,26 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb) | |||
| 538 | brcmf_netif_rx(ifp, skb); | 541 | brcmf_netif_rx(ifp, skb); |
| 539 | } | 542 | } |
| 540 | 543 | ||
| 541 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, | 544 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, |
| 542 | bool success) | 545 | bool success) |
| 543 | { | 546 | { |
| 544 | struct brcmf_if *ifp; | 547 | struct brcmf_if *ifp; |
| 545 | struct ethhdr *eh; | 548 | struct ethhdr *eh; |
| 546 | u8 ifidx; | ||
| 547 | u16 type; | 549 | u16 type; |
| 548 | int res; | ||
| 549 | |||
| 550 | res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp); | ||
| 551 | 550 | ||
| 552 | ifp = drvr->iflist[ifidx]; | 551 | ifp = drvr->iflist[ifidx]; |
| 553 | if (!ifp) | 552 | if (!ifp) |
| 554 | goto done; | 553 | goto done; |
| 555 | 554 | ||
| 556 | if (res == 0) { | 555 | eh = (struct ethhdr *)(txp->data); |
| 557 | eh = (struct ethhdr *)(txp->data); | 556 | type = ntohs(eh->h_proto); |
| 558 | type = ntohs(eh->h_proto); | ||
| 559 | 557 | ||
| 560 | if (type == ETH_P_PAE) { | 558 | if (type == ETH_P_PAE) { |
| 561 | atomic_dec(&ifp->pend_8021x_cnt); | 559 | atomic_dec(&ifp->pend_8021x_cnt); |
| 562 | if (waitqueue_active(&ifp->pend_8021x_wait)) | 560 | if (waitqueue_active(&ifp->pend_8021x_wait)) |
| 563 | wake_up(&ifp->pend_8021x_wait); | 561 | wake_up(&ifp->pend_8021x_wait); |
| 564 | } | ||
| 565 | } | 562 | } |
| 563 | |||
| 566 | if (!success) | 564 | if (!success) |
| 567 | ifp->stats.tx_errors++; | 565 | ifp->stats.tx_errors++; |
| 568 | done: | 566 | done: |
| @@ -573,13 +571,17 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) | |||
| 573 | { | 571 | { |
| 574 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 572 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
| 575 | struct brcmf_pub *drvr = bus_if->drvr; | 573 | struct brcmf_pub *drvr = bus_if->drvr; |
| 574 | u8 ifidx; | ||
| 576 | 575 | ||
| 577 | /* await txstatus signal for firmware if active */ | 576 | /* await txstatus signal for firmware if active */ |
| 578 | if (brcmf_fws_fc_active(drvr->fws)) { | 577 | if (brcmf_fws_fc_active(drvr->fws)) { |
| 579 | if (!success) | 578 | if (!success) |
| 580 | brcmf_fws_bustxfail(drvr->fws, txp); | 579 | brcmf_fws_bustxfail(drvr->fws, txp); |
| 581 | } else { | 580 | } else { |
| 582 | brcmf_txfinalize(drvr, txp, success); | 581 | if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp)) |
| 582 | brcmu_pkt_buf_free_skb(txp); | ||
| 583 | else | ||
| 584 | brcmf_txfinalize(drvr, txp, ifidx, success); | ||
| 583 | } | 585 | } |
| 584 | } | 586 | } |
| 585 | 587 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index 614e4888504f..2bc68a2137fc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | |||
| @@ -53,6 +53,14 @@ | |||
| 53 | #define BRCMF_OBSS_COEX_OFF 0 | 53 | #define BRCMF_OBSS_COEX_OFF 0 |
| 54 | #define BRCMF_OBSS_COEX_ON 1 | 54 | #define BRCMF_OBSS_COEX_ON 1 |
| 55 | 55 | ||
| 56 | /* join preference types for join_pref iovar */ | ||
| 57 | enum brcmf_join_pref_types { | ||
| 58 | BRCMF_JOIN_PREF_RSSI = 1, | ||
| 59 | BRCMF_JOIN_PREF_WPA, | ||
| 60 | BRCMF_JOIN_PREF_BAND, | ||
| 61 | BRCMF_JOIN_PREF_RSSI_DELTA, | ||
| 62 | }; | ||
| 63 | |||
| 56 | enum brcmf_fil_p2p_if_types { | 64 | enum brcmf_fil_p2p_if_types { |
| 57 | BRCMF_FIL_P2P_IF_CLIENT, | 65 | BRCMF_FIL_P2P_IF_CLIENT, |
| 58 | BRCMF_FIL_P2P_IF_GO, | 66 | BRCMF_FIL_P2P_IF_GO, |
| @@ -282,6 +290,22 @@ struct brcmf_assoc_params_le { | |||
| 282 | __le16 chanspec_list[1]; | 290 | __le16 chanspec_list[1]; |
| 283 | }; | 291 | }; |
| 284 | 292 | ||
| 293 | /** | ||
| 294 | * struct join_pref params - parameters for preferred join selection. | ||
| 295 | * | ||
| 296 | * @type: preference type (see enum brcmf_join_pref_types). | ||
| 297 | * @len: length of bytes following (currently always 2). | ||
| 298 | * @rssi_gain: signal gain for selection (only when @type is RSSI_DELTA). | ||
| 299 | * @band: band to which selection preference applies. | ||
| 300 | * This is used if @type is BAND or RSSI_DELTA. | ||
| 301 | */ | ||
| 302 | struct brcmf_join_pref_params { | ||
| 303 | u8 type; | ||
| 304 | u8 len; | ||
| 305 | u8 rssi_gain; | ||
| 306 | u8 band; | ||
| 307 | }; | ||
| 308 | |||
| 285 | /* used for join with or without a specific bssid and channel list */ | 309 | /* used for join with or without a specific bssid and channel list */ |
| 286 | struct brcmf_join_params { | 310 | struct brcmf_join_params { |
| 287 | struct brcmf_ssid_le ssid_le; | 311 | struct brcmf_ssid_le ssid_le; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index c3e7d76dbf35..699908de314a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
| @@ -476,6 +476,7 @@ struct brcmf_fws_info { | |||
| 476 | bool bus_flow_blocked; | 476 | bool bus_flow_blocked; |
| 477 | bool creditmap_received; | 477 | bool creditmap_received; |
| 478 | u8 mode; | 478 | u8 mode; |
| 479 | bool avoid_queueing; | ||
| 479 | }; | 480 | }; |
| 480 | 481 | ||
| 481 | /* | 482 | /* |
| @@ -1369,13 +1370,12 @@ done: | |||
| 1369 | } | 1370 | } |
| 1370 | 1371 | ||
| 1371 | static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, | 1372 | static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, |
| 1372 | struct sk_buff *skb, u32 genbit, | 1373 | struct sk_buff *skb, u8 ifidx, |
| 1373 | u16 seq) | 1374 | u32 genbit, u16 seq) |
| 1374 | { | 1375 | { |
| 1375 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; | 1376 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; |
| 1376 | u32 hslot; | 1377 | u32 hslot; |
| 1377 | int ret; | 1378 | int ret; |
| 1378 | u8 ifidx; | ||
| 1379 | 1379 | ||
| 1380 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); | 1380 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); |
| 1381 | 1381 | ||
| @@ -1389,29 +1389,21 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, | |||
| 1389 | 1389 | ||
| 1390 | entry->generation = genbit; | 1390 | entry->generation = genbit; |
| 1391 | 1391 | ||
| 1392 | ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); | 1392 | brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit); |
| 1393 | if (ret == 0) { | 1393 | brcmf_skbcb(skb)->htod_seq = seq; |
| 1394 | brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit); | 1394 | if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) { |
| 1395 | brcmf_skbcb(skb)->htod_seq = seq; | 1395 | brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1); |
| 1396 | if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) { | 1396 | brcmf_skb_htod_seq_set_field(skb, FROMFW, 0); |
| 1397 | brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1); | 1397 | } else { |
| 1398 | brcmf_skb_htod_seq_set_field(skb, FROMFW, 0); | 1398 | brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0); |
| 1399 | } else { | ||
| 1400 | brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0); | ||
| 1401 | } | ||
| 1402 | ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, | ||
| 1403 | skb); | ||
| 1404 | } | 1399 | } |
| 1400 | ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb); | ||
| 1405 | 1401 | ||
| 1406 | if (ret != 0) { | 1402 | if (ret != 0) { |
| 1407 | /* suppress q is full or hdrpull failed, drop this packet */ | 1403 | /* suppress q is full drop this packet */ |
| 1408 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, | 1404 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, true); |
| 1409 | true); | ||
| 1410 | } else { | 1405 | } else { |
| 1411 | /* | 1406 | /* Mark suppressed to avoid a double free during wlfc cleanup */ |
| 1412 | * Mark suppressed to avoid a double free during | ||
| 1413 | * wlfc cleanup | ||
| 1414 | */ | ||
| 1415 | brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot); | 1407 | brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot); |
| 1416 | } | 1408 | } |
| 1417 | 1409 | ||
| @@ -1428,6 +1420,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, | |||
| 1428 | struct sk_buff *skb; | 1420 | struct sk_buff *skb; |
| 1429 | struct brcmf_skbuff_cb *skcb; | 1421 | struct brcmf_skbuff_cb *skcb; |
| 1430 | struct brcmf_fws_mac_descriptor *entry = NULL; | 1422 | struct brcmf_fws_mac_descriptor *entry = NULL; |
| 1423 | u8 ifidx; | ||
| 1431 | 1424 | ||
| 1432 | brcmf_dbg(DATA, "flags %d\n", flags); | 1425 | brcmf_dbg(DATA, "flags %d\n", flags); |
| 1433 | 1426 | ||
| @@ -1476,12 +1469,15 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, | |||
| 1476 | } | 1469 | } |
| 1477 | brcmf_fws_macdesc_return_req_credit(skb); | 1470 | brcmf_fws_macdesc_return_req_credit(skb); |
| 1478 | 1471 | ||
| 1472 | if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) { | ||
| 1473 | brcmu_pkt_buf_free_skb(skb); | ||
| 1474 | return -EINVAL; | ||
| 1475 | } | ||
| 1479 | if (!remove_from_hanger) | 1476 | if (!remove_from_hanger) |
| 1480 | ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit, | 1477 | ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx, |
| 1481 | seq); | 1478 | genbit, seq); |
| 1482 | |||
| 1483 | if (remove_from_hanger || ret) | 1479 | if (remove_from_hanger || ret) |
| 1484 | brcmf_txfinalize(fws->drvr, skb, true); | 1480 | brcmf_txfinalize(fws->drvr, skb, ifidx, true); |
| 1485 | 1481 | ||
| 1486 | return 0; | 1482 | return 0; |
| 1487 | } | 1483 | } |
| @@ -1868,7 +1864,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) | |||
| 1868 | struct ethhdr *eh = (struct ethhdr *)(skb->data); | 1864 | struct ethhdr *eh = (struct ethhdr *)(skb->data); |
| 1869 | int fifo = BRCMF_FWS_FIFO_BCMC; | 1865 | int fifo = BRCMF_FWS_FIFO_BCMC; |
| 1870 | bool multicast = is_multicast_ether_addr(eh->h_dest); | 1866 | bool multicast = is_multicast_ether_addr(eh->h_dest); |
| 1871 | bool pae = eh->h_proto == htons(ETH_P_PAE); | 1867 | int rc = 0; |
| 1872 | 1868 | ||
| 1873 | brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto)); | 1869 | brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto)); |
| 1874 | /* determine the priority */ | 1870 | /* determine the priority */ |
| @@ -1876,8 +1872,13 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) | |||
| 1876 | skb->priority = cfg80211_classify8021d(skb, NULL); | 1872 | skb->priority = cfg80211_classify8021d(skb, NULL); |
| 1877 | 1873 | ||
| 1878 | drvr->tx_multicast += !!multicast; | 1874 | drvr->tx_multicast += !!multicast; |
| 1879 | if (pae) | 1875 | |
| 1880 | atomic_inc(&ifp->pend_8021x_cnt); | 1876 | if (fws->avoid_queueing) { |
| 1877 | rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb); | ||
| 1878 | if (rc < 0) | ||
| 1879 | brcmf_txfinalize(drvr, skb, ifp->ifidx, false); | ||
| 1880 | return rc; | ||
| 1881 | } | ||
| 1881 | 1882 | ||
| 1882 | /* set control buffer information */ | 1883 | /* set control buffer information */ |
| 1883 | skcb->if_flags = 0; | 1884 | skcb->if_flags = 0; |
| @@ -1899,15 +1900,12 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) | |||
| 1899 | brcmf_fws_schedule_deq(fws); | 1900 | brcmf_fws_schedule_deq(fws); |
| 1900 | } else { | 1901 | } else { |
| 1901 | brcmf_err("drop skb: no hanger slot\n"); | 1902 | brcmf_err("drop skb: no hanger slot\n"); |
| 1902 | if (pae) { | 1903 | brcmf_txfinalize(drvr, skb, ifp->ifidx, false); |
| 1903 | atomic_dec(&ifp->pend_8021x_cnt); | 1904 | rc = -ENOMEM; |
| 1904 | if (waitqueue_active(&ifp->pend_8021x_wait)) | ||
| 1905 | wake_up(&ifp->pend_8021x_wait); | ||
| 1906 | } | ||
| 1907 | brcmu_pkt_buf_free_skb(skb); | ||
| 1908 | } | 1905 | } |
| 1909 | brcmf_fws_unlock(fws); | 1906 | brcmf_fws_unlock(fws); |
| 1910 | return 0; | 1907 | |
| 1908 | return rc; | ||
| 1911 | } | 1909 | } |
| 1912 | 1910 | ||
| 1913 | void brcmf_fws_reset_interface(struct brcmf_if *ifp) | 1911 | void brcmf_fws_reset_interface(struct brcmf_if *ifp) |
| @@ -1982,7 +1980,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) | |||
| 1982 | ret = brcmf_proto_txdata(drvr, ifidx, 0, skb); | 1980 | ret = brcmf_proto_txdata(drvr, ifidx, 0, skb); |
| 1983 | brcmf_fws_lock(fws); | 1981 | brcmf_fws_lock(fws); |
| 1984 | if (ret < 0) | 1982 | if (ret < 0) |
| 1985 | brcmf_txfinalize(drvr, skb, false); | 1983 | brcmf_txfinalize(drvr, skb, ifidx, |
| 1984 | false); | ||
| 1986 | if (fws->bus_flow_blocked) | 1985 | if (fws->bus_flow_blocked) |
| 1987 | break; | 1986 | break; |
| 1988 | } | 1987 | } |
| @@ -2039,6 +2038,13 @@ int brcmf_fws_init(struct brcmf_pub *drvr) | |||
| 2039 | fws->drvr = drvr; | 2038 | fws->drvr = drvr; |
| 2040 | fws->fcmode = fcmode; | 2039 | fws->fcmode = fcmode; |
| 2041 | 2040 | ||
| 2041 | if ((drvr->bus_if->always_use_fws_queue == false) && | ||
| 2042 | (fcmode == BRCMF_FWS_FCMODE_NONE)) { | ||
| 2043 | fws->avoid_queueing = true; | ||
| 2044 | brcmf_dbg(INFO, "FWS queueing will be avoided\n"); | ||
| 2045 | return 0; | ||
| 2046 | } | ||
| 2047 | |||
| 2042 | fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq"); | 2048 | fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq"); |
| 2043 | if (fws->fws_wq == NULL) { | 2049 | if (fws->fws_wq == NULL) { |
| 2044 | brcmf_err("workqueue creation failed\n"); | 2050 | brcmf_err("workqueue creation failed\n"); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/nvram.c b/drivers/net/wireless/brcm80211/brcmfmac/nvram.c index d5ef86db631b..5c450d11dbc9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/nvram.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/nvram.c | |||
| @@ -18,72 +18,205 @@ | |||
| 18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 19 | #include <linux/firmware.h> | 19 | #include <linux/firmware.h> |
| 20 | 20 | ||
| 21 | #include "dhd_dbg.h" | ||
| 21 | #include "nvram.h" | 22 | #include "nvram.h" |
| 22 | 23 | ||
| 23 | /* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a file | 24 | enum nvram_parser_state { |
| 25 | IDLE, | ||
| 26 | KEY, | ||
| 27 | VALUE, | ||
| 28 | COMMENT, | ||
| 29 | END | ||
| 30 | }; | ||
| 31 | |||
| 32 | /** | ||
| 33 | * struct nvram_parser - internal info for parser. | ||
| 34 | * | ||
| 35 | * @state: current parser state. | ||
| 36 | * @fwnv: input buffer being parsed. | ||
| 37 | * @nvram: output buffer with parse result. | ||
| 38 | * @nvram_len: lenght of parse result. | ||
| 39 | * @line: current line. | ||
| 40 | * @column: current column in line. | ||
| 41 | * @pos: byte offset in input buffer. | ||
| 42 | * @entry: start position of key,value entry. | ||
| 43 | */ | ||
| 44 | struct nvram_parser { | ||
| 45 | enum nvram_parser_state state; | ||
| 46 | const struct firmware *fwnv; | ||
| 47 | u8 *nvram; | ||
| 48 | u32 nvram_len; | ||
| 49 | u32 line; | ||
| 50 | u32 column; | ||
| 51 | u32 pos; | ||
| 52 | u32 entry; | ||
| 53 | }; | ||
| 54 | |||
| 55 | static bool is_nvram_char(char c) | ||
| 56 | { | ||
| 57 | /* comment marker excluded */ | ||
| 58 | if (c == '#') | ||
| 59 | return false; | ||
| 60 | |||
| 61 | /* key and value may have any other readable character */ | ||
| 62 | return (c > 0x20 && c < 0x7f); | ||
| 63 | } | ||
| 64 | |||
| 65 | static bool is_whitespace(char c) | ||
| 66 | { | ||
| 67 | return (c == ' ' || c == '\r' || c == '\n' || c == '\t'); | ||
| 68 | } | ||
| 69 | |||
| 70 | static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp) | ||
| 71 | { | ||
| 72 | char c; | ||
| 73 | |||
| 74 | c = nvp->fwnv->data[nvp->pos]; | ||
| 75 | if (c == '\n') | ||
| 76 | return COMMENT; | ||
| 77 | if (is_whitespace(c)) | ||
| 78 | goto proceed; | ||
| 79 | if (c == '#') | ||
| 80 | return COMMENT; | ||
| 81 | if (is_nvram_char(c)) { | ||
| 82 | nvp->entry = nvp->pos; | ||
| 83 | return KEY; | ||
| 84 | } | ||
| 85 | brcmf_dbg(INFO, "warning: ln=%d:col=%d: ignoring invalid character\n", | ||
| 86 | nvp->line, nvp->column); | ||
| 87 | proceed: | ||
| 88 | nvp->column++; | ||
| 89 | nvp->pos++; | ||
| 90 | return IDLE; | ||
| 91 | } | ||
| 92 | |||
| 93 | static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp) | ||
| 94 | { | ||
| 95 | enum nvram_parser_state st = nvp->state; | ||
| 96 | char c; | ||
| 97 | |||
| 98 | c = nvp->fwnv->data[nvp->pos]; | ||
| 99 | if (c == '=') { | ||
| 100 | st = VALUE; | ||
| 101 | } else if (!is_nvram_char(c)) { | ||
| 102 | brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", | ||
| 103 | nvp->line, nvp->column); | ||
| 104 | return COMMENT; | ||
| 105 | } | ||
| 106 | |||
| 107 | nvp->column++; | ||
| 108 | nvp->pos++; | ||
| 109 | return st; | ||
| 110 | } | ||
| 111 | |||
| 112 | static enum nvram_parser_state | ||
| 113 | brcmf_nvram_handle_value(struct nvram_parser *nvp) | ||
| 114 | { | ||
| 115 | char c; | ||
| 116 | char *skv; | ||
| 117 | char *ekv; | ||
| 118 | u32 cplen; | ||
| 119 | |||
| 120 | c = nvp->fwnv->data[nvp->pos]; | ||
| 121 | if (!is_nvram_char(c)) { | ||
| 122 | /* key,value pair complete */ | ||
| 123 | ekv = (u8 *)&nvp->fwnv->data[nvp->pos]; | ||
| 124 | skv = (u8 *)&nvp->fwnv->data[nvp->entry]; | ||
| 125 | cplen = ekv - skv; | ||
| 126 | /* copy to output buffer */ | ||
| 127 | memcpy(&nvp->nvram[nvp->nvram_len], skv, cplen); | ||
| 128 | nvp->nvram_len += cplen; | ||
| 129 | nvp->nvram[nvp->nvram_len] = '\0'; | ||
| 130 | nvp->nvram_len++; | ||
| 131 | return IDLE; | ||
| 132 | } | ||
| 133 | nvp->pos++; | ||
| 134 | nvp->column++; | ||
| 135 | return VALUE; | ||
| 136 | } | ||
| 137 | |||
| 138 | static enum nvram_parser_state | ||
| 139 | brcmf_nvram_handle_comment(struct nvram_parser *nvp) | ||
| 140 | { | ||
| 141 | char *eol, *sol; | ||
| 142 | |||
| 143 | sol = (char *)&nvp->fwnv->data[nvp->pos]; | ||
| 144 | eol = strchr(sol, '\n'); | ||
| 145 | if (eol == NULL) | ||
| 146 | return END; | ||
| 147 | |||
| 148 | /* eat all moving to next line */ | ||
| 149 | nvp->line++; | ||
| 150 | nvp->column = 1; | ||
| 151 | nvp->pos += (eol - sol) + 1; | ||
| 152 | return IDLE; | ||
| 153 | } | ||
| 154 | |||
| 155 | static enum nvram_parser_state brcmf_nvram_handle_end(struct nvram_parser *nvp) | ||
| 156 | { | ||
| 157 | /* final state */ | ||
| 158 | return END; | ||
| 159 | } | ||
| 160 | |||
| 161 | static enum nvram_parser_state | ||
| 162 | (*nv_parser_states[])(struct nvram_parser *nvp) = { | ||
| 163 | brcmf_nvram_handle_idle, | ||
| 164 | brcmf_nvram_handle_key, | ||
| 165 | brcmf_nvram_handle_value, | ||
| 166 | brcmf_nvram_handle_comment, | ||
| 167 | brcmf_nvram_handle_end | ||
| 168 | }; | ||
| 169 | |||
| 170 | static int brcmf_init_nvram_parser(struct nvram_parser *nvp, | ||
| 171 | const struct firmware *nv) | ||
| 172 | { | ||
| 173 | memset(nvp, 0, sizeof(*nvp)); | ||
| 174 | nvp->fwnv = nv; | ||
| 175 | /* Alloc for extra 0 byte + roundup by 4 + length field */ | ||
| 176 | nvp->nvram = kzalloc(nv->size + 1 + 3 + sizeof(u32), GFP_KERNEL); | ||
| 177 | if (!nvp->nvram) | ||
| 178 | return -ENOMEM; | ||
| 179 | |||
| 180 | nvp->line = 1; | ||
| 181 | nvp->column = 1; | ||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | |||
| 185 | /* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil | ||
| 24 | * and ending in a NUL. Removes carriage returns, empty lines, comment lines, | 186 | * and ending in a NUL. Removes carriage returns, empty lines, comment lines, |
| 25 | * and converts newlines to NULs. Shortens buffer as needed and pads with NULs. | 187 | * and converts newlines to NULs. Shortens buffer as needed and pads with NULs. |
| 26 | * End of buffer is completed with token identifying length of buffer. | 188 | * End of buffer is completed with token identifying length of buffer. |
| 27 | */ | 189 | */ |
| 28 | void *brcmf_nvram_strip(const struct firmware *nv, u32 *new_length) | 190 | void *brcmf_nvram_strip(const struct firmware *nv, u32 *new_length) |
| 29 | { | 191 | { |
| 30 | u8 *nvram; | 192 | struct nvram_parser nvp; |
| 31 | u32 i; | 193 | u32 pad; |
| 32 | u32 len; | ||
| 33 | u32 column; | ||
| 34 | u8 val; | ||
| 35 | bool comment; | ||
| 36 | u32 token; | 194 | u32 token; |
| 37 | __le32 token_le; | 195 | __le32 token_le; |
| 38 | 196 | ||
| 39 | /* Alloc for extra 0 byte + roundup by 4 + length field */ | 197 | if (brcmf_init_nvram_parser(&nvp, nv) < 0) |
| 40 | nvram = kmalloc(nv->size + 1 + 3 + sizeof(token_le), GFP_KERNEL); | ||
| 41 | if (!nvram) | ||
| 42 | return NULL; | 198 | return NULL; |
| 43 | 199 | ||
| 44 | len = 0; | 200 | while (nvp.pos < nv->size) { |
| 45 | column = 0; | 201 | nvp.state = nv_parser_states[nvp.state](&nvp); |
| 46 | comment = false; | 202 | if (nvp.state == END) |
| 47 | for (i = 0; i < nv->size; i++) { | ||
| 48 | val = nv->data[i]; | ||
| 49 | if (val == 0) | ||
| 50 | break; | 203 | break; |
| 51 | if (val == '\r') | ||
| 52 | continue; | ||
| 53 | if (comment && (val != '\n')) | ||
| 54 | continue; | ||
| 55 | comment = false; | ||
| 56 | if (val == '#') { | ||
| 57 | comment = true; | ||
| 58 | continue; | ||
| 59 | } | ||
| 60 | if (val == '\n') { | ||
| 61 | if (column == 0) | ||
| 62 | continue; | ||
| 63 | nvram[len] = 0; | ||
| 64 | len++; | ||
| 65 | column = 0; | ||
| 66 | continue; | ||
| 67 | } | ||
| 68 | nvram[len] = val; | ||
| 69 | len++; | ||
| 70 | column++; | ||
| 71 | } | 204 | } |
| 72 | column = len; | 205 | pad = nvp.nvram_len; |
| 73 | *new_length = roundup(len + 1, 4); | 206 | *new_length = roundup(nvp.nvram_len + 1, 4); |
| 74 | while (column != *new_length) { | 207 | while (pad != *new_length) { |
| 75 | nvram[column] = 0; | 208 | nvp.nvram[pad] = 0; |
| 76 | column++; | 209 | pad++; |
| 77 | } | 210 | } |
| 78 | 211 | ||
| 79 | token = *new_length / 4; | 212 | token = *new_length / 4; |
| 80 | token = (~token << 16) | (token & 0x0000FFFF); | 213 | token = (~token << 16) | (token & 0x0000FFFF); |
| 81 | token_le = cpu_to_le32(token); | 214 | token_le = cpu_to_le32(token); |
| 82 | 215 | ||
| 83 | memcpy(&nvram[*new_length], &token_le, sizeof(token_le)); | 216 | memcpy(&nvp.nvram[*new_length], &token_le, sizeof(token_le)); |
| 84 | *new_length += sizeof(token_le); | 217 | *new_length += sizeof(token_le); |
| 85 | 218 | ||
| 86 | return nvram; | 219 | return nvp.nvram; |
| 87 | } | 220 | } |
| 88 | 221 | ||
| 89 | void brcmf_nvram_free(void *nvram) | 222 | void brcmf_nvram_free(void *nvram) |
| @@ -91,4 +224,3 @@ void brcmf_nvram_free(void *nvram) | |||
| 91 | kfree(nvram); | 224 | kfree(nvram); |
| 92 | } | 225 | } |
| 93 | 226 | ||
| 94 | |||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 24f65cd53859..3ce0e7cfd027 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
| @@ -1254,6 +1254,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) | |||
| 1254 | bus->chip = bus_pub->devid; | 1254 | bus->chip = bus_pub->devid; |
| 1255 | bus->chiprev = bus_pub->chiprev; | 1255 | bus->chiprev = bus_pub->chiprev; |
| 1256 | bus->proto_type = BRCMF_PROTO_BCDC; | 1256 | bus->proto_type = BRCMF_PROTO_BCDC; |
| 1257 | bus->always_use_fws_queue = true; | ||
| 1257 | 1258 | ||
| 1258 | /* Attach to the common driver interface */ | 1259 | /* Attach to the common driver interface */ |
| 1259 | ret = brcmf_attach(dev); | 1260 | ret = brcmf_attach(dev); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index be1985296bdc..92cb29a2003f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
| @@ -221,9 +221,9 @@ static const struct ieee80211_regdomain brcmf_regdom = { | |||
| 221 | */ | 221 | */ |
| 222 | REG_RULE(2484-10, 2484+10, 20, 6, 20, 0), | 222 | REG_RULE(2484-10, 2484+10, 20, 6, 20, 0), |
| 223 | /* IEEE 802.11a, channel 36..64 */ | 223 | /* IEEE 802.11a, channel 36..64 */ |
| 224 | REG_RULE(5150-10, 5350+10, 40, 6, 20, 0), | 224 | REG_RULE(5150-10, 5350+10, 80, 6, 20, 0), |
| 225 | /* IEEE 802.11a, channel 100..165 */ | 225 | /* IEEE 802.11a, channel 100..165 */ |
| 226 | REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), } | 226 | REG_RULE(5470-10, 5850+10, 80, 6, 20, 0), } |
| 227 | }; | 227 | }; |
| 228 | 228 | ||
| 229 | static const u32 __wl_cipher_suites[] = { | 229 | static const u32 __wl_cipher_suites[] = { |
| @@ -341,6 +341,60 @@ static u8 brcmf_mw_to_qdbm(u16 mw) | |||
| 341 | return qdbm; | 341 | return qdbm; |
| 342 | } | 342 | } |
| 343 | 343 | ||
| 344 | u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, | ||
| 345 | struct cfg80211_chan_def *ch) | ||
| 346 | { | ||
| 347 | struct brcmu_chan ch_inf; | ||
| 348 | s32 primary_offset; | ||
| 349 | |||
| 350 | brcmf_dbg(TRACE, "chandef: control %d center %d width %d\n", | ||
| 351 | ch->chan->center_freq, ch->center_freq1, ch->width); | ||
| 352 | ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq1); | ||
| 353 | primary_offset = ch->center_freq1 - ch->chan->center_freq; | ||
| 354 | switch (ch->width) { | ||
| 355 | case NL80211_CHAN_WIDTH_20: | ||
| 356 | ch_inf.bw = BRCMU_CHAN_BW_20; | ||
| 357 | WARN_ON(primary_offset != 0); | ||
| 358 | break; | ||
| 359 | case NL80211_CHAN_WIDTH_40: | ||
| 360 | ch_inf.bw = BRCMU_CHAN_BW_40; | ||
| 361 | if (primary_offset < 0) | ||
| 362 | ch_inf.sb = BRCMU_CHAN_SB_U; | ||
| 363 | else | ||
| 364 | ch_inf.sb = BRCMU_CHAN_SB_L; | ||
| 365 | break; | ||
| 366 | case NL80211_CHAN_WIDTH_80: | ||
| 367 | ch_inf.bw = BRCMU_CHAN_BW_80; | ||
| 368 | if (primary_offset < 0) { | ||
| 369 | if (primary_offset < -CH_10MHZ_APART) | ||
| 370 | ch_inf.sb = BRCMU_CHAN_SB_UU; | ||
| 371 | else | ||
| 372 | ch_inf.sb = BRCMU_CHAN_SB_UL; | ||
| 373 | } else { | ||
| 374 | if (primary_offset > CH_10MHZ_APART) | ||
| 375 | ch_inf.sb = BRCMU_CHAN_SB_LL; | ||
| 376 | else | ||
| 377 | ch_inf.sb = BRCMU_CHAN_SB_LU; | ||
| 378 | } | ||
| 379 | break; | ||
| 380 | default: | ||
| 381 | WARN_ON_ONCE(1); | ||
| 382 | } | ||
| 383 | switch (ch->chan->band) { | ||
| 384 | case IEEE80211_BAND_2GHZ: | ||
| 385 | ch_inf.band = BRCMU_CHAN_BAND_2G; | ||
| 386 | break; | ||
| 387 | case IEEE80211_BAND_5GHZ: | ||
| 388 | ch_inf.band = BRCMU_CHAN_BAND_5G; | ||
| 389 | break; | ||
| 390 | default: | ||
| 391 | WARN_ON_ONCE(1); | ||
| 392 | } | ||
| 393 | d11inf->encchspec(&ch_inf); | ||
| 394 | |||
| 395 | return ch_inf.chspec; | ||
| 396 | } | ||
| 397 | |||
| 344 | u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, | 398 | u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, |
| 345 | struct ieee80211_channel *ch) | 399 | struct ieee80211_channel *ch) |
| 346 | { | 400 | { |
| @@ -1236,8 +1290,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, | |||
| 1236 | params->chandef.chan->center_freq); | 1290 | params->chandef.chan->center_freq); |
| 1237 | if (params->channel_fixed) { | 1291 | if (params->channel_fixed) { |
| 1238 | /* adding chanspec */ | 1292 | /* adding chanspec */ |
| 1239 | chanspec = channel_to_chanspec(&cfg->d11inf, | 1293 | chanspec = chandef_to_chanspec(&cfg->d11inf, |
| 1240 | params->chandef.chan); | 1294 | ¶ms->chandef); |
| 1241 | join_params.params_le.chanspec_list[0] = | 1295 | join_params.params_le.chanspec_list[0] = |
| 1242 | cpu_to_le16(chanspec); | 1296 | cpu_to_le16(chanspec); |
| 1243 | join_params.params_le.chanspec_num = cpu_to_le32(1); | 1297 | join_params.params_le.chanspec_num = cpu_to_le32(1); |
| @@ -2182,7 +2236,7 @@ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, | |||
| 2182 | 2236 | ||
| 2183 | static s32 | 2237 | static s32 |
| 2184 | brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | 2238 | brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, |
| 2185 | u8 *mac, struct station_info *sinfo) | 2239 | const u8 *mac, struct station_info *sinfo) |
| 2186 | { | 2240 | { |
| 2187 | struct brcmf_if *ifp = netdev_priv(ndev); | 2241 | struct brcmf_if *ifp = netdev_priv(ndev); |
| 2188 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | 2242 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; |
| @@ -3734,23 +3788,6 @@ brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif, | |||
| 3734 | } | 3788 | } |
| 3735 | 3789 | ||
| 3736 | static s32 | 3790 | static s32 |
| 3737 | brcmf_cfg80211_set_channel(struct brcmf_cfg80211_info *cfg, | ||
| 3738 | struct brcmf_if *ifp, | ||
| 3739 | struct ieee80211_channel *channel) | ||
| 3740 | { | ||
| 3741 | u16 chanspec; | ||
| 3742 | s32 err; | ||
| 3743 | |||
| 3744 | brcmf_dbg(TRACE, "band=%d, center_freq=%d\n", channel->band, | ||
| 3745 | channel->center_freq); | ||
| 3746 | |||
| 3747 | chanspec = channel_to_chanspec(&cfg->d11inf, channel); | ||
| 3748 | err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec); | ||
| 3749 | |||
| 3750 | return err; | ||
| 3751 | } | ||
| 3752 | |||
| 3753 | static s32 | ||
| 3754 | brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | 3791 | brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, |
| 3755 | struct cfg80211_ap_settings *settings) | 3792 | struct cfg80211_ap_settings *settings) |
| 3756 | { | 3793 | { |
| @@ -3765,11 +3802,12 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
| 3765 | struct brcmf_join_params join_params; | 3802 | struct brcmf_join_params join_params; |
| 3766 | enum nl80211_iftype dev_role; | 3803 | enum nl80211_iftype dev_role; |
| 3767 | struct brcmf_fil_bss_enable_le bss_enable; | 3804 | struct brcmf_fil_bss_enable_le bss_enable; |
| 3805 | u16 chanspec; | ||
| 3768 | 3806 | ||
| 3769 | brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n", | 3807 | brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n", |
| 3770 | cfg80211_get_chandef_type(&settings->chandef), | 3808 | settings->chandef.chan->hw_value, |
| 3771 | settings->beacon_interval, | 3809 | settings->chandef.center_freq1, settings->chandef.width, |
| 3772 | settings->dtim_period); | 3810 | settings->beacon_interval, settings->dtim_period); |
| 3773 | brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n", | 3811 | brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n", |
| 3774 | settings->ssid, settings->ssid_len, settings->auth_type, | 3812 | settings->ssid, settings->ssid_len, settings->auth_type, |
| 3775 | settings->inactivity_timeout); | 3813 | settings->inactivity_timeout); |
| @@ -3826,9 +3864,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
| 3826 | 3864 | ||
| 3827 | brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon); | 3865 | brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon); |
| 3828 | 3866 | ||
| 3829 | err = brcmf_cfg80211_set_channel(cfg, ifp, settings->chandef.chan); | 3867 | chanspec = chandef_to_chanspec(&cfg->d11inf, &settings->chandef); |
| 3868 | err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec); | ||
| 3830 | if (err < 0) { | 3869 | if (err < 0) { |
| 3831 | brcmf_err("Set Channel failed, %d\n", err); | 3870 | brcmf_err("Set Channel failed: chspec=%d, %d\n", chanspec, err); |
| 3832 | goto exit; | 3871 | goto exit; |
| 3833 | } | 3872 | } |
| 3834 | 3873 | ||
| @@ -3975,7 +4014,7 @@ brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev, | |||
| 3975 | 4014 | ||
| 3976 | static int | 4015 | static int |
| 3977 | brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, | 4016 | brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, |
| 3978 | u8 *mac) | 4017 | const u8 *mac) |
| 3979 | { | 4018 | { |
| 3980 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 4019 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 3981 | struct brcmf_scb_val_le scbval; | 4020 | struct brcmf_scb_val_le scbval; |
| @@ -4203,7 +4242,7 @@ static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper) | |||
| 4203 | } | 4242 | } |
| 4204 | 4243 | ||
| 4205 | static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy, | 4244 | static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy, |
| 4206 | struct net_device *ndev, u8 *peer, | 4245 | struct net_device *ndev, const u8 *peer, |
| 4207 | enum nl80211_tdls_operation oper) | 4246 | enum nl80211_tdls_operation oper) |
| 4208 | { | 4247 | { |
| 4209 | struct brcmf_if *ifp; | 4248 | struct brcmf_if *ifp; |
| @@ -4364,6 +4403,8 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | |||
| 4364 | WIPHY_FLAG_OFFCHAN_TX | | 4403 | WIPHY_FLAG_OFFCHAN_TX | |
| 4365 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | 4404 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
| 4366 | WIPHY_FLAG_SUPPORTS_TDLS; | 4405 | WIPHY_FLAG_SUPPORTS_TDLS; |
| 4406 | if (!brcmf_roamoff) | ||
| 4407 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; | ||
| 4367 | wiphy->mgmt_stypes = brcmf_txrx_stypes; | 4408 | wiphy->mgmt_stypes = brcmf_txrx_stypes; |
| 4368 | wiphy->max_remain_on_channel_duration = 5000; | 4409 | wiphy->max_remain_on_channel_duration = 5000; |
| 4369 | brcmf_wiphy_pno_params(wiphy); | 4410 | brcmf_wiphy_pno_params(wiphy); |
| @@ -4685,7 +4726,6 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, | |||
| 4685 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | 4726 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; |
| 4686 | struct ieee80211_channel *chan; | 4727 | struct ieee80211_channel *chan; |
| 4687 | s32 err = 0; | 4728 | s32 err = 0; |
| 4688 | u16 reason; | ||
| 4689 | 4729 | ||
| 4690 | if (brcmf_is_apmode(ifp->vif)) { | 4730 | if (brcmf_is_apmode(ifp->vif)) { |
| 4691 | err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); | 4731 | err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); |
| @@ -4706,16 +4746,6 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, | |||
| 4706 | brcmf_dbg(CONN, "Linkdown\n"); | 4746 | brcmf_dbg(CONN, "Linkdown\n"); |
| 4707 | if (!brcmf_is_ibssmode(ifp->vif)) { | 4747 | if (!brcmf_is_ibssmode(ifp->vif)) { |
| 4708 | brcmf_bss_connect_done(cfg, ndev, e, false); | 4748 | brcmf_bss_connect_done(cfg, ndev, e, false); |
| 4709 | if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, | ||
| 4710 | &ifp->vif->sme_state)) { | ||
| 4711 | reason = 0; | ||
| 4712 | if (((e->event_code == BRCMF_E_DEAUTH_IND) || | ||
| 4713 | (e->event_code == BRCMF_E_DISASSOC_IND)) && | ||
| 4714 | (e->reason != WLAN_REASON_UNSPECIFIED)) | ||
| 4715 | reason = e->reason; | ||
| 4716 | cfg80211_disconnected(ndev, reason, NULL, 0, | ||
| 4717 | GFP_KERNEL); | ||
| 4718 | } | ||
| 4719 | } | 4749 | } |
| 4720 | brcmf_link_down(ifp->vif); | 4750 | brcmf_link_down(ifp->vif); |
| 4721 | brcmf_init_prof(ndev_to_prof(ndev)); | 4751 | brcmf_init_prof(ndev_to_prof(ndev)); |
| @@ -5215,6 +5245,9 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, | |||
| 5215 | if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) && | 5245 | if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) && |
| 5216 | ch.bw == BRCMU_CHAN_BW_40) | 5246 | ch.bw == BRCMU_CHAN_BW_40) |
| 5217 | continue; | 5247 | continue; |
| 5248 | if (!(bw_cap[band] & WLC_BW_80MHZ_BIT) && | ||
| 5249 | ch.bw == BRCMU_CHAN_BW_80) | ||
| 5250 | continue; | ||
| 5218 | update = false; | 5251 | update = false; |
| 5219 | for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { | 5252 | for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { |
| 5220 | if (band_chan_arr[j].hw_value == ch.chnum) { | 5253 | if (band_chan_arr[j].hw_value == ch.chnum) { |
| @@ -5231,10 +5264,13 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, | |||
| 5231 | ieee80211_channel_to_frequency(ch.chnum, band); | 5264 | ieee80211_channel_to_frequency(ch.chnum, band); |
| 5232 | band_chan_arr[index].hw_value = ch.chnum; | 5265 | band_chan_arr[index].hw_value = ch.chnum; |
| 5233 | 5266 | ||
| 5234 | if (ch.bw == BRCMU_CHAN_BW_40) { | 5267 | /* assuming the chanspecs order is HT20, |
| 5235 | /* assuming the order is HT20, HT40 Upper, | 5268 | * HT40 upper, HT40 lower, and VHT80. |
| 5236 | * HT40 lower from chanspecs | 5269 | */ |
| 5237 | */ | 5270 | if (ch.bw == BRCMU_CHAN_BW_80) { |
| 5271 | band_chan_arr[index].flags &= | ||
| 5272 | ~IEEE80211_CHAN_NO_80MHZ; | ||
| 5273 | } else if (ch.bw == BRCMU_CHAN_BW_40) { | ||
| 5238 | ht40_flag = band_chan_arr[index].flags & | 5274 | ht40_flag = band_chan_arr[index].flags & |
| 5239 | IEEE80211_CHAN_NO_HT40; | 5275 | IEEE80211_CHAN_NO_HT40; |
| 5240 | if (ch.sb == BRCMU_CHAN_SB_U) { | 5276 | if (ch.sb == BRCMU_CHAN_SB_U) { |
| @@ -5255,8 +5291,13 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, | |||
| 5255 | IEEE80211_CHAN_NO_HT40MINUS; | 5291 | IEEE80211_CHAN_NO_HT40MINUS; |
| 5256 | } | 5292 | } |
| 5257 | } else { | 5293 | } else { |
| 5294 | /* disable other bandwidths for now as mentioned | ||
| 5295 | * order assure they are enabled for subsequent | ||
| 5296 | * chanspecs. | ||
| 5297 | */ | ||
| 5258 | band_chan_arr[index].flags = | 5298 | band_chan_arr[index].flags = |
| 5259 | IEEE80211_CHAN_NO_HT40; | 5299 | IEEE80211_CHAN_NO_HT40 | |
| 5300 | IEEE80211_CHAN_NO_80MHZ; | ||
| 5260 | ch.bw = BRCMU_CHAN_BW_20; | 5301 | ch.bw = BRCMU_CHAN_BW_20; |
| 5261 | cfg->d11inf.encchspec(&ch); | 5302 | cfg->d11inf.encchspec(&ch); |
| 5262 | channel = ch.chspec; | 5303 | channel = ch.chspec; |
| @@ -5323,13 +5364,63 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) | |||
| 5323 | } | 5364 | } |
| 5324 | } | 5365 | } |
| 5325 | 5366 | ||
| 5367 | static void brcmf_update_ht_cap(struct ieee80211_supported_band *band, | ||
| 5368 | u32 bw_cap[2], u32 nchain) | ||
| 5369 | { | ||
| 5370 | band->ht_cap.ht_supported = true; | ||
| 5371 | if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) { | ||
| 5372 | band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; | ||
| 5373 | band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
| 5374 | } | ||
| 5375 | band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; | ||
| 5376 | band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; | ||
| 5377 | band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
| 5378 | band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; | ||
| 5379 | memset(band->ht_cap.mcs.rx_mask, 0xff, nchain); | ||
| 5380 | band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
| 5381 | } | ||
| 5382 | |||
| 5383 | static __le16 brcmf_get_mcs_map(u32 nchain, enum ieee80211_vht_mcs_support supp) | ||
| 5384 | { | ||
| 5385 | u16 mcs_map; | ||
| 5386 | int i; | ||
| 5387 | |||
| 5388 | for (i = 0, mcs_map = 0xFFFF; i < nchain; i++) | ||
| 5389 | mcs_map = (mcs_map << 2) | supp; | ||
| 5390 | |||
| 5391 | return cpu_to_le16(mcs_map); | ||
| 5392 | } | ||
| 5393 | |||
| 5394 | static void brcmf_update_vht_cap(struct ieee80211_supported_band *band, | ||
| 5395 | u32 bw_cap[2], u32 nchain) | ||
| 5396 | { | ||
| 5397 | __le16 mcs_map; | ||
| 5398 | |||
| 5399 | /* not allowed in 2.4G band */ | ||
| 5400 | if (band->band == IEEE80211_BAND_2GHZ) | ||
| 5401 | return; | ||
| 5402 | |||
| 5403 | band->vht_cap.vht_supported = true; | ||
| 5404 | /* 80MHz is mandatory */ | ||
| 5405 | band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; | ||
| 5406 | if (bw_cap[band->band] & WLC_BW_160MHZ_BIT) { | ||
| 5407 | band->vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | ||
| 5408 | band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160; | ||
| 5409 | } | ||
| 5410 | /* all support 256-QAM */ | ||
| 5411 | mcs_map = brcmf_get_mcs_map(nchain, IEEE80211_VHT_MCS_SUPPORT_0_9); | ||
| 5412 | band->vht_cap.vht_mcs.rx_mcs_map = mcs_map; | ||
| 5413 | band->vht_cap.vht_mcs.tx_mcs_map = mcs_map; | ||
| 5414 | } | ||
| 5415 | |||
| 5326 | static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | 5416 | static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) |
| 5327 | { | 5417 | { |
| 5328 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | 5418 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
| 5329 | struct wiphy *wiphy; | 5419 | struct wiphy *wiphy; |
| 5330 | s32 phy_list; | 5420 | s32 phy_list; |
| 5331 | u32 band_list[3]; | 5421 | u32 band_list[3]; |
| 5332 | u32 nmode; | 5422 | u32 nmode = 0; |
| 5423 | u32 vhtmode = 0; | ||
| 5333 | u32 bw_cap[2] = { 0, 0 }; | 5424 | u32 bw_cap[2] = { 0, 0 }; |
| 5334 | u32 rxchain; | 5425 | u32 rxchain; |
| 5335 | u32 nchain; | 5426 | u32 nchain; |
| @@ -5360,14 +5451,16 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | |||
| 5360 | brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n", | 5451 | brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n", |
| 5361 | band_list[0], band_list[1], band_list[2]); | 5452 | band_list[0], band_list[1], band_list[2]); |
| 5362 | 5453 | ||
| 5454 | (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode); | ||
| 5363 | err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); | 5455 | err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); |
| 5364 | if (err) { | 5456 | if (err) { |
| 5365 | brcmf_err("nmode error (%d)\n", err); | 5457 | brcmf_err("nmode error (%d)\n", err); |
| 5366 | } else { | 5458 | } else { |
| 5367 | brcmf_get_bwcap(ifp, bw_cap); | 5459 | brcmf_get_bwcap(ifp, bw_cap); |
| 5368 | } | 5460 | } |
| 5369 | brcmf_dbg(INFO, "nmode=%d, bw_cap=(%d, %d)\n", nmode, | 5461 | brcmf_dbg(INFO, "nmode=%d, vhtmode=%d, bw_cap=(%d, %d)\n", |
| 5370 | bw_cap[IEEE80211_BAND_2GHZ], bw_cap[IEEE80211_BAND_5GHZ]); | 5462 | nmode, vhtmode, bw_cap[IEEE80211_BAND_2GHZ], |
| 5463 | bw_cap[IEEE80211_BAND_5GHZ]); | ||
| 5371 | 5464 | ||
| 5372 | err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain); | 5465 | err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain); |
| 5373 | if (err) { | 5466 | if (err) { |
| @@ -5398,17 +5491,10 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | |||
| 5398 | else | 5491 | else |
| 5399 | continue; | 5492 | continue; |
| 5400 | 5493 | ||
| 5401 | if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) { | 5494 | if (nmode) |
| 5402 | band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; | 5495 | brcmf_update_ht_cap(band, bw_cap, nchain); |
| 5403 | band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 5496 | if (vhtmode) |
| 5404 | } | 5497 | brcmf_update_vht_cap(band, bw_cap, nchain); |
| 5405 | band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; | ||
| 5406 | band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; | ||
| 5407 | band->ht_cap.ht_supported = true; | ||
| 5408 | band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
| 5409 | band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; | ||
| 5410 | memset(band->ht_cap.mcs.rx_mask, 0xff, nchain); | ||
| 5411 | band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
| 5412 | bands[band->band] = band; | 5498 | bands[band->band] = band; |
| 5413 | } | 5499 | } |
| 5414 | 5500 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 9417cb5a2553..af8ba64ace39 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
| @@ -4870,14 +4870,11 @@ static void brcms_c_detach_module(struct brcms_c_info *wlc) | |||
| 4870 | /* | 4870 | /* |
| 4871 | * low level detach | 4871 | * low level detach |
| 4872 | */ | 4872 | */ |
| 4873 | static int brcms_b_detach(struct brcms_c_info *wlc) | 4873 | static void brcms_b_detach(struct brcms_c_info *wlc) |
| 4874 | { | 4874 | { |
| 4875 | uint i; | 4875 | uint i; |
| 4876 | struct brcms_hw_band *band; | 4876 | struct brcms_hw_band *band; |
| 4877 | struct brcms_hardware *wlc_hw = wlc->hw; | 4877 | struct brcms_hardware *wlc_hw = wlc->hw; |
| 4878 | int callbacks; | ||
| 4879 | |||
| 4880 | callbacks = 0; | ||
| 4881 | 4878 | ||
| 4882 | brcms_b_detach_dmapio(wlc_hw); | 4879 | brcms_b_detach_dmapio(wlc_hw); |
| 4883 | 4880 | ||
| @@ -4900,9 +4897,6 @@ static int brcms_b_detach(struct brcms_c_info *wlc) | |||
| 4900 | ai_detach(wlc_hw->sih); | 4897 | ai_detach(wlc_hw->sih); |
| 4901 | wlc_hw->sih = NULL; | 4898 | wlc_hw->sih = NULL; |
| 4902 | } | 4899 | } |
| 4903 | |||
| 4904 | return callbacks; | ||
| 4905 | |||
| 4906 | } | 4900 | } |
| 4907 | 4901 | ||
| 4908 | /* | 4902 | /* |
| @@ -4917,14 +4911,15 @@ static int brcms_b_detach(struct brcms_c_info *wlc) | |||
| 4917 | */ | 4911 | */ |
| 4918 | uint brcms_c_detach(struct brcms_c_info *wlc) | 4912 | uint brcms_c_detach(struct brcms_c_info *wlc) |
| 4919 | { | 4913 | { |
| 4920 | uint callbacks = 0; | 4914 | uint callbacks; |
| 4921 | 4915 | ||
| 4922 | if (wlc == NULL) | 4916 | if (wlc == NULL) |
| 4923 | return 0; | 4917 | return 0; |
| 4924 | 4918 | ||
| 4925 | callbacks += brcms_b_detach(wlc); | 4919 | brcms_b_detach(wlc); |
| 4926 | 4920 | ||
| 4927 | /* delete software timers */ | 4921 | /* delete software timers */ |
| 4922 | callbacks = 0; | ||
| 4928 | if (!brcms_c_radio_monitor_stop(wlc)) | 4923 | if (!brcms_c_radio_monitor_stop(wlc)) |
| 4929 | callbacks++; | 4924 | callbacks++; |
| 4930 | 4925 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmutil/d11.c b/drivers/net/wireless/brcm80211/brcmutil/d11.c index 30e54e2c6c9b..6cbc33d0fc19 100644 --- a/drivers/net/wireless/brcm80211/brcmutil/d11.c +++ b/drivers/net/wireless/brcm80211/brcmutil/d11.c | |||
| @@ -21,43 +21,81 @@ | |||
| 21 | #include <brcmu_wifi.h> | 21 | #include <brcmu_wifi.h> |
| 22 | #include <brcmu_d11.h> | 22 | #include <brcmu_d11.h> |
| 23 | 23 | ||
| 24 | static void brcmu_d11n_encchspec(struct brcmu_chan *ch) | 24 | static u16 d11n_sb(enum brcmu_chan_sb sb) |
| 25 | { | 25 | { |
| 26 | ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK; | 26 | switch (sb) { |
| 27 | case BRCMU_CHAN_SB_NONE: | ||
| 28 | return BRCMU_CHSPEC_D11N_SB_N; | ||
| 29 | case BRCMU_CHAN_SB_L: | ||
| 30 | return BRCMU_CHSPEC_D11N_SB_L; | ||
| 31 | case BRCMU_CHAN_SB_U: | ||
| 32 | return BRCMU_CHSPEC_D11N_SB_U; | ||
| 33 | default: | ||
| 34 | WARN_ON(1); | ||
| 35 | } | ||
| 36 | return 0; | ||
| 37 | } | ||
| 27 | 38 | ||
| 28 | switch (ch->bw) { | 39 | static u16 d11n_bw(enum brcmu_chan_bw bw) |
| 40 | { | ||
| 41 | switch (bw) { | ||
| 29 | case BRCMU_CHAN_BW_20: | 42 | case BRCMU_CHAN_BW_20: |
| 30 | ch->chspec |= BRCMU_CHSPEC_D11N_BW_20 | BRCMU_CHSPEC_D11N_SB_N; | 43 | return BRCMU_CHSPEC_D11N_BW_20; |
| 31 | break; | ||
| 32 | case BRCMU_CHAN_BW_40: | 44 | case BRCMU_CHAN_BW_40: |
| 45 | return BRCMU_CHSPEC_D11N_BW_40; | ||
| 33 | default: | 46 | default: |
| 34 | WARN_ON_ONCE(1); | 47 | WARN_ON(1); |
| 35 | break; | ||
| 36 | } | 48 | } |
| 49 | return 0; | ||
| 50 | } | ||
| 37 | 51 | ||
| 52 | static void brcmu_d11n_encchspec(struct brcmu_chan *ch) | ||
| 53 | { | ||
| 54 | if (ch->bw == BRCMU_CHAN_BW_20) | ||
| 55 | ch->sb = BRCMU_CHAN_SB_NONE; | ||
| 56 | |||
| 57 | brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK, | ||
| 58 | BRCMU_CHSPEC_CH_SHIFT, ch->chnum); | ||
| 59 | brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_SB_MASK, | ||
| 60 | 0, d11n_sb(ch->sb)); | ||
| 61 | brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_BW_MASK, | ||
| 62 | 0, d11n_bw(ch->bw)); | ||
| 63 | |||
| 64 | ch->chspec &= ~BRCMU_CHSPEC_D11N_BND_MASK; | ||
| 38 | if (ch->chnum <= CH_MAX_2G_CHANNEL) | 65 | if (ch->chnum <= CH_MAX_2G_CHANNEL) |
| 39 | ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G; | 66 | ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G; |
| 40 | else | 67 | else |
| 41 | ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G; | 68 | ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G; |
| 42 | } | 69 | } |
| 43 | 70 | ||
| 44 | static void brcmu_d11ac_encchspec(struct brcmu_chan *ch) | 71 | static u16 d11ac_bw(enum brcmu_chan_bw bw) |
| 45 | { | 72 | { |
| 46 | ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK; | 73 | switch (bw) { |
| 47 | |||
| 48 | switch (ch->bw) { | ||
| 49 | case BRCMU_CHAN_BW_20: | 74 | case BRCMU_CHAN_BW_20: |
| 50 | ch->chspec |= BRCMU_CHSPEC_D11AC_BW_20; | 75 | return BRCMU_CHSPEC_D11AC_BW_20; |
| 51 | break; | ||
| 52 | case BRCMU_CHAN_BW_40: | 76 | case BRCMU_CHAN_BW_40: |
| 77 | return BRCMU_CHSPEC_D11AC_BW_40; | ||
| 53 | case BRCMU_CHAN_BW_80: | 78 | case BRCMU_CHAN_BW_80: |
| 54 | case BRCMU_CHAN_BW_80P80: | 79 | return BRCMU_CHSPEC_D11AC_BW_80; |
| 55 | case BRCMU_CHAN_BW_160: | ||
| 56 | default: | 80 | default: |
| 57 | WARN_ON_ONCE(1); | 81 | WARN_ON(1); |
| 58 | break; | ||
| 59 | } | 82 | } |
| 83 | return 0; | ||
| 84 | } | ||
| 60 | 85 | ||
| 86 | static void brcmu_d11ac_encchspec(struct brcmu_chan *ch) | ||
| 87 | { | ||
| 88 | if (ch->bw == BRCMU_CHAN_BW_20 || ch->sb == BRCMU_CHAN_SB_NONE) | ||
| 89 | ch->sb = BRCMU_CHAN_SB_L; | ||
| 90 | |||
| 91 | brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK, | ||
| 92 | BRCMU_CHSPEC_CH_SHIFT, ch->chnum); | ||
| 93 | brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK, | ||
| 94 | BRCMU_CHSPEC_D11AC_SB_SHIFT, ch->sb); | ||
| 95 | brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_BW_MASK, | ||
| 96 | 0, d11ac_bw(ch->bw)); | ||
| 97 | |||
| 98 | ch->chspec &= ~BRCMU_CHSPEC_D11AC_BND_MASK; | ||
| 61 | if (ch->chnum <= CH_MAX_2G_CHANNEL) | 99 | if (ch->chnum <= CH_MAX_2G_CHANNEL) |
| 62 | ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G; | 100 | ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G; |
| 63 | else | 101 | else |
| @@ -73,6 +111,7 @@ static void brcmu_d11n_decchspec(struct brcmu_chan *ch) | |||
| 73 | switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) { | 111 | switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) { |
| 74 | case BRCMU_CHSPEC_D11N_BW_20: | 112 | case BRCMU_CHSPEC_D11N_BW_20: |
| 75 | ch->bw = BRCMU_CHAN_BW_20; | 113 | ch->bw = BRCMU_CHAN_BW_20; |
| 114 | ch->sb = BRCMU_CHAN_SB_NONE; | ||
| 76 | break; | 115 | break; |
| 77 | case BRCMU_CHSPEC_D11N_BW_40: | 116 | case BRCMU_CHSPEC_D11N_BW_40: |
| 78 | ch->bw = BRCMU_CHAN_BW_40; | 117 | ch->bw = BRCMU_CHAN_BW_40; |
| @@ -112,6 +151,7 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch) | |||
| 112 | switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) { | 151 | switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) { |
| 113 | case BRCMU_CHSPEC_D11AC_BW_20: | 152 | case BRCMU_CHSPEC_D11AC_BW_20: |
| 114 | ch->bw = BRCMU_CHAN_BW_20; | 153 | ch->bw = BRCMU_CHAN_BW_20; |
| 154 | ch->sb = BRCMU_CHAN_SB_NONE; | ||
| 115 | break; | 155 | break; |
| 116 | case BRCMU_CHSPEC_D11AC_BW_40: | 156 | case BRCMU_CHSPEC_D11AC_BW_40: |
| 117 | ch->bw = BRCMU_CHAN_BW_40; | 157 | ch->bw = BRCMU_CHAN_BW_40; |
| @@ -128,6 +168,25 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch) | |||
| 128 | break; | 168 | break; |
| 129 | case BRCMU_CHSPEC_D11AC_BW_80: | 169 | case BRCMU_CHSPEC_D11AC_BW_80: |
| 130 | ch->bw = BRCMU_CHAN_BW_80; | 170 | ch->bw = BRCMU_CHAN_BW_80; |
| 171 | ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK, | ||
| 172 | BRCMU_CHSPEC_D11AC_SB_SHIFT); | ||
| 173 | switch (ch->sb) { | ||
| 174 | case BRCMU_CHAN_SB_LL: | ||
| 175 | ch->chnum -= CH_30MHZ_APART; | ||
| 176 | break; | ||
| 177 | case BRCMU_CHAN_SB_LU: | ||
| 178 | ch->chnum -= CH_10MHZ_APART; | ||
| 179 | break; | ||
| 180 | case BRCMU_CHAN_SB_UL: | ||
| 181 | ch->chnum += CH_10MHZ_APART; | ||
| 182 | break; | ||
| 183 | case BRCMU_CHAN_SB_UU: | ||
| 184 | ch->chnum += CH_30MHZ_APART; | ||
| 185 | break; | ||
| 186 | default: | ||
| 187 | WARN_ON_ONCE(1); | ||
| 188 | break; | ||
| 189 | } | ||
| 131 | break; | 190 | break; |
| 132 | case BRCMU_CHSPEC_D11AC_BW_8080: | 191 | case BRCMU_CHSPEC_D11AC_BW_8080: |
| 133 | case BRCMU_CHSPEC_D11AC_BW_160: | 192 | case BRCMU_CHSPEC_D11AC_BW_160: |
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_d11.h b/drivers/net/wireless/brcm80211/include/brcmu_d11.h index 8660a2cba098..f9745ea8b3e0 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_d11.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_d11.h | |||
| @@ -108,13 +108,7 @@ enum brcmu_chan_bw { | |||
| 108 | }; | 108 | }; |
| 109 | 109 | ||
| 110 | enum brcmu_chan_sb { | 110 | enum brcmu_chan_sb { |
| 111 | BRCMU_CHAN_SB_NONE = 0, | 111 | BRCMU_CHAN_SB_NONE = -1, |
| 112 | BRCMU_CHAN_SB_L, | ||
| 113 | BRCMU_CHAN_SB_U, | ||
| 114 | BRCMU_CHAN_SB_LL, | ||
| 115 | BRCMU_CHAN_SB_LU, | ||
| 116 | BRCMU_CHAN_SB_UL, | ||
| 117 | BRCMU_CHAN_SB_UU, | ||
| 118 | BRCMU_CHAN_SB_LLL, | 112 | BRCMU_CHAN_SB_LLL, |
| 119 | BRCMU_CHAN_SB_LLU, | 113 | BRCMU_CHAN_SB_LLU, |
| 120 | BRCMU_CHAN_SB_LUL, | 114 | BRCMU_CHAN_SB_LUL, |
| @@ -123,6 +117,12 @@ enum brcmu_chan_sb { | |||
| 123 | BRCMU_CHAN_SB_ULU, | 117 | BRCMU_CHAN_SB_ULU, |
| 124 | BRCMU_CHAN_SB_UUL, | 118 | BRCMU_CHAN_SB_UUL, |
| 125 | BRCMU_CHAN_SB_UUU, | 119 | BRCMU_CHAN_SB_UUU, |
| 120 | BRCMU_CHAN_SB_L = BRCMU_CHAN_SB_LLL, | ||
| 121 | BRCMU_CHAN_SB_U = BRCMU_CHAN_SB_LLU, | ||
| 122 | BRCMU_CHAN_SB_LL = BRCMU_CHAN_SB_LLL, | ||
| 123 | BRCMU_CHAN_SB_LU = BRCMU_CHAN_SB_LLU, | ||
| 124 | BRCMU_CHAN_SB_UL = BRCMU_CHAN_SB_LUL, | ||
| 125 | BRCMU_CHAN_SB_UU = BRCMU_CHAN_SB_LUU, | ||
| 126 | }; | 126 | }; |
| 127 | 127 | ||
| 128 | struct brcmu_chan { | 128 | struct brcmu_chan { |
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h index 74419d4bd123..76b5d3a86294 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #define CH_UPPER_SB 0x01 | 29 | #define CH_UPPER_SB 0x01 |
| 30 | #define CH_LOWER_SB 0x02 | 30 | #define CH_LOWER_SB 0x02 |
| 31 | #define CH_EWA_VALID 0x04 | 31 | #define CH_EWA_VALID 0x04 |
| 32 | #define CH_30MHZ_APART 6 | ||
| 32 | #define CH_20MHZ_APART 4 | 33 | #define CH_20MHZ_APART 4 |
| 33 | #define CH_10MHZ_APART 2 | 34 | #define CH_10MHZ_APART 2 |
| 34 | #define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ | 35 | #define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 74b3b4de7bb7..7fd50428b934 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
| @@ -2,10 +2,6 @@ config IWLWIFI | |||
| 2 | tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) " | 2 | tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) " |
| 3 | depends on PCI && MAC80211 && HAS_IOMEM | 3 | depends on PCI && MAC80211 && HAS_IOMEM |
| 4 | select FW_LOADER | 4 | select FW_LOADER |
| 5 | select NEW_LEDS | ||
| 6 | select LEDS_CLASS | ||
| 7 | select LEDS_TRIGGERS | ||
| 8 | select MAC80211_LEDS | ||
| 9 | ---help--- | 5 | ---help--- |
| 10 | Select to build the driver supporting the: | 6 | Select to build the driver supporting the: |
| 11 | 7 | ||
| @@ -43,6 +39,14 @@ config IWLWIFI | |||
| 43 | say M here and read <file:Documentation/kbuild/modules.txt>. The | 39 | say M here and read <file:Documentation/kbuild/modules.txt>. The |
| 44 | module will be called iwlwifi. | 40 | module will be called iwlwifi. |
| 45 | 41 | ||
| 42 | config IWLWIFI_LEDS | ||
| 43 | bool | ||
| 44 | depends on IWLWIFI | ||
| 45 | depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI | ||
| 46 | select LEDS_TRIGGERS | ||
| 47 | select MAC80211_LEDS | ||
| 48 | default y | ||
| 49 | |||
| 46 | config IWLDVM | 50 | config IWLDVM |
| 47 | tristate "Intel Wireless WiFi DVM Firmware support" | 51 | tristate "Intel Wireless WiFi DVM Firmware support" |
| 48 | depends on IWLWIFI | 52 | depends on IWLWIFI |
| @@ -124,7 +128,6 @@ config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE | |||
| 124 | Enable use of experimental ucode for testing and debugging. | 128 | Enable use of experimental ucode for testing and debugging. |
| 125 | 129 | ||
| 126 | config IWLWIFI_DEVICE_TRACING | 130 | config IWLWIFI_DEVICE_TRACING |
| 127 | |||
| 128 | bool "iwlwifi device access tracing" | 131 | bool "iwlwifi device access tracing" |
| 129 | depends on IWLWIFI | 132 | depends on IWLWIFI |
| 130 | depends on EVENT_TRACING | 133 | depends on EVENT_TRACING |
diff --git a/drivers/net/wireless/iwlwifi/dvm/Makefile b/drivers/net/wireless/iwlwifi/dvm/Makefile index dce7ab2e0c4b..4d19685f31c3 100644 --- a/drivers/net/wireless/iwlwifi/dvm/Makefile +++ b/drivers/net/wireless/iwlwifi/dvm/Makefile | |||
| @@ -4,9 +4,10 @@ iwldvm-objs += main.o rs.o mac80211.o ucode.o tx.o | |||
| 4 | iwldvm-objs += lib.o calib.o tt.o sta.o rx.o | 4 | iwldvm-objs += lib.o calib.o tt.o sta.o rx.o |
| 5 | 5 | ||
| 6 | iwldvm-objs += power.o | 6 | iwldvm-objs += power.o |
| 7 | iwldvm-objs += scan.o led.o | 7 | iwldvm-objs += scan.o |
| 8 | iwldvm-objs += rxon.o devices.o | 8 | iwldvm-objs += rxon.o devices.o |
| 9 | 9 | ||
| 10 | iwldvm-$(CONFIG_IWLWIFI_LEDS) += led.o | ||
| 10 | iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o | 11 | iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o |
| 11 | 12 | ||
| 12 | ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ | 13 | ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ |
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c index be1086c87157..20e6aa910700 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.c +++ b/drivers/net/wireless/iwlwifi/dvm/calib.c | |||
| @@ -94,7 +94,6 @@ int iwl_send_calib_results(struct iwl_priv *priv) | |||
| 94 | { | 94 | { |
| 95 | struct iwl_host_cmd hcmd = { | 95 | struct iwl_host_cmd hcmd = { |
| 96 | .id = REPLY_PHY_CALIBRATION_CMD, | 96 | .id = REPLY_PHY_CALIBRATION_CMD, |
| 97 | .flags = CMD_SYNC, | ||
| 98 | }; | 97 | }; |
| 99 | struct iwl_calib_result *res; | 98 | struct iwl_calib_result *res; |
| 100 | 99 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index d2fe2596d54e..0ffb6ff1a255 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c | |||
| @@ -1481,7 +1481,7 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, | |||
| 1481 | 1481 | ||
| 1482 | /* make request to uCode to retrieve statistics information */ | 1482 | /* make request to uCode to retrieve statistics information */ |
| 1483 | mutex_lock(&priv->mutex); | 1483 | mutex_lock(&priv->mutex); |
| 1484 | ret = iwl_send_statistics_request(priv, CMD_SYNC, false); | 1484 | ret = iwl_send_statistics_request(priv, 0, false); |
| 1485 | mutex_unlock(&priv->mutex); | 1485 | mutex_unlock(&priv->mutex); |
| 1486 | 1486 | ||
| 1487 | if (ret) | 1487 | if (ret) |
| @@ -1868,7 +1868,7 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, | |||
| 1868 | 1868 | ||
| 1869 | /* make request to uCode to retrieve statistics information */ | 1869 | /* make request to uCode to retrieve statistics information */ |
| 1870 | mutex_lock(&priv->mutex); | 1870 | mutex_lock(&priv->mutex); |
| 1871 | iwl_send_statistics_request(priv, CMD_SYNC, true); | 1871 | iwl_send_statistics_request(priv, 0, true); |
| 1872 | mutex_unlock(&priv->mutex); | 1872 | mutex_unlock(&priv->mutex); |
| 1873 | 1873 | ||
| 1874 | return count; | 1874 | return count; |
| @@ -2188,7 +2188,6 @@ static int iwl_cmd_echo_test(struct iwl_priv *priv) | |||
| 2188 | struct iwl_host_cmd cmd = { | 2188 | struct iwl_host_cmd cmd = { |
| 2189 | .id = REPLY_ECHO, | 2189 | .id = REPLY_ECHO, |
| 2190 | .len = { 0 }, | 2190 | .len = { 0 }, |
| 2191 | .flags = CMD_SYNC, | ||
| 2192 | }; | 2191 | }; |
| 2193 | 2192 | ||
| 2194 | ret = iwl_dvm_send_cmd(priv, &cmd); | 2193 | ret = iwl_dvm_send_cmd(priv, &cmd); |
| @@ -2320,7 +2319,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | |||
| 2320 | mutex_lock(&priv->mutex); | 2319 | mutex_lock(&priv->mutex); |
| 2321 | 2320 | ||
| 2322 | /* take the return value to make compiler happy - it will fail anyway */ | 2321 | /* take the return value to make compiler happy - it will fail anyway */ |
| 2323 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, CMD_SYNC, 0, NULL); | 2322 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, 0, 0, NULL); |
| 2324 | 2323 | ||
| 2325 | mutex_unlock(&priv->mutex); | 2324 | mutex_unlock(&priv->mutex); |
| 2326 | 2325 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index 3441f70d0ff9..a6f22c32a279 100644 --- a/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h | |||
| @@ -888,9 +888,11 @@ struct iwl_priv { | |||
| 888 | 888 | ||
| 889 | struct iwl_event_log event_log; | 889 | struct iwl_event_log event_log; |
| 890 | 890 | ||
| 891 | #ifdef CONFIG_IWLWIFI_LEDS | ||
| 891 | struct led_classdev led; | 892 | struct led_classdev led; |
| 892 | unsigned long blink_on, blink_off; | 893 | unsigned long blink_on, blink_off; |
| 893 | bool led_registered; | 894 | bool led_registered; |
| 895 | #endif | ||
| 894 | 896 | ||
| 895 | /* WoWLAN GTK rekey data */ | 897 | /* WoWLAN GTK rekey data */ |
| 896 | u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN]; | 898 | u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN]; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 758c54eeb206..34b41e5f7cfc 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c | |||
| @@ -417,7 +417,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |||
| 417 | struct iwl_host_cmd hcmd = { | 417 | struct iwl_host_cmd hcmd = { |
| 418 | .id = REPLY_CHANNEL_SWITCH, | 418 | .id = REPLY_CHANNEL_SWITCH, |
| 419 | .len = { sizeof(cmd), }, | 419 | .len = { sizeof(cmd), }, |
| 420 | .flags = CMD_SYNC, | ||
| 421 | .data = { &cmd, }, | 420 | .data = { &cmd, }, |
| 422 | }; | 421 | }; |
| 423 | 422 | ||
| @@ -579,7 +578,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
| 579 | struct iwl_host_cmd hcmd = { | 578 | struct iwl_host_cmd hcmd = { |
| 580 | .id = REPLY_CHANNEL_SWITCH, | 579 | .id = REPLY_CHANNEL_SWITCH, |
| 581 | .len = { sizeof(*cmd), }, | 580 | .len = { sizeof(*cmd), }, |
| 582 | .flags = CMD_SYNC, | ||
| 583 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | 581 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, |
| 584 | }; | 582 | }; |
| 585 | int err; | 583 | int err; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/led.h b/drivers/net/wireless/iwlwifi/dvm/led.h index 6a0817d9c4fa..1c6b2252d0f2 100644 --- a/drivers/net/wireless/iwlwifi/dvm/led.h +++ b/drivers/net/wireless/iwlwifi/dvm/led.h | |||
| @@ -36,8 +36,20 @@ struct iwl_priv; | |||
| 36 | #define IWL_LED_ACTIVITY (0<<1) | 36 | #define IWL_LED_ACTIVITY (0<<1) |
| 37 | #define IWL_LED_LINK (1<<1) | 37 | #define IWL_LED_LINK (1<<1) |
| 38 | 38 | ||
| 39 | #ifdef CONFIG_IWLWIFI_LEDS | ||
| 39 | void iwlagn_led_enable(struct iwl_priv *priv); | 40 | void iwlagn_led_enable(struct iwl_priv *priv); |
| 40 | void iwl_leds_init(struct iwl_priv *priv); | 41 | void iwl_leds_init(struct iwl_priv *priv); |
| 41 | void iwl_leds_exit(struct iwl_priv *priv); | 42 | void iwl_leds_exit(struct iwl_priv *priv); |
| 43 | #else | ||
| 44 | static inline void iwlagn_led_enable(struct iwl_priv *priv) | ||
| 45 | { | ||
| 46 | } | ||
| 47 | static inline void iwl_leds_init(struct iwl_priv *priv) | ||
| 48 | { | ||
| 49 | } | ||
| 50 | static inline void iwl_leds_exit(struct iwl_priv *priv) | ||
| 51 | { | ||
| 52 | } | ||
| 53 | #endif | ||
| 42 | 54 | ||
| 43 | #endif /* __iwl_leds_h__ */ | 55 | #endif /* __iwl_leds_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index d169228f59e7..2191621d69c1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
| @@ -81,7 +81,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | |||
| 81 | else | 81 | else |
| 82 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; | 82 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; |
| 83 | 83 | ||
| 84 | return iwl_dvm_send_cmd_pdu(priv, tx_ant_cfg_cmd, CMD_SYNC, | 84 | return iwl_dvm_send_cmd_pdu(priv, tx_ant_cfg_cmd, 0, |
| 85 | sizeof(tx_power_cmd), &tx_power_cmd); | 85 | sizeof(tx_power_cmd), &tx_power_cmd); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| @@ -141,7 +141,6 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk) | |||
| 141 | struct iwl_host_cmd cmd = { | 141 | struct iwl_host_cmd cmd = { |
| 142 | .id = REPLY_TXFIFO_FLUSH, | 142 | .id = REPLY_TXFIFO_FLUSH, |
| 143 | .len = { sizeof(struct iwl_txfifo_flush_cmd), }, | 143 | .len = { sizeof(struct iwl_txfifo_flush_cmd), }, |
| 144 | .flags = CMD_SYNC, | ||
| 145 | .data = { &flush_cmd, }, | 144 | .data = { &flush_cmd, }, |
| 146 | }; | 145 | }; |
| 147 | 146 | ||
| @@ -333,12 +332,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) | |||
| 333 | memcpy(&bt_cmd_v2.basic, &basic, | 332 | memcpy(&bt_cmd_v2.basic, &basic, |
| 334 | sizeof(basic)); | 333 | sizeof(basic)); |
| 335 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, | 334 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, |
| 336 | CMD_SYNC, sizeof(bt_cmd_v2), &bt_cmd_v2); | 335 | 0, sizeof(bt_cmd_v2), &bt_cmd_v2); |
| 337 | } else { | 336 | } else { |
| 338 | memcpy(&bt_cmd_v1.basic, &basic, | 337 | memcpy(&bt_cmd_v1.basic, &basic, |
| 339 | sizeof(basic)); | 338 | sizeof(basic)); |
| 340 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, | 339 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, |
| 341 | CMD_SYNC, sizeof(bt_cmd_v1), &bt_cmd_v1); | 340 | 0, sizeof(bt_cmd_v1), &bt_cmd_v1); |
| 342 | } | 341 | } |
| 343 | if (ret) | 342 | if (ret) |
| 344 | IWL_ERR(priv, "failed to send BT Coex Config\n"); | 343 | IWL_ERR(priv, "failed to send BT Coex Config\n"); |
| @@ -1044,7 +1043,6 @@ int iwlagn_send_patterns(struct iwl_priv *priv, | |||
| 1044 | struct iwl_host_cmd cmd = { | 1043 | struct iwl_host_cmd cmd = { |
| 1045 | .id = REPLY_WOWLAN_PATTERNS, | 1044 | .id = REPLY_WOWLAN_PATTERNS, |
| 1046 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | 1045 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, |
| 1047 | .flags = CMD_SYNC, | ||
| 1048 | }; | 1046 | }; |
| 1049 | int i, err; | 1047 | int i, err; |
| 1050 | 1048 | ||
| @@ -1201,7 +1199,6 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan) | |||
| 1201 | if (key_data.use_rsc_tsc) { | 1199 | if (key_data.use_rsc_tsc) { |
| 1202 | struct iwl_host_cmd rsc_tsc_cmd = { | 1200 | struct iwl_host_cmd rsc_tsc_cmd = { |
| 1203 | .id = REPLY_WOWLAN_TSC_RSC_PARAMS, | 1201 | .id = REPLY_WOWLAN_TSC_RSC_PARAMS, |
| 1204 | .flags = CMD_SYNC, | ||
| 1205 | .data[0] = key_data.rsc_tsc, | 1202 | .data[0] = key_data.rsc_tsc, |
| 1206 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | 1203 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, |
| 1207 | .len[0] = sizeof(*key_data.rsc_tsc), | 1204 | .len[0] = sizeof(*key_data.rsc_tsc), |
| @@ -1215,7 +1212,7 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan) | |||
| 1215 | if (key_data.use_tkip) { | 1212 | if (key_data.use_tkip) { |
| 1216 | ret = iwl_dvm_send_cmd_pdu(priv, | 1213 | ret = iwl_dvm_send_cmd_pdu(priv, |
| 1217 | REPLY_WOWLAN_TKIP_PARAMS, | 1214 | REPLY_WOWLAN_TKIP_PARAMS, |
| 1218 | CMD_SYNC, sizeof(tkip_cmd), | 1215 | 0, sizeof(tkip_cmd), |
| 1219 | &tkip_cmd); | 1216 | &tkip_cmd); |
| 1220 | if (ret) | 1217 | if (ret) |
| 1221 | goto out; | 1218 | goto out; |
| @@ -1231,20 +1228,20 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan) | |||
| 1231 | 1228 | ||
| 1232 | ret = iwl_dvm_send_cmd_pdu(priv, | 1229 | ret = iwl_dvm_send_cmd_pdu(priv, |
| 1233 | REPLY_WOWLAN_KEK_KCK_MATERIAL, | 1230 | REPLY_WOWLAN_KEK_KCK_MATERIAL, |
| 1234 | CMD_SYNC, sizeof(kek_kck_cmd), | 1231 | 0, sizeof(kek_kck_cmd), |
| 1235 | &kek_kck_cmd); | 1232 | &kek_kck_cmd); |
| 1236 | if (ret) | 1233 | if (ret) |
| 1237 | goto out; | 1234 | goto out; |
| 1238 | } | 1235 | } |
| 1239 | } | 1236 | } |
| 1240 | 1237 | ||
| 1241 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_D3_CONFIG, CMD_SYNC, | 1238 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_D3_CONFIG, 0, |
| 1242 | sizeof(d3_cfg_cmd), &d3_cfg_cmd); | 1239 | sizeof(d3_cfg_cmd), &d3_cfg_cmd); |
| 1243 | if (ret) | 1240 | if (ret) |
| 1244 | goto out; | 1241 | goto out; |
| 1245 | 1242 | ||
| 1246 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_WAKEUP_FILTER, | 1243 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_WAKEUP_FILTER, |
| 1247 | CMD_SYNC, sizeof(wakeup_filter_cmd), | 1244 | 0, sizeof(wakeup_filter_cmd), |
| 1248 | &wakeup_filter_cmd); | 1245 | &wakeup_filter_cmd); |
| 1249 | if (ret) | 1246 | if (ret) |
| 1250 | goto out; | 1247 | goto out; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 6a00353768f3..0b7f46f0b079 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
| @@ -128,7 +128,6 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
| 128 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; | 128 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; |
| 129 | struct iwl_host_cmd cmd = { | 129 | struct iwl_host_cmd cmd = { |
| 130 | .id = REPLY_TX_BEACON, | 130 | .id = REPLY_TX_BEACON, |
| 131 | .flags = CMD_SYNC, | ||
| 132 | }; | 131 | }; |
| 133 | struct ieee80211_tx_info *info; | 132 | struct ieee80211_tx_info *info; |
| 134 | u32 frame_size; | 133 | u32 frame_size; |
| @@ -311,8 +310,7 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) | |||
| 311 | sizeof(struct iwl_statistics_cmd), | 310 | sizeof(struct iwl_statistics_cmd), |
| 312 | &statistics_cmd); | 311 | &statistics_cmd); |
| 313 | else | 312 | else |
| 314 | return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, | 313 | return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, 0, |
| 315 | CMD_SYNC, | ||
| 316 | sizeof(struct iwl_statistics_cmd), | 314 | sizeof(struct iwl_statistics_cmd), |
| 317 | &statistics_cmd); | 315 | &statistics_cmd); |
| 318 | } | 316 | } |
| @@ -622,7 +620,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
| 622 | 620 | ||
| 623 | ret = iwl_dvm_send_cmd_pdu(priv, | 621 | ret = iwl_dvm_send_cmd_pdu(priv, |
| 624 | REPLY_CT_KILL_CONFIG_CMD, | 622 | REPLY_CT_KILL_CONFIG_CMD, |
| 625 | CMD_SYNC, sizeof(adv_cmd), &adv_cmd); | 623 | 0, sizeof(adv_cmd), &adv_cmd); |
| 626 | if (ret) | 624 | if (ret) |
| 627 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); | 625 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); |
| 628 | else | 626 | else |
| @@ -637,7 +635,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
| 637 | 635 | ||
| 638 | ret = iwl_dvm_send_cmd_pdu(priv, | 636 | ret = iwl_dvm_send_cmd_pdu(priv, |
| 639 | REPLY_CT_KILL_CONFIG_CMD, | 637 | REPLY_CT_KILL_CONFIG_CMD, |
| 640 | CMD_SYNC, sizeof(cmd), &cmd); | 638 | 0, sizeof(cmd), &cmd); |
| 641 | if (ret) | 639 | if (ret) |
| 642 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); | 640 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); |
| 643 | else | 641 | else |
| @@ -673,9 +671,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | |||
| 673 | 671 | ||
| 674 | if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) { | 672 | if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) { |
| 675 | IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); | 673 | IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); |
| 676 | return iwl_dvm_send_cmd_pdu(priv, | 674 | return iwl_dvm_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, 0, |
| 677 | TX_ANT_CONFIGURATION_CMD, | ||
| 678 | CMD_SYNC, | ||
| 679 | sizeof(struct iwl_tx_ant_config_cmd), | 675 | sizeof(struct iwl_tx_ant_config_cmd), |
| 680 | &tx_ant_cmd); | 676 | &tx_ant_cmd); |
| 681 | } else { | 677 | } else { |
| @@ -703,7 +699,7 @@ static void iwl_send_bt_config(struct iwl_priv *priv) | |||
| 703 | (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); | 699 | (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); |
| 704 | 700 | ||
| 705 | if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, | 701 | if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, |
| 706 | CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd)) | 702 | 0, sizeof(struct iwl_bt_cmd), &bt_cmd)) |
| 707 | IWL_ERR(priv, "failed to send BT Coex Config\n"); | 703 | IWL_ERR(priv, "failed to send BT Coex Config\n"); |
| 708 | } | 704 | } |
| 709 | 705 | ||
| @@ -987,7 +983,7 @@ static void iwl_bg_restart(struct work_struct *data) | |||
| 987 | ieee80211_restart_hw(priv->hw); | 983 | ieee80211_restart_hw(priv->hw); |
| 988 | else | 984 | else |
| 989 | IWL_ERR(priv, | 985 | IWL_ERR(priv, |
| 990 | "Cannot request restart before registrating with mac80211"); | 986 | "Cannot request restart before registrating with mac80211\n"); |
| 991 | } else { | 987 | } else { |
| 992 | WARN_ON(1); | 988 | WARN_ON(1); |
| 993 | } | 989 | } |
| @@ -1127,7 +1123,6 @@ static void iwl_option_config(struct iwl_priv *priv) | |||
| 1127 | static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | 1123 | static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) |
| 1128 | { | 1124 | { |
| 1129 | struct iwl_nvm_data *data = priv->nvm_data; | 1125 | struct iwl_nvm_data *data = priv->nvm_data; |
| 1130 | char *debug_msg; | ||
| 1131 | 1126 | ||
| 1132 | if (data->sku_cap_11n_enable && | 1127 | if (data->sku_cap_11n_enable && |
| 1133 | !priv->cfg->ht_params) { | 1128 | !priv->cfg->ht_params) { |
| @@ -1141,8 +1136,8 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | |||
| 1141 | return -EINVAL; | 1136 | return -EINVAL; |
| 1142 | } | 1137 | } |
| 1143 | 1138 | ||
| 1144 | debug_msg = "Device SKU: 24GHz %s %s, 52GHz %s %s, 11.n %s %s\n"; | 1139 | IWL_DEBUG_INFO(priv, |
| 1145 | IWL_DEBUG_INFO(priv, debug_msg, | 1140 | "Device SKU: 24GHz %s %s, 52GHz %s %s, 11.n %s %s\n", |
| 1146 | data->sku_cap_band_24GHz_enable ? "" : "NOT", "enabled", | 1141 | data->sku_cap_band_24GHz_enable ? "" : "NOT", "enabled", |
| 1147 | data->sku_cap_band_52GHz_enable ? "" : "NOT", "enabled", | 1142 | data->sku_cap_band_52GHz_enable ? "" : "NOT", "enabled", |
| 1148 | data->sku_cap_11n_enable ? "" : "NOT", "enabled"); | 1143 | data->sku_cap_11n_enable ? "" : "NOT", "enabled"); |
| @@ -1350,7 +1345,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
| 1350 | iwl_set_hw_params(priv); | 1345 | iwl_set_hw_params(priv); |
| 1351 | 1346 | ||
| 1352 | if (!(priv->nvm_data->sku_cap_ipan_enable)) { | 1347 | if (!(priv->nvm_data->sku_cap_ipan_enable)) { |
| 1353 | IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN"); | 1348 | IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN\n"); |
| 1354 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; | 1349 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; |
| 1355 | /* | 1350 | /* |
| 1356 | * if not PAN, then don't support P2P -- might be a uCode | 1351 | * if not PAN, then don't support P2P -- might be a uCode |
| @@ -2019,10 +2014,10 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv) | |||
| 2019 | 2014 | ||
| 2020 | for (mq = 0; mq < IWLAGN_FIRST_AMPDU_QUEUE; mq++) { | 2015 | for (mq = 0; mq < IWLAGN_FIRST_AMPDU_QUEUE; mq++) { |
| 2021 | if (!test_bit(mq, &priv->transport_queue_stop)) { | 2016 | if (!test_bit(mq, &priv->transport_queue_stop)) { |
| 2022 | IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d", mq); | 2017 | IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d\n", mq); |
| 2023 | ieee80211_wake_queue(priv->hw, mq); | 2018 | ieee80211_wake_queue(priv->hw, mq); |
| 2024 | } else { | 2019 | } else { |
| 2025 | IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d", mq); | 2020 | IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d\n", mq); |
| 2026 | } | 2021 | } |
| 2027 | } | 2022 | } |
| 2028 | 2023 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/power.c b/drivers/net/wireless/iwlwifi/dvm/power.c index b4e61417013a..f2c1439566b5 100644 --- a/drivers/net/wireless/iwlwifi/dvm/power.c +++ b/drivers/net/wireless/iwlwifi/dvm/power.c | |||
| @@ -278,7 +278,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) | |||
| 278 | le32_to_cpu(cmd->sleep_interval[3]), | 278 | le32_to_cpu(cmd->sleep_interval[3]), |
| 279 | le32_to_cpu(cmd->sleep_interval[4])); | 279 | le32_to_cpu(cmd->sleep_interval[4])); |
| 280 | 280 | ||
| 281 | return iwl_dvm_send_cmd_pdu(priv, POWER_TABLE_CMD, CMD_SYNC, | 281 | return iwl_dvm_send_cmd_pdu(priv, POWER_TABLE_CMD, 0, |
| 282 | sizeof(struct iwl_powertable_cmd), cmd); | 282 | sizeof(struct iwl_powertable_cmd), cmd); |
| 283 | } | 283 | } |
| 284 | 284 | ||
| @@ -361,7 +361,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, | |||
| 361 | 361 | ||
| 362 | memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)); | 362 | memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)); |
| 363 | } else | 363 | } else |
| 364 | IWL_ERR(priv, "set power fail, ret = %d", ret); | 364 | IWL_ERR(priv, "set power fail, ret = %d\n", ret); |
| 365 | 365 | ||
| 366 | return ret; | 366 | return ret; |
| 367 | } | 367 | } |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index aa773a2da4ab..32b78a66536d 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c | |||
| @@ -1453,7 +1453,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
| 1453 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1453 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
| 1454 | break; | 1454 | break; |
| 1455 | default: | 1455 | default: |
| 1456 | IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); | 1456 | IWL_ERR(priv, "Invalid BT load %d\n", priv->bt_traffic_load); |
| 1457 | break; | 1457 | break; |
| 1458 | } | 1458 | } |
| 1459 | 1459 | ||
| @@ -1628,7 +1628,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
| 1628 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1628 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
| 1629 | break; | 1629 | break; |
| 1630 | default: | 1630 | default: |
| 1631 | IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); | 1631 | IWL_ERR(priv, "Invalid BT load %d\n", priv->bt_traffic_load); |
| 1632 | break; | 1632 | break; |
| 1633 | } | 1633 | } |
| 1634 | 1634 | ||
| @@ -1799,7 +1799,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
| 1799 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | 1799 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; |
| 1800 | break; | 1800 | break; |
| 1801 | default: | 1801 | default: |
| 1802 | IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); | 1802 | IWL_ERR(priv, "Invalid BT load %d\n", priv->bt_traffic_load); |
| 1803 | break; | 1803 | break; |
| 1804 | } | 1804 | } |
| 1805 | 1805 | ||
| @@ -1969,7 +1969,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
| 1969 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; | 1969 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; |
| 1970 | break; | 1970 | break; |
| 1971 | default: | 1971 | default: |
| 1972 | IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load); | 1972 | IWL_ERR(priv, "Invalid BT load %d\n", priv->bt_traffic_load); |
| 1973 | break; | 1973 | break; |
| 1974 | } | 1974 | } |
| 1975 | 1975 | ||
| @@ -2709,7 +2709,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
| 2709 | rs_set_expected_tpt_table(lq_sta, tbl); | 2709 | rs_set_expected_tpt_table(lq_sta, tbl); |
| 2710 | rs_fill_link_cmd(NULL, lq_sta, rate); | 2710 | rs_fill_link_cmd(NULL, lq_sta, rate); |
| 2711 | priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; | 2711 | priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; |
| 2712 | iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_SYNC, true); | 2712 | iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, 0, true); |
| 2713 | } | 2713 | } |
| 2714 | 2714 | ||
| 2715 | static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | 2715 | static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index cd8377346aff..debec963c610 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c | |||
| @@ -786,7 +786,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
| 786 | 786 | ||
| 787 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | 787 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); |
| 788 | 788 | ||
| 789 | ieee80211_rx_ni(priv->hw, skb); | 789 | ieee80211_rx(priv->hw, skb); |
| 790 | } | 790 | } |
| 791 | 791 | ||
| 792 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | 792 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c index 503a81e58185..ed50de6362ed 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rxon.c +++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c | |||
| @@ -104,7 +104,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv, | |||
| 104 | 104 | ||
| 105 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 105 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
| 106 | ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, | 106 | ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, |
| 107 | CMD_SYNC, sizeof(*send), send); | 107 | 0, sizeof(*send), send); |
| 108 | 108 | ||
| 109 | send->filter_flags = old_filter; | 109 | send->filter_flags = old_filter; |
| 110 | 110 | ||
| @@ -134,7 +134,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, | |||
| 134 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 134 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
| 135 | send->dev_type = RXON_DEV_TYPE_P2P; | 135 | send->dev_type = RXON_DEV_TYPE_P2P; |
| 136 | ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, | 136 | ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, |
| 137 | CMD_SYNC, sizeof(*send), send); | 137 | 0, sizeof(*send), send); |
| 138 | 138 | ||
| 139 | send->filter_flags = old_filter; | 139 | send->filter_flags = old_filter; |
| 140 | send->dev_type = old_dev_type; | 140 | send->dev_type = old_dev_type; |
| @@ -160,7 +160,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv, | |||
| 160 | int ret; | 160 | int ret; |
| 161 | 161 | ||
| 162 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 162 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
| 163 | ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC, | 163 | ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, 0, |
| 164 | sizeof(*send), send); | 164 | sizeof(*send), send); |
| 165 | 165 | ||
| 166 | send->filter_flags = old_filter; | 166 | send->filter_flags = old_filter; |
| @@ -189,7 +189,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv, | |||
| 189 | ctx->qos_data.qos_active, | 189 | ctx->qos_data.qos_active, |
| 190 | ctx->qos_data.def_qos_parm.qos_flags); | 190 | ctx->qos_data.def_qos_parm.qos_flags); |
| 191 | 191 | ||
| 192 | ret = iwl_dvm_send_cmd_pdu(priv, ctx->qos_cmd, CMD_SYNC, | 192 | ret = iwl_dvm_send_cmd_pdu(priv, ctx->qos_cmd, 0, |
| 193 | sizeof(struct iwl_qosparam_cmd), | 193 | sizeof(struct iwl_qosparam_cmd), |
| 194 | &ctx->qos_data.def_qos_parm); | 194 | &ctx->qos_data.def_qos_parm); |
| 195 | if (ret) | 195 | if (ret) |
| @@ -353,7 +353,7 @@ static int iwl_send_rxon_timing(struct iwl_priv *priv, | |||
| 353 | le16_to_cpu(ctx->timing.atim_window)); | 353 | le16_to_cpu(ctx->timing.atim_window)); |
| 354 | 354 | ||
| 355 | return iwl_dvm_send_cmd_pdu(priv, ctx->rxon_timing_cmd, | 355 | return iwl_dvm_send_cmd_pdu(priv, ctx->rxon_timing_cmd, |
| 356 | CMD_SYNC, sizeof(ctx->timing), &ctx->timing); | 356 | 0, sizeof(ctx->timing), &ctx->timing); |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | static int iwlagn_rxon_disconn(struct iwl_priv *priv, | 359 | static int iwlagn_rxon_disconn(struct iwl_priv *priv, |
| @@ -495,7 +495,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, | |||
| 495 | * Associated RXON doesn't clear the station table in uCode, | 495 | * Associated RXON doesn't clear the station table in uCode, |
| 496 | * so we don't need to restore stations etc. after this. | 496 | * so we don't need to restore stations etc. after this. |
| 497 | */ | 497 | */ |
| 498 | ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC, | 498 | ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, 0, |
| 499 | sizeof(struct iwl_rxon_cmd), &ctx->staging); | 499 | sizeof(struct iwl_rxon_cmd), &ctx->staging); |
| 500 | if (ret) { | 500 | if (ret) { |
| 501 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); | 501 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); |
| @@ -610,7 +610,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
| 610 | cmd.slots[0].width = cpu_to_le16(slot0); | 610 | cmd.slots[0].width = cpu_to_le16(slot0); |
| 611 | cmd.slots[1].width = cpu_to_le16(slot1); | 611 | cmd.slots[1].width = cpu_to_le16(slot1); |
| 612 | 612 | ||
| 613 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, CMD_SYNC, | 613 | ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, 0, |
| 614 | sizeof(cmd), &cmd); | 614 | sizeof(cmd), &cmd); |
| 615 | if (ret) | 615 | if (ret) |
| 616 | IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); | 616 | IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); |
| @@ -823,7 +823,7 @@ static int iwl_check_rxon_cmd(struct iwl_priv *priv, | |||
| 823 | 823 | ||
| 824 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) | 824 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) |
| 825 | == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) { | 825 | == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) { |
| 826 | IWL_WARN(priv, "CCK and auto detect"); | 826 | IWL_WARN(priv, "CCK and auto detect\n"); |
| 827 | errors |= BIT(8); | 827 | errors |= BIT(8); |
| 828 | } | 828 | } |
| 829 | 829 | ||
| @@ -1395,7 +1395,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | |||
| 1395 | priv->phy_calib_chain_noise_reset_cmd); | 1395 | priv->phy_calib_chain_noise_reset_cmd); |
| 1396 | ret = iwl_dvm_send_cmd_pdu(priv, | 1396 | ret = iwl_dvm_send_cmd_pdu(priv, |
| 1397 | REPLY_PHY_CALIBRATION_CMD, | 1397 | REPLY_PHY_CALIBRATION_CMD, |
| 1398 | CMD_SYNC, sizeof(cmd), &cmd); | 1398 | 0, sizeof(cmd), &cmd); |
| 1399 | if (ret) | 1399 | if (ret) |
| 1400 | IWL_ERR(priv, | 1400 | IWL_ERR(priv, |
| 1401 | "Could not send REPLY_PHY_CALIBRATION_CMD\n"); | 1401 | "Could not send REPLY_PHY_CALIBRATION_CMD\n"); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index be98b913ed58..43bef901e8f9 100644 --- a/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c | |||
| @@ -59,7 +59,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) | |||
| 59 | int ret; | 59 | int ret; |
| 60 | struct iwl_host_cmd cmd = { | 60 | struct iwl_host_cmd cmd = { |
| 61 | .id = REPLY_SCAN_ABORT_CMD, | 61 | .id = REPLY_SCAN_ABORT_CMD, |
| 62 | .flags = CMD_SYNC | CMD_WANT_SKB, | 62 | .flags = CMD_WANT_SKB, |
| 63 | }; | 63 | }; |
| 64 | __le32 *status; | 64 | __le32 *status; |
| 65 | 65 | ||
| @@ -639,7 +639,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
| 639 | struct iwl_host_cmd cmd = { | 639 | struct iwl_host_cmd cmd = { |
| 640 | .id = REPLY_SCAN_CMD, | 640 | .id = REPLY_SCAN_CMD, |
| 641 | .len = { sizeof(struct iwl_scan_cmd), }, | 641 | .len = { sizeof(struct iwl_scan_cmd), }, |
| 642 | .flags = CMD_SYNC, | ||
| 643 | }; | 642 | }; |
| 644 | struct iwl_scan_cmd *scan; | 643 | struct iwl_scan_cmd *scan; |
| 645 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 644 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c index 9cdd91cdf661..6ec86adbe4a1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/sta.c +++ b/drivers/net/wireless/iwlwifi/dvm/sta.c | |||
| @@ -39,7 +39,7 @@ static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | |||
| 39 | lockdep_assert_held(&priv->sta_lock); | 39 | lockdep_assert_held(&priv->sta_lock); |
| 40 | 40 | ||
| 41 | if (sta_id >= IWLAGN_STATION_COUNT) { | 41 | if (sta_id >= IWLAGN_STATION_COUNT) { |
| 42 | IWL_ERR(priv, "invalid sta_id %u", sta_id); | 42 | IWL_ERR(priv, "invalid sta_id %u\n", sta_id); |
| 43 | return -EINVAL; | 43 | return -EINVAL; |
| 44 | } | 44 | } |
| 45 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) | 45 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) |
| @@ -165,7 +165,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
| 165 | iwl_free_resp(&cmd); | 165 | iwl_free_resp(&cmd); |
| 166 | 166 | ||
| 167 | if (cmd.handler_status) | 167 | if (cmd.handler_status) |
| 168 | IWL_ERR(priv, "%s - error in the CMD response %d", __func__, | 168 | IWL_ERR(priv, "%s - error in the CMD response %d\n", __func__, |
| 169 | cmd.handler_status); | 169 | cmd.handler_status); |
| 170 | 170 | ||
| 171 | return cmd.handler_status; | 171 | return cmd.handler_status; |
| @@ -261,7 +261,7 @@ int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
| 261 | cmd.station_flags = flags; | 261 | cmd.station_flags = flags; |
| 262 | cmd.sta.sta_id = sta_id; | 262 | cmd.sta.sta_id = sta_id; |
| 263 | 263 | ||
| 264 | return iwl_send_add_sta(priv, &cmd, CMD_SYNC); | 264 | return iwl_send_add_sta(priv, &cmd, 0); |
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, | 267 | static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, |
| @@ -413,7 +413,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | |||
| 413 | spin_unlock_bh(&priv->sta_lock); | 413 | spin_unlock_bh(&priv->sta_lock); |
| 414 | 414 | ||
| 415 | /* Add station to device's station table */ | 415 | /* Add station to device's station table */ |
| 416 | ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); | 416 | ret = iwl_send_add_sta(priv, &sta_cmd, 0); |
| 417 | if (ret) { | 417 | if (ret) { |
| 418 | spin_lock_bh(&priv->sta_lock); | 418 | spin_lock_bh(&priv->sta_lock); |
| 419 | IWL_ERR(priv, "Adding station %pM failed.\n", | 419 | IWL_ERR(priv, "Adding station %pM failed.\n", |
| @@ -456,7 +456,6 @@ static int iwl_send_remove_station(struct iwl_priv *priv, | |||
| 456 | struct iwl_host_cmd cmd = { | 456 | struct iwl_host_cmd cmd = { |
| 457 | .id = REPLY_REMOVE_STA, | 457 | .id = REPLY_REMOVE_STA, |
| 458 | .len = { sizeof(struct iwl_rem_sta_cmd), }, | 458 | .len = { sizeof(struct iwl_rem_sta_cmd), }, |
| 459 | .flags = CMD_SYNC, | ||
| 460 | .data = { &rm_sta_cmd, }, | 459 | .data = { &rm_sta_cmd, }, |
| 461 | }; | 460 | }; |
| 462 | 461 | ||
| @@ -740,7 +739,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
| 740 | send_lq = true; | 739 | send_lq = true; |
| 741 | } | 740 | } |
| 742 | spin_unlock_bh(&priv->sta_lock); | 741 | spin_unlock_bh(&priv->sta_lock); |
| 743 | ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); | 742 | ret = iwl_send_add_sta(priv, &sta_cmd, 0); |
| 744 | if (ret) { | 743 | if (ret) { |
| 745 | spin_lock_bh(&priv->sta_lock); | 744 | spin_lock_bh(&priv->sta_lock); |
| 746 | IWL_ERR(priv, "Adding station %pM failed.\n", | 745 | IWL_ERR(priv, "Adding station %pM failed.\n", |
| @@ -756,8 +755,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
| 756 | * current LQ command | 755 | * current LQ command |
| 757 | */ | 756 | */ |
| 758 | if (send_lq) | 757 | if (send_lq) |
| 759 | iwl_send_lq_cmd(priv, ctx, &lq, | 758 | iwl_send_lq_cmd(priv, ctx, &lq, 0, true); |
| 760 | CMD_SYNC, true); | ||
| 761 | spin_lock_bh(&priv->sta_lock); | 759 | spin_lock_bh(&priv->sta_lock); |
| 762 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; | 760 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; |
| 763 | } | 761 | } |
| @@ -968,7 +966,7 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, | |||
| 968 | return -ENOMEM; | 966 | return -ENOMEM; |
| 969 | } | 967 | } |
| 970 | 968 | ||
| 971 | ret = iwl_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true); | 969 | ret = iwl_send_lq_cmd(priv, ctx, link_cmd, 0, true); |
| 972 | if (ret) | 970 | if (ret) |
| 973 | IWL_ERR(priv, "Link quality command failed (%d)\n", ret); | 971 | IWL_ERR(priv, "Link quality command failed (%d)\n", ret); |
| 974 | 972 | ||
| @@ -999,7 +997,6 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, | |||
| 999 | struct iwl_host_cmd cmd = { | 997 | struct iwl_host_cmd cmd = { |
| 1000 | .id = ctx->wep_key_cmd, | 998 | .id = ctx->wep_key_cmd, |
| 1001 | .data = { wep_cmd, }, | 999 | .data = { wep_cmd, }, |
| 1002 | .flags = CMD_SYNC, | ||
| 1003 | }; | 1000 | }; |
| 1004 | 1001 | ||
| 1005 | might_sleep(); | 1002 | might_sleep(); |
| @@ -1248,7 +1245,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, | |||
| 1248 | sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; | 1245 | sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; |
| 1249 | sta_cmd.mode = STA_CONTROL_MODIFY_MSK; | 1246 | sta_cmd.mode = STA_CONTROL_MODIFY_MSK; |
| 1250 | 1247 | ||
| 1251 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); | 1248 | return iwl_send_add_sta(priv, &sta_cmd, 0); |
| 1252 | } | 1249 | } |
| 1253 | 1250 | ||
| 1254 | int iwl_set_dynamic_key(struct iwl_priv *priv, | 1251 | int iwl_set_dynamic_key(struct iwl_priv *priv, |
| @@ -1284,13 +1281,13 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, | |||
| 1284 | ieee80211_get_key_rx_seq(keyconf, 0, &seq); | 1281 | ieee80211_get_key_rx_seq(keyconf, 0, &seq); |
| 1285 | ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k); | 1282 | ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k); |
| 1286 | ret = iwlagn_send_sta_key(priv, keyconf, sta_id, | 1283 | ret = iwlagn_send_sta_key(priv, keyconf, sta_id, |
| 1287 | seq.tkip.iv32, p1k, CMD_SYNC); | 1284 | seq.tkip.iv32, p1k, 0); |
| 1288 | break; | 1285 | break; |
| 1289 | case WLAN_CIPHER_SUITE_CCMP: | 1286 | case WLAN_CIPHER_SUITE_CCMP: |
| 1290 | case WLAN_CIPHER_SUITE_WEP40: | 1287 | case WLAN_CIPHER_SUITE_WEP40: |
| 1291 | case WLAN_CIPHER_SUITE_WEP104: | 1288 | case WLAN_CIPHER_SUITE_WEP104: |
| 1292 | ret = iwlagn_send_sta_key(priv, keyconf, sta_id, | 1289 | ret = iwlagn_send_sta_key(priv, keyconf, sta_id, |
| 1293 | 0, NULL, CMD_SYNC); | 1290 | 0, NULL, 0); |
| 1294 | break; | 1291 | break; |
| 1295 | default: | 1292 | default: |
| 1296 | IWL_ERR(priv, "Unknown cipher %x\n", keyconf->cipher); | 1293 | IWL_ERR(priv, "Unknown cipher %x\n", keyconf->cipher); |
| @@ -1409,7 +1406,7 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) | |||
| 1409 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); | 1406 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); |
| 1410 | spin_unlock_bh(&priv->sta_lock); | 1407 | spin_unlock_bh(&priv->sta_lock); |
| 1411 | 1408 | ||
| 1412 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); | 1409 | return iwl_send_add_sta(priv, &sta_cmd, 0); |
| 1413 | } | 1410 | } |
| 1414 | 1411 | ||
| 1415 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, | 1412 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, |
| @@ -1433,7 +1430,7 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, | |||
| 1433 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); | 1430 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); |
| 1434 | spin_unlock_bh(&priv->sta_lock); | 1431 | spin_unlock_bh(&priv->sta_lock); |
| 1435 | 1432 | ||
| 1436 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); | 1433 | return iwl_send_add_sta(priv, &sta_cmd, 0); |
| 1437 | } | 1434 | } |
| 1438 | 1435 | ||
| 1439 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, | 1436 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, |
| @@ -1458,7 +1455,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, | |||
| 1458 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); | 1455 | memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); |
| 1459 | spin_unlock_bh(&priv->sta_lock); | 1456 | spin_unlock_bh(&priv->sta_lock); |
| 1460 | 1457 | ||
| 1461 | return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); | 1458 | return iwl_send_add_sta(priv, &sta_cmd, 0); |
| 1462 | } | 1459 | } |
| 1463 | 1460 | ||
| 1464 | 1461 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/tt.c b/drivers/net/wireless/iwlwifi/dvm/tt.c index 058c5892c427..acb981a0a0aa 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/iwlwifi/dvm/tt.c | |||
| @@ -236,7 +236,7 @@ static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) | |||
| 236 | { | 236 | { |
| 237 | IWL_DEBUG_TEMP(priv, "Prepare to enter IWL_TI_CT_KILL\n"); | 237 | IWL_DEBUG_TEMP(priv, "Prepare to enter IWL_TI_CT_KILL\n"); |
| 238 | /* make request to retrieve statistics information */ | 238 | /* make request to retrieve statistics information */ |
| 239 | iwl_send_statistics_request(priv, CMD_SYNC, false); | 239 | iwl_send_statistics_request(priv, 0, false); |
| 240 | /* Reschedule the ct_kill wait timer */ | 240 | /* Reschedule the ct_kill wait timer */ |
| 241 | mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, | 241 | mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, |
| 242 | jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); | 242 | jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 398dd096674c..3255a1723d17 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
| @@ -402,10 +402,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, | |||
| 402 | /* aggregation is on for this <sta,tid> */ | 402 | /* aggregation is on for this <sta,tid> */ |
| 403 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | 403 | if (info->flags & IEEE80211_TX_CTL_AMPDU && |
| 404 | tid_data->agg.state != IWL_AGG_ON) { | 404 | tid_data->agg.state != IWL_AGG_ON) { |
| 405 | IWL_ERR(priv, "TX_CTL_AMPDU while not in AGG:" | 405 | IWL_ERR(priv, |
| 406 | " Tx flags = 0x%08x, agg.state = %d", | 406 | "TX_CTL_AMPDU while not in AGG: Tx flags = 0x%08x, agg.state = %d\n", |
| 407 | info->flags, tid_data->agg.state); | 407 | info->flags, tid_data->agg.state); |
| 408 | IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d", | 408 | IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d\n", |
| 409 | sta_id, tid, | 409 | sta_id, tid, |
| 410 | IEEE80211_SEQ_TO_SN(tid_data->seq_number)); | 410 | IEEE80211_SEQ_TO_SN(tid_data->seq_number)); |
| 411 | goto drop_unlock_sta; | 411 | goto drop_unlock_sta; |
| @@ -416,7 +416,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, | |||
| 416 | */ | 416 | */ |
| 417 | if (WARN_ONCE(tid_data->agg.state != IWL_AGG_ON && | 417 | if (WARN_ONCE(tid_data->agg.state != IWL_AGG_ON && |
| 418 | tid_data->agg.state != IWL_AGG_OFF, | 418 | tid_data->agg.state != IWL_AGG_OFF, |
| 419 | "Tx while agg.state = %d", tid_data->agg.state)) | 419 | "Tx while agg.state = %d\n", tid_data->agg.state)) |
| 420 | goto drop_unlock_sta; | 420 | goto drop_unlock_sta; |
| 421 | 421 | ||
| 422 | seq_number = tid_data->seq_number; | 422 | seq_number = tid_data->seq_number; |
| @@ -778,8 +778,8 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid) | |||
| 778 | /* There are no packets for this RA / TID in the HW any more */ | 778 | /* There are no packets for this RA / TID in the HW any more */ |
| 779 | if (tid_data->agg.ssn == tid_data->next_reclaimed) { | 779 | if (tid_data->agg.ssn == tid_data->next_reclaimed) { |
| 780 | IWL_DEBUG_TX_QUEUES(priv, | 780 | IWL_DEBUG_TX_QUEUES(priv, |
| 781 | "Can continue DELBA flow ssn = next_recl =" | 781 | "Can continue DELBA flow ssn = next_recl = %d\n", |
| 782 | " %d", tid_data->next_reclaimed); | 782 | tid_data->next_reclaimed); |
| 783 | iwl_trans_txq_disable(priv->trans, | 783 | iwl_trans_txq_disable(priv->trans, |
| 784 | tid_data->agg.txq_id); | 784 | tid_data->agg.txq_id); |
| 785 | iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); | 785 | iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); |
| @@ -791,8 +791,8 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid) | |||
| 791 | /* There are no packets for this RA / TID in the HW any more */ | 791 | /* There are no packets for this RA / TID in the HW any more */ |
| 792 | if (tid_data->agg.ssn == tid_data->next_reclaimed) { | 792 | if (tid_data->agg.ssn == tid_data->next_reclaimed) { |
| 793 | IWL_DEBUG_TX_QUEUES(priv, | 793 | IWL_DEBUG_TX_QUEUES(priv, |
| 794 | "Can continue ADDBA flow ssn = next_recl =" | 794 | "Can continue ADDBA flow ssn = next_recl = %d\n", |
| 795 | " %d", tid_data->next_reclaimed); | 795 | tid_data->next_reclaimed); |
| 796 | tid_data->agg.state = IWL_AGG_STARTING; | 796 | tid_data->agg.state = IWL_AGG_STARTING; |
| 797 | ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); | 797 | ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); |
| 798 | } | 798 | } |
| @@ -1216,8 +1216,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
| 1216 | ctx->vif->type == NL80211_IFTYPE_STATION) { | 1216 | ctx->vif->type == NL80211_IFTYPE_STATION) { |
| 1217 | /* block and stop all queues */ | 1217 | /* block and stop all queues */ |
| 1218 | priv->passive_no_rx = true; | 1218 | priv->passive_no_rx = true; |
| 1219 | IWL_DEBUG_TX_QUEUES(priv, "stop all queues: " | 1219 | IWL_DEBUG_TX_QUEUES(priv, |
| 1220 | "passive channel"); | 1220 | "stop all queues: passive channel\n"); |
| 1221 | ieee80211_stop_queues(priv->hw); | 1221 | ieee80211_stop_queues(priv->hw); |
| 1222 | 1222 | ||
| 1223 | IWL_DEBUG_TX_REPLY(priv, | 1223 | IWL_DEBUG_TX_REPLY(priv, |
| @@ -1271,7 +1271,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
| 1271 | 1271 | ||
| 1272 | while (!skb_queue_empty(&skbs)) { | 1272 | while (!skb_queue_empty(&skbs)) { |
| 1273 | skb = __skb_dequeue(&skbs); | 1273 | skb = __skb_dequeue(&skbs); |
| 1274 | ieee80211_tx_status_ni(priv->hw, skb); | 1274 | ieee80211_tx_status(priv->hw, skb); |
| 1275 | } | 1275 | } |
| 1276 | 1276 | ||
| 1277 | return 0; | 1277 | return 0; |
| @@ -1411,7 +1411,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
| 1411 | 1411 | ||
| 1412 | while (!skb_queue_empty(&reclaimed_skbs)) { | 1412 | while (!skb_queue_empty(&reclaimed_skbs)) { |
| 1413 | skb = __skb_dequeue(&reclaimed_skbs); | 1413 | skb = __skb_dequeue(&reclaimed_skbs); |
| 1414 | ieee80211_tx_status_ni(priv->hw, skb); | 1414 | ieee80211_tx_status(priv->hw, skb); |
| 1415 | } | 1415 | } |
| 1416 | 1416 | ||
| 1417 | return 0; | 1417 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index cf03ef5619d9..d5cee1530597 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
| @@ -172,7 +172,7 @@ static int iwl_send_wimax_coex(struct iwl_priv *priv) | |||
| 172 | memset(&coex_cmd, 0, sizeof(coex_cmd)); | 172 | memset(&coex_cmd, 0, sizeof(coex_cmd)); |
| 173 | 173 | ||
| 174 | return iwl_dvm_send_cmd_pdu(priv, | 174 | return iwl_dvm_send_cmd_pdu(priv, |
| 175 | COEX_PRIORITY_TABLE_CMD, CMD_SYNC, | 175 | COEX_PRIORITY_TABLE_CMD, 0, |
| 176 | sizeof(coex_cmd), &coex_cmd); | 176 | sizeof(coex_cmd), &coex_cmd); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| @@ -205,7 +205,7 @@ void iwl_send_prio_tbl(struct iwl_priv *priv) | |||
| 205 | memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl, | 205 | memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl, |
| 206 | sizeof(iwl_bt_prio_tbl)); | 206 | sizeof(iwl_bt_prio_tbl)); |
| 207 | if (iwl_dvm_send_cmd_pdu(priv, | 207 | if (iwl_dvm_send_cmd_pdu(priv, |
| 208 | REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, | 208 | REPLY_BT_COEX_PRIO_TABLE, 0, |
| 209 | sizeof(prio_tbl_cmd), &prio_tbl_cmd)) | 209 | sizeof(prio_tbl_cmd), &prio_tbl_cmd)) |
| 210 | IWL_ERR(priv, "failed to send BT prio tbl command\n"); | 210 | IWL_ERR(priv, "failed to send BT prio tbl command\n"); |
| 211 | } | 211 | } |
| @@ -218,7 +218,7 @@ int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) | |||
| 218 | env_cmd.action = action; | 218 | env_cmd.action = action; |
| 219 | env_cmd.type = type; | 219 | env_cmd.type = type; |
| 220 | ret = iwl_dvm_send_cmd_pdu(priv, | 220 | ret = iwl_dvm_send_cmd_pdu(priv, |
| 221 | REPLY_BT_COEX_PROT_ENV, CMD_SYNC, | 221 | REPLY_BT_COEX_PROT_ENV, 0, |
| 222 | sizeof(env_cmd), &env_cmd); | 222 | sizeof(env_cmd), &env_cmd); |
| 223 | if (ret) | 223 | if (ret) |
| 224 | IWL_ERR(priv, "failed to send BT env command\n"); | 224 | IWL_ERR(priv, "failed to send BT env command\n"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index f73de239cdc1..48730064da73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
| @@ -98,7 +98,7 @@ | |||
| 98 | #define NVM_HW_SECTION_NUM_FAMILY_7000 0 | 98 | #define NVM_HW_SECTION_NUM_FAMILY_7000 0 |
| 99 | 99 | ||
| 100 | static const struct iwl_base_params iwl7000_base_params = { | 100 | static const struct iwl_base_params iwl7000_base_params = { |
| 101 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 101 | .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_7000, |
| 102 | .num_of_queues = IWLAGN_NUM_QUEUES, | 102 | .num_of_queues = IWLAGN_NUM_QUEUES, |
| 103 | .pll_cfg_val = 0, | 103 | .pll_cfg_val = 0, |
| 104 | .shadow_ram_support = true, | 104 | .shadow_ram_support = true, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c index f5bd82b88592..51c41531d81d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/iwlwifi/iwl-8000.c | |||
| @@ -83,9 +83,10 @@ | |||
| 83 | #define IWL8000_MODULE_FIRMWARE(api) IWL8000_FW_PRE __stringify(api) ".ucode" | 83 | #define IWL8000_MODULE_FIRMWARE(api) IWL8000_FW_PRE __stringify(api) ".ucode" |
| 84 | 84 | ||
| 85 | #define NVM_HW_SECTION_NUM_FAMILY_8000 10 | 85 | #define NVM_HW_SECTION_NUM_FAMILY_8000 10 |
| 86 | #define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin" | ||
| 86 | 87 | ||
| 87 | static const struct iwl_base_params iwl8000_base_params = { | 88 | static const struct iwl_base_params iwl8000_base_params = { |
| 88 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 89 | .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000, |
| 89 | .num_of_queues = IWLAGN_NUM_QUEUES, | 90 | .num_of_queues = IWLAGN_NUM_QUEUES, |
| 90 | .pll_cfg_val = 0, | 91 | .pll_cfg_val = 0, |
| 91 | .shadow_ram_support = true, | 92 | .shadow_ram_support = true, |
| @@ -118,6 +119,7 @@ const struct iwl_cfg iwl8260_2ac_cfg = { | |||
| 118 | .ht_params = &iwl8000_ht_params, | 119 | .ht_params = &iwl8000_ht_params, |
| 119 | .nvm_ver = IWL8000_NVM_VERSION, | 120 | .nvm_ver = IWL8000_NVM_VERSION, |
| 120 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 121 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
| 122 | .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000, | ||
| 121 | }; | 123 | }; |
| 122 | 124 | ||
| 123 | const struct iwl_cfg iwl8260_n_cfg = { | 125 | const struct iwl_cfg iwl8260_n_cfg = { |
| @@ -127,6 +129,7 @@ const struct iwl_cfg iwl8260_n_cfg = { | |||
| 127 | .ht_params = &iwl8000_ht_params, | 129 | .ht_params = &iwl8000_ht_params, |
| 128 | .nvm_ver = IWL8000_NVM_VERSION, | 130 | .nvm_ver = IWL8000_NVM_VERSION, |
| 129 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 131 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
| 132 | .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000, | ||
| 130 | }; | 133 | }; |
| 131 | 134 | ||
| 132 | MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); | 135 | MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index 7f37fb86837b..04a483d38659 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h | |||
| @@ -102,9 +102,7 @@ | |||
| 102 | 102 | ||
| 103 | /* EEPROM */ | 103 | /* EEPROM */ |
| 104 | #define IWLAGN_EEPROM_IMG_SIZE 2048 | 104 | #define IWLAGN_EEPROM_IMG_SIZE 2048 |
| 105 | /* OTP */ | 105 | |
| 106 | /* lower blocks contain EEPROM image and calibration data */ | ||
| 107 | #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ | ||
| 108 | /* high blocks contain PAPD data */ | 106 | /* high blocks contain PAPD data */ |
| 109 | #define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */ | 107 | #define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */ |
| 110 | #define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */ | 108 | #define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 7ce82d9c7222..b7047905f41a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
| @@ -193,6 +193,11 @@ struct iwl_ht_params { | |||
| 193 | #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS 0x80 | 193 | #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS 0x80 |
| 194 | #define EEPROM_REGULATORY_BAND_NO_HT40 0 | 194 | #define EEPROM_REGULATORY_BAND_NO_HT40 0 |
| 195 | 195 | ||
| 196 | /* lower blocks contain EEPROM image and calibration data */ | ||
| 197 | #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ | ||
| 198 | #define OTP_LOW_IMAGE_SIZE_FAMILY_7000 (16 * 512 * sizeof(u16)) /* 16 KB */ | ||
| 199 | #define OTP_LOW_IMAGE_SIZE_FAMILY_8000 (32 * 512 * sizeof(u16)) /* 32 KB */ | ||
| 200 | |||
| 196 | struct iwl_eeprom_params { | 201 | struct iwl_eeprom_params { |
| 197 | const u8 regulatory_bands[7]; | 202 | const u8 regulatory_bands[7]; |
| 198 | bool enhanced_txpower; | 203 | bool enhanced_txpower; |
| @@ -269,6 +274,8 @@ struct iwl_cfg { | |||
| 269 | u8 nvm_hw_section_num; | 274 | u8 nvm_hw_section_num; |
| 270 | bool lp_xtal_workaround; | 275 | bool lp_xtal_workaround; |
| 271 | const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; | 276 | const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; |
| 277 | bool no_power_up_nic_in_init; | ||
| 278 | const char *default_nvm_file; | ||
| 272 | }; | 279 | }; |
| 273 | 280 | ||
| 274 | /* | 281 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.c b/drivers/net/wireless/iwlwifi/iwl-debug.c index 8a44f594528d..09feff4fa226 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.c +++ b/drivers/net/wireless/iwlwifi/iwl-debug.c | |||
| @@ -61,8 +61,6 @@ | |||
| 61 | * | 61 | * |
| 62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
| 63 | 63 | ||
| 64 | #define DEBUG | ||
| 65 | |||
| 66 | #include <linux/device.h> | 64 | #include <linux/device.h> |
| 67 | #include <linux/interrupt.h> | 65 | #include <linux/interrupt.h> |
| 68 | #include <linux/export.h> | 66 | #include <linux/export.h> |
| @@ -128,8 +126,8 @@ void __iwl_dbg(struct device *dev, | |||
| 128 | #ifdef CONFIG_IWLWIFI_DEBUG | 126 | #ifdef CONFIG_IWLWIFI_DEBUG |
| 129 | if (iwl_have_debug_level(level) && | 127 | if (iwl_have_debug_level(level) && |
| 130 | (!limit || net_ratelimit())) | 128 | (!limit || net_ratelimit())) |
| 131 | dev_dbg(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U', | 129 | dev_printk(KERN_DEBUG, dev, "%c %s %pV", |
| 132 | function, &vaf); | 130 | in_interrupt() ? 'I' : 'U', function, &vaf); |
| 133 | #endif | 131 | #endif |
| 134 | trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf); | 132 | trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf); |
| 135 | va_end(args); | 133 | va_end(args); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index c8cbdbe15924..295083510e72 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
| @@ -47,12 +47,32 @@ void __iwl_warn(struct device *dev, const char *fmt, ...) __printf(2, 3); | |||
| 47 | void __iwl_info(struct device *dev, const char *fmt, ...) __printf(2, 3); | 47 | void __iwl_info(struct device *dev, const char *fmt, ...) __printf(2, 3); |
| 48 | void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3); | 48 | void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3); |
| 49 | 49 | ||
| 50 | /* not all compilers can evaluate strlen() at compile time, so use sizeof() */ | ||
| 51 | #define CHECK_FOR_NEWLINE(f) BUILD_BUG_ON(f[sizeof(f) - 2] != '\n') | ||
| 52 | |||
| 50 | /* No matter what is m (priv, bus, trans), this will work */ | 53 | /* No matter what is m (priv, bus, trans), this will work */ |
| 51 | #define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a) | 54 | #define IWL_ERR_DEV(d, f, a...) \ |
| 52 | #define IWL_ERR_DEV(d, f, a...) __iwl_err((d), false, false, f, ## a) | 55 | do { \ |
| 53 | #define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a) | 56 | CHECK_FOR_NEWLINE(f); \ |
| 54 | #define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a) | 57 | __iwl_err((d), false, false, f, ## a); \ |
| 55 | #define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a) | 58 | } while (0) |
| 59 | #define IWL_ERR(m, f, a...) \ | ||
| 60 | IWL_ERR_DEV((m)->dev, f, ## a) | ||
| 61 | #define IWL_WARN(m, f, a...) \ | ||
| 62 | do { \ | ||
| 63 | CHECK_FOR_NEWLINE(f); \ | ||
| 64 | __iwl_warn((m)->dev, f, ## a); \ | ||
| 65 | } while (0) | ||
| 66 | #define IWL_INFO(m, f, a...) \ | ||
| 67 | do { \ | ||
| 68 | CHECK_FOR_NEWLINE(f); \ | ||
| 69 | __iwl_info((m)->dev, f, ## a); \ | ||
| 70 | } while (0) | ||
| 71 | #define IWL_CRIT(m, f, a...) \ | ||
| 72 | do { \ | ||
| 73 | CHECK_FOR_NEWLINE(f); \ | ||
| 74 | __iwl_crit((m)->dev, f, ## a); \ | ||
| 75 | } while (0) | ||
| 56 | 76 | ||
| 57 | #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) | 77 | #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) |
| 58 | void __iwl_dbg(struct device *dev, | 78 | void __iwl_dbg(struct device *dev, |
| @@ -72,12 +92,17 @@ do { \ | |||
| 72 | DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ | 92 | DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ |
| 73 | } while (0) | 93 | } while (0) |
| 74 | 94 | ||
| 95 | #define __IWL_DEBUG_DEV(dev, level, limit, fmt, args...) \ | ||
| 96 | do { \ | ||
| 97 | CHECK_FOR_NEWLINE(fmt); \ | ||
| 98 | __iwl_dbg(dev, level, limit, __func__, fmt, ##args); \ | ||
| 99 | } while (0) | ||
| 75 | #define IWL_DEBUG(m, level, fmt, args...) \ | 100 | #define IWL_DEBUG(m, level, fmt, args...) \ |
| 76 | __iwl_dbg((m)->dev, level, false, __func__, fmt, ##args) | 101 | __IWL_DEBUG_DEV((m)->dev, level, false, fmt, ##args) |
| 77 | #define IWL_DEBUG_DEV(dev, level, fmt, args...) \ | 102 | #define IWL_DEBUG_DEV(dev, level, fmt, args...) \ |
| 78 | __iwl_dbg((dev), level, false, __func__, fmt, ##args) | 103 | __IWL_DEBUG_DEV(dev, level, false, fmt, ##args) |
| 79 | #define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ | 104 | #define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ |
| 80 | __iwl_dbg((m)->dev, level, true, __func__, fmt, ##args) | 105 | __IWL_DEBUG_DEV((m)->dev, level, true, fmt, ##args) |
| 81 | 106 | ||
| 82 | #ifdef CONFIG_IWLWIFI_DEBUG | 107 | #ifdef CONFIG_IWLWIFI_DEBUG |
| 83 | #define iwl_print_hex_dump(m, level, p, len) \ | 108 | #define iwl_print_hex_dump(m, level, p, len) \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 0a3e841b44a9..f2a5c12269a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
| @@ -1243,6 +1243,7 @@ struct iwl_mod_params iwlwifi_mod_params = { | |||
| 1243 | .bt_coex_active = true, | 1243 | .bt_coex_active = true, |
| 1244 | .power_level = IWL_POWER_INDEX_1, | 1244 | .power_level = IWL_POWER_INDEX_1, |
| 1245 | .wd_disable = true, | 1245 | .wd_disable = true, |
| 1246 | .uapsd_disable = false, | ||
| 1246 | /* the rest are 0 by default */ | 1247 | /* the rest are 0 by default */ |
| 1247 | }; | 1248 | }; |
| 1248 | IWL_EXPORT_SYMBOL(iwlwifi_mod_params); | 1249 | IWL_EXPORT_SYMBOL(iwlwifi_mod_params); |
| @@ -1356,6 +1357,10 @@ MODULE_PARM_DESC(wd_disable, | |||
| 1356 | module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO); | 1357 | module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO); |
| 1357 | MODULE_PARM_DESC(nvm_file, "NVM file name"); | 1358 | MODULE_PARM_DESC(nvm_file, "NVM file name"); |
| 1358 | 1359 | ||
| 1360 | module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, | ||
| 1361 | bool, S_IRUGO); | ||
| 1362 | MODULE_PARM_DESC(uapsd_disable, "disable U-APSD functionality (default: N)"); | ||
| 1363 | |||
| 1359 | /* | 1364 | /* |
| 1360 | * set bt_coex_active to true, uCode will do kill/defer | 1365 | * set bt_coex_active to true, uCode will do kill/defer |
| 1361 | * every time the priority line is asserted (BT is sending signals on the | 1366 | * every time the priority line is asserted (BT is sending signals on the |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h index f381908be7e5..2953ffceda38 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h | |||
| @@ -72,11 +72,14 @@ | |||
| 72 | * @IWL_FW_ERROR_DUMP_SRAM: | 72 | * @IWL_FW_ERROR_DUMP_SRAM: |
| 73 | * @IWL_FW_ERROR_DUMP_REG: | 73 | * @IWL_FW_ERROR_DUMP_REG: |
| 74 | * @IWL_FW_ERROR_DUMP_RXF: | 74 | * @IWL_FW_ERROR_DUMP_RXF: |
| 75 | * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as | ||
| 76 | * &struct iwl_fw_error_dump_txcmd packets | ||
| 75 | */ | 77 | */ |
| 76 | enum iwl_fw_error_dump_type { | 78 | enum iwl_fw_error_dump_type { |
| 77 | IWL_FW_ERROR_DUMP_SRAM = 0, | 79 | IWL_FW_ERROR_DUMP_SRAM = 0, |
| 78 | IWL_FW_ERROR_DUMP_REG = 1, | 80 | IWL_FW_ERROR_DUMP_REG = 1, |
| 79 | IWL_FW_ERROR_DUMP_RXF = 2, | 81 | IWL_FW_ERROR_DUMP_RXF = 2, |
| 82 | IWL_FW_ERROR_DUMP_TXCMD = 3, | ||
| 80 | 83 | ||
| 81 | IWL_FW_ERROR_DUMP_MAX, | 84 | IWL_FW_ERROR_DUMP_MAX, |
| 82 | }; | 85 | }; |
| @@ -105,4 +108,27 @@ struct iwl_fw_error_dump_file { | |||
| 105 | u8 data[0]; | 108 | u8 data[0]; |
| 106 | } __packed; | 109 | } __packed; |
| 107 | 110 | ||
| 111 | /** | ||
| 112 | * struct iwl_fw_error_dump_txcmd - TX command data | ||
| 113 | * @cmdlen: original length of command | ||
| 114 | * @caplen: captured length of command (may be less) | ||
| 115 | * @data: captured command data, @caplen bytes | ||
| 116 | */ | ||
| 117 | struct iwl_fw_error_dump_txcmd { | ||
| 118 | __le32 cmdlen; | ||
| 119 | __le32 caplen; | ||
| 120 | u8 data[]; | ||
| 121 | } __packed; | ||
| 122 | |||
| 123 | /** | ||
| 124 | * iwl_mvm_fw_error_next_data - advance fw error dump data pointer | ||
| 125 | * @data: previous data block | ||
| 126 | * Returns: next data block | ||
| 127 | */ | ||
| 128 | static inline struct iwl_fw_error_dump_data * | ||
| 129 | iwl_mvm_fw_error_next_data(struct iwl_fw_error_dump_data *data) | ||
| 130 | { | ||
| 131 | return (void *)(data->data + le32_to_cpu(data->len)); | ||
| 132 | } | ||
| 133 | |||
| 108 | #endif /* __fw_error_dump_h__ */ | 134 | #endif /* __fw_error_dump_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index f5927d0cf9b6..0aa7c0085c9f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
| @@ -74,7 +74,7 @@ | |||
| 74 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). | 74 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). |
| 75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. | 75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. |
| 76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS | 76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS |
| 77 | * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD | 77 | * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: This uCode image supports uAPSD |
| 78 | * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan | 78 | * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan |
| 79 | * offload profile config command. | 79 | * offload profile config command. |
| 80 | * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six | 80 | * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six |
| @@ -107,6 +107,7 @@ enum iwl_ucode_tlv_flag { | |||
| 107 | IWL_UCODE_TLV_FLAGS_P2P_PM = BIT(21), | 107 | IWL_UCODE_TLV_FLAGS_P2P_PM = BIT(21), |
| 108 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22), | 108 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22), |
| 109 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM = BIT(23), | 109 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM = BIT(23), |
| 110 | IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), | ||
| 110 | IWL_UCODE_TLV_FLAGS_EBS_SUPPORT = BIT(25), | 111 | IWL_UCODE_TLV_FLAGS_EBS_SUPPORT = BIT(25), |
| 111 | IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26), | 112 | IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26), |
| 112 | IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29), | 113 | IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29), |
| @@ -116,9 +117,11 @@ enum iwl_ucode_tlv_flag { | |||
| 116 | /** | 117 | /** |
| 117 | * enum iwl_ucode_tlv_api - ucode api | 118 | * enum iwl_ucode_tlv_api - ucode api |
| 118 | * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field. | 119 | * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field. |
| 120 | * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA. | ||
| 119 | */ | 121 | */ |
| 120 | enum iwl_ucode_tlv_api { | 122 | enum iwl_ucode_tlv_api { |
| 121 | IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0), | 123 | IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0), |
| 124 | IWL_UCODE_TLV_API_CSA_FLOW = BIT(4), | ||
| 122 | }; | 125 | }; |
| 123 | 126 | ||
| 124 | /** | 127 | /** |
| @@ -194,6 +197,11 @@ struct fw_img { | |||
| 194 | bool is_dual_cpus; | 197 | bool is_dual_cpus; |
| 195 | }; | 198 | }; |
| 196 | 199 | ||
| 200 | struct iwl_sf_region { | ||
| 201 | u32 addr; | ||
| 202 | u32 size; | ||
| 203 | }; | ||
| 204 | |||
| 197 | /* uCode version contains 4 values: Major/Minor/API/Serial */ | 205 | /* uCode version contains 4 values: Major/Minor/API/Serial */ |
| 198 | #define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24) | 206 | #define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24) |
| 199 | #define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16) | 207 | #define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 44cc3cf45762..5eef4ae7333b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include "iwl-io.h" | 33 | #include "iwl-io.h" |
| 34 | #include "iwl-csr.h" | 34 | #include "iwl-csr.h" |
| 35 | #include "iwl-debug.h" | 35 | #include "iwl-debug.h" |
| 36 | #include "iwl-prph.h" | ||
| 36 | #include "iwl-fh.h" | 37 | #include "iwl-fh.h" |
| 37 | 38 | ||
| 38 | #define IWL_POLL_INTERVAL 10 /* microseconds */ | 39 | #define IWL_POLL_INTERVAL 10 /* microseconds */ |
| @@ -183,6 +184,23 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | |||
| 183 | } | 184 | } |
| 184 | IWL_EXPORT_SYMBOL(iwl_clear_bits_prph); | 185 | IWL_EXPORT_SYMBOL(iwl_clear_bits_prph); |
| 185 | 186 | ||
| 187 | void iwl_force_nmi(struct iwl_trans *trans) | ||
| 188 | { | ||
| 189 | /* | ||
| 190 | * In HW previous to the 8000 HW family, and in the 8000 HW family | ||
| 191 | * itself when the revision step==0, the DEVICE_SET_NMI_REG is used | ||
| 192 | * to force an NMI. Otherwise, a different register - | ||
| 193 | * DEVICE_SET_NMI_8000B_REG - is used. | ||
| 194 | */ | ||
| 195 | if ((trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) || | ||
| 196 | ((trans->hw_rev & 0xc) == 0x0)) | ||
| 197 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, DEVICE_SET_NMI_VAL); | ||
| 198 | else | ||
| 199 | iwl_write_prph(trans, DEVICE_SET_NMI_8000B_REG, | ||
| 200 | DEVICE_SET_NMI_8000B_VAL); | ||
| 201 | } | ||
| 202 | IWL_EXPORT_SYMBOL(iwl_force_nmi); | ||
| 203 | |||
| 186 | static const char *get_fh_string(int cmd) | 204 | static const char *get_fh_string(int cmd) |
| 187 | { | 205 | { |
| 188 | #define IWL_CMD(x) case x: return #x | 206 | #define IWL_CMD(x) case x: return #x |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 665ddd9dbbc4..705d12c079e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
| @@ -80,6 +80,7 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); | |||
| 80 | void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, | 80 | void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, |
| 81 | u32 bits, u32 mask); | 81 | u32 bits, u32 mask); |
| 82 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); | 82 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); |
| 83 | void iwl_force_nmi(struct iwl_trans *trans); | ||
| 83 | 84 | ||
| 84 | /* Error handling */ | 85 | /* Error handling */ |
| 85 | int iwl_dump_fh(struct iwl_trans *trans, char **buf); | 86 | int iwl_dump_fh(struct iwl_trans *trans, char **buf); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index d994317db85b..d051857729ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
| @@ -119,6 +119,7 @@ struct iwl_mod_params { | |||
| 119 | #endif | 119 | #endif |
| 120 | int ant_coupling; | 120 | int ant_coupling; |
| 121 | char *nvm_file; | 121 | char *nvm_file; |
| 122 | bool uapsd_disable; | ||
| 122 | }; | 123 | }; |
| 123 | 124 | ||
| 124 | #endif /* #__iwl_modparams_h__ */ | 125 | #endif /* #__iwl_modparams_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 4049c0d626ba..85eee79c495c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
| @@ -62,6 +62,7 @@ | |||
| 62 | #include <linux/types.h> | 62 | #include <linux/types.h> |
| 63 | #include <linux/slab.h> | 63 | #include <linux/slab.h> |
| 64 | #include <linux/export.h> | 64 | #include <linux/export.h> |
| 65 | #include <linux/etherdevice.h> | ||
| 65 | #include "iwl-drv.h" | 66 | #include "iwl-drv.h" |
| 66 | #include "iwl-modparams.h" | 67 | #include "iwl-modparams.h" |
| 67 | #include "iwl-nvm-parse.h" | 68 | #include "iwl-nvm-parse.h" |
| @@ -127,7 +128,7 @@ static const u8 iwl_nvm_channels[] = { | |||
| 127 | 128 | ||
| 128 | static const u8 iwl_nvm_channels_family_8000[] = { | 129 | static const u8 iwl_nvm_channels_family_8000[] = { |
| 129 | /* 2.4 GHz */ | 130 | /* 2.4 GHz */ |
| 130 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, | 131 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
| 131 | /* 5 GHz */ | 132 | /* 5 GHz */ |
| 132 | 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, | 133 | 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, |
| 133 | 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, | 134 | 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, |
| @@ -137,7 +138,7 @@ static const u8 iwl_nvm_channels_family_8000[] = { | |||
| 137 | #define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels) | 138 | #define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels) |
| 138 | #define IWL_NUM_CHANNELS_FAMILY_8000 ARRAY_SIZE(iwl_nvm_channels_family_8000) | 139 | #define IWL_NUM_CHANNELS_FAMILY_8000 ARRAY_SIZE(iwl_nvm_channels_family_8000) |
| 139 | #define NUM_2GHZ_CHANNELS 14 | 140 | #define NUM_2GHZ_CHANNELS 14 |
| 140 | #define NUM_2GHZ_CHANNELS_FAMILY_8000 13 | 141 | #define NUM_2GHZ_CHANNELS_FAMILY_8000 14 |
| 141 | #define FIRST_2GHZ_HT_MINUS 5 | 142 | #define FIRST_2GHZ_HT_MINUS 5 |
| 142 | #define LAST_2GHZ_HT_PLUS 9 | 143 | #define LAST_2GHZ_HT_PLUS 9 |
| 143 | #define LAST_5GHZ_HT 161 | 144 | #define LAST_5GHZ_HT 161 |
| @@ -450,13 +451,7 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg, | |||
| 450 | struct iwl_nvm_data *data, | 451 | struct iwl_nvm_data *data, |
| 451 | const __le16 *nvm_sec) | 452 | const __le16 *nvm_sec) |
| 452 | { | 453 | { |
| 453 | u8 hw_addr[ETH_ALEN]; | 454 | const u8 *hw_addr = (const u8 *)(nvm_sec + HW_ADDR); |
| 454 | |||
| 455 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
| 456 | memcpy(hw_addr, nvm_sec + HW_ADDR, ETH_ALEN); | ||
| 457 | else | ||
| 458 | memcpy(hw_addr, nvm_sec + MAC_ADDRESS_OVERRIDE_FAMILY_8000, | ||
| 459 | ETH_ALEN); | ||
| 460 | 455 | ||
| 461 | /* The byte order is little endian 16 bit, meaning 214365 */ | 456 | /* The byte order is little endian 16 bit, meaning 214365 */ |
| 462 | data->hw_addr[0] = hw_addr[1]; | 457 | data->hw_addr[0] = hw_addr[1]; |
| @@ -467,6 +462,41 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg, | |||
| 467 | data->hw_addr[5] = hw_addr[4]; | 462 | data->hw_addr[5] = hw_addr[4]; |
| 468 | } | 463 | } |
| 469 | 464 | ||
| 465 | static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg, | ||
| 466 | struct iwl_nvm_data *data, | ||
| 467 | const __le16 *mac_override, | ||
| 468 | const __le16 *nvm_hw) | ||
| 469 | { | ||
| 470 | const u8 *hw_addr; | ||
| 471 | |||
| 472 | if (mac_override) { | ||
| 473 | hw_addr = (const u8 *)(mac_override + | ||
| 474 | MAC_ADDRESS_OVERRIDE_FAMILY_8000); | ||
| 475 | |||
| 476 | /* The byte order is little endian 16 bit, meaning 214365 */ | ||
| 477 | data->hw_addr[0] = hw_addr[1]; | ||
| 478 | data->hw_addr[1] = hw_addr[0]; | ||
| 479 | data->hw_addr[2] = hw_addr[3]; | ||
| 480 | data->hw_addr[3] = hw_addr[2]; | ||
| 481 | data->hw_addr[4] = hw_addr[5]; | ||
| 482 | data->hw_addr[5] = hw_addr[4]; | ||
| 483 | |||
| 484 | if (is_valid_ether_addr(hw_addr)) | ||
| 485 | return; | ||
| 486 | } | ||
| 487 | |||
| 488 | /* take the MAC address from the OTP */ | ||
| 489 | hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_FAMILY_8000); | ||
| 490 | data->hw_addr[0] = hw_addr[3]; | ||
| 491 | data->hw_addr[1] = hw_addr[2]; | ||
| 492 | data->hw_addr[2] = hw_addr[1]; | ||
| 493 | data->hw_addr[3] = hw_addr[0]; | ||
| 494 | |||
| 495 | hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_FAMILY_8000); | ||
| 496 | data->hw_addr[4] = hw_addr[1]; | ||
| 497 | data->hw_addr[5] = hw_addr[0]; | ||
| 498 | } | ||
| 499 | |||
| 470 | struct iwl_nvm_data * | 500 | struct iwl_nvm_data * |
| 471 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | 501 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, |
| 472 | const __le16 *nvm_hw, const __le16 *nvm_sw, | 502 | const __le16 *nvm_hw, const __le16 *nvm_sw, |
| @@ -526,7 +556,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | |||
| 526 | rx_chains); | 556 | rx_chains); |
| 527 | } else { | 557 | } else { |
| 528 | /* MAC address in family 8000 */ | 558 | /* MAC address in family 8000 */ |
| 529 | iwl_set_hw_address(cfg, data, mac_override); | 559 | iwl_set_hw_address_family_8000(cfg, data, mac_override, nvm_hw); |
| 530 | 560 | ||
| 531 | iwl_init_sbands(dev, cfg, data, regulatory, | 561 | iwl_init_sbands(dev, cfg, data, regulatory, |
| 532 | sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, | 562 | sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c index b761ac4822a3..d4fb5cad07ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c | |||
| @@ -345,7 +345,6 @@ static int iwl_send_phy_db_cmd(struct iwl_phy_db *phy_db, u16 type, | |||
| 345 | struct iwl_phy_db_cmd phy_db_cmd; | 345 | struct iwl_phy_db_cmd phy_db_cmd; |
| 346 | struct iwl_host_cmd cmd = { | 346 | struct iwl_host_cmd cmd = { |
| 347 | .id = PHY_DB_CMD, | 347 | .id = PHY_DB_CMD, |
| 348 | .flags = CMD_SYNC, | ||
| 349 | }; | 348 | }; |
| 350 | 349 | ||
| 351 | IWL_DEBUG_INFO(phy_db->trans, | 350 | IWL_DEBUG_INFO(phy_db->trans, |
| @@ -393,13 +392,13 @@ static int iwl_phy_db_send_all_channel_groups( | |||
| 393 | entry->data); | 392 | entry->data); |
| 394 | if (err) { | 393 | if (err) { |
| 395 | IWL_ERR(phy_db->trans, | 394 | IWL_ERR(phy_db->trans, |
| 396 | "Can't SEND phy_db section %d (%d), err %d", | 395 | "Can't SEND phy_db section %d (%d), err %d\n", |
| 397 | type, i, err); | 396 | type, i, err); |
| 398 | return err; | 397 | return err; |
| 399 | } | 398 | } |
| 400 | 399 | ||
| 401 | IWL_DEBUG_INFO(phy_db->trans, | 400 | IWL_DEBUG_INFO(phy_db->trans, |
| 402 | "Sent PHY_DB HCMD, type = %d num = %d", | 401 | "Sent PHY_DB HCMD, type = %d num = %d\n", |
| 403 | type, i); | 402 | type, i); |
| 404 | } | 403 | } |
| 405 | 404 | ||
| @@ -451,7 +450,7 @@ int iwl_send_phy_db_data(struct iwl_phy_db *phy_db) | |||
| 451 | IWL_NUM_PAPD_CH_GROUPS); | 450 | IWL_NUM_PAPD_CH_GROUPS); |
| 452 | if (err) { | 451 | if (err) { |
| 453 | IWL_ERR(phy_db->trans, | 452 | IWL_ERR(phy_db->trans, |
| 454 | "Cannot send channel specific PAPD groups"); | 453 | "Cannot send channel specific PAPD groups\n"); |
| 455 | return err; | 454 | return err; |
| 456 | } | 455 | } |
| 457 | 456 | ||
| @@ -461,7 +460,7 @@ int iwl_send_phy_db_data(struct iwl_phy_db *phy_db) | |||
| 461 | IWL_NUM_TXP_CH_GROUPS); | 460 | IWL_NUM_TXP_CH_GROUPS); |
| 462 | if (err) { | 461 | if (err) { |
| 463 | IWL_ERR(phy_db->trans, | 462 | IWL_ERR(phy_db->trans, |
| 464 | "Cannot send channel specific TX power groups"); | 463 | "Cannot send channel specific TX power groups\n"); |
| 465 | return err; | 464 | return err; |
| 466 | } | 465 | } |
| 467 | 466 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 779311080a9e..4997e27672b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
| @@ -105,6 +105,9 @@ | |||
| 105 | 105 | ||
| 106 | /* Device NMI register */ | 106 | /* Device NMI register */ |
| 107 | #define DEVICE_SET_NMI_REG 0x00a01c30 | 107 | #define DEVICE_SET_NMI_REG 0x00a01c30 |
| 108 | #define DEVICE_SET_NMI_VAL 0x1 | ||
| 109 | #define DEVICE_SET_NMI_8000B_REG 0x00a01c24 | ||
| 110 | #define DEVICE_SET_NMI_8000B_VAL 0x1000000 | ||
| 108 | 111 | ||
| 109 | /* Shared registers (0x0..0x3ff, via target indirect or periphery */ | 112 | /* Shared registers (0x0..0x3ff, via target indirect or periphery */ |
| 110 | #define SHR_BASE 0x00a10000 | 113 | #define SHR_BASE 0x00a10000 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 22fd94ec8048..34d49e171fb4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
| @@ -189,10 +189,9 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt) | |||
| 189 | /** | 189 | /** |
| 190 | * enum CMD_MODE - how to send the host commands ? | 190 | * enum CMD_MODE - how to send the host commands ? |
| 191 | * | 191 | * |
| 192 | * @CMD_SYNC: The caller will be stalled until the fw responds to the command | ||
| 193 | * @CMD_ASYNC: Return right away and don't wait for the response | 192 | * @CMD_ASYNC: Return right away and don't wait for the response |
| 194 | * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the | 193 | * @CMD_WANT_SKB: Not valid with CMD_ASYNC. The caller needs the buffer of |
| 195 | * response. The caller needs to call iwl_free_resp when done. | 194 | * the response. The caller needs to call iwl_free_resp when done. |
| 196 | * @CMD_HIGH_PRIO: The command is high priority - it goes to the front of the | 195 | * @CMD_HIGH_PRIO: The command is high priority - it goes to the front of the |
| 197 | * command queue, but after other high priority commands. valid only | 196 | * command queue, but after other high priority commands. valid only |
| 198 | * with CMD_ASYNC. | 197 | * with CMD_ASYNC. |
| @@ -202,7 +201,6 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt) | |||
| 202 | * (i.e. mark it as non-idle). | 201 | * (i.e. mark it as non-idle). |
| 203 | */ | 202 | */ |
| 204 | enum CMD_MODE { | 203 | enum CMD_MODE { |
| 205 | CMD_SYNC = 0, | ||
| 206 | CMD_ASYNC = BIT(0), | 204 | CMD_ASYNC = BIT(0), |
| 207 | CMD_WANT_SKB = BIT(1), | 205 | CMD_WANT_SKB = BIT(1), |
| 208 | CMD_SEND_IN_RFKILL = BIT(2), | 206 | CMD_SEND_IN_RFKILL = BIT(2), |
| @@ -427,7 +425,7 @@ struct iwl_trans; | |||
| 427 | * @send_cmd:send a host command. Must return -ERFKILL if RFkill is asserted. | 425 | * @send_cmd:send a host command. Must return -ERFKILL if RFkill is asserted. |
| 428 | * If RFkill is asserted in the middle of a SYNC host command, it must | 426 | * If RFkill is asserted in the middle of a SYNC host command, it must |
| 429 | * return -ERFKILL straight away. | 427 | * return -ERFKILL straight away. |
| 430 | * May sleep only if CMD_SYNC is set | 428 | * May sleep only if CMD_ASYNC is not set |
| 431 | * @tx: send an skb | 429 | * @tx: send an skb |
| 432 | * Must be atomic | 430 | * Must be atomic |
| 433 | * @reclaim: free packet until ssn. Returns a list of freed packets. | 431 | * @reclaim: free packet until ssn. Returns a list of freed packets. |
| @@ -463,6 +461,11 @@ struct iwl_trans; | |||
| 463 | * @unref: release a reference previously taken with @ref. Note that | 461 | * @unref: release a reference previously taken with @ref. Note that |
| 464 | * initially the reference count is 1, making an initial @unref | 462 | * initially the reference count is 1, making an initial @unref |
| 465 | * necessary to allow low power states. | 463 | * necessary to allow low power states. |
| 464 | * @dump_data: fill a data dump with debug data, maybe containing last | ||
| 465 | * TX'ed commands and similar. When called with a NULL buffer and | ||
| 466 | * zero buffer length, provide only the (estimated) required buffer | ||
| 467 | * length. Return the used buffer length. | ||
| 468 | * Note that the transport must fill in the proper file headers. | ||
| 466 | */ | 469 | */ |
| 467 | struct iwl_trans_ops { | 470 | struct iwl_trans_ops { |
| 468 | 471 | ||
| @@ -470,6 +473,8 @@ struct iwl_trans_ops { | |||
| 470 | void (*op_mode_leave)(struct iwl_trans *iwl_trans); | 473 | void (*op_mode_leave)(struct iwl_trans *iwl_trans); |
| 471 | int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw, | 474 | int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw, |
| 472 | bool run_in_rfkill); | 475 | bool run_in_rfkill); |
| 476 | int (*update_sf)(struct iwl_trans *trans, | ||
| 477 | struct iwl_sf_region *st_fwrd_space); | ||
| 473 | void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); | 478 | void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); |
| 474 | void (*stop_device)(struct iwl_trans *trans); | 479 | void (*stop_device)(struct iwl_trans *trans); |
| 475 | 480 | ||
| @@ -511,6 +516,10 @@ struct iwl_trans_ops { | |||
| 511 | u32 value); | 516 | u32 value); |
| 512 | void (*ref)(struct iwl_trans *trans); | 517 | void (*ref)(struct iwl_trans *trans); |
| 513 | void (*unref)(struct iwl_trans *trans); | 518 | void (*unref)(struct iwl_trans *trans); |
| 519 | |||
| 520 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
| 521 | u32 (*dump_data)(struct iwl_trans *trans, void *buf, u32 buflen); | ||
| 522 | #endif | ||
| 514 | }; | 523 | }; |
| 515 | 524 | ||
| 516 | /** | 525 | /** |
| @@ -629,6 +638,17 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans, | |||
| 629 | return trans->ops->start_fw(trans, fw, run_in_rfkill); | 638 | return trans->ops->start_fw(trans, fw, run_in_rfkill); |
| 630 | } | 639 | } |
| 631 | 640 | ||
| 641 | static inline int iwl_trans_update_sf(struct iwl_trans *trans, | ||
| 642 | struct iwl_sf_region *st_fwrd_space) | ||
| 643 | { | ||
| 644 | might_sleep(); | ||
| 645 | |||
| 646 | if (trans->ops->update_sf) | ||
| 647 | return trans->ops->update_sf(trans, st_fwrd_space); | ||
| 648 | |||
| 649 | return 0; | ||
| 650 | } | ||
| 651 | |||
| 632 | static inline void iwl_trans_stop_device(struct iwl_trans *trans) | 652 | static inline void iwl_trans_stop_device(struct iwl_trans *trans) |
| 633 | { | 653 | { |
| 634 | might_sleep(); | 654 | might_sleep(); |
| @@ -664,6 +684,16 @@ static inline void iwl_trans_unref(struct iwl_trans *trans) | |||
| 664 | trans->ops->unref(trans); | 684 | trans->ops->unref(trans); |
| 665 | } | 685 | } |
| 666 | 686 | ||
| 687 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
| 688 | static inline u32 iwl_trans_dump_data(struct iwl_trans *trans, | ||
| 689 | void *buf, u32 buflen) | ||
| 690 | { | ||
| 691 | if (!trans->ops->dump_data) | ||
| 692 | return 0; | ||
| 693 | return trans->ops->dump_data(trans, buf, buflen); | ||
| 694 | } | ||
| 695 | #endif | ||
| 696 | |||
| 667 | static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | 697 | static inline int iwl_trans_send_cmd(struct iwl_trans *trans, |
| 668 | struct iwl_host_cmd *cmd) | 698 | struct iwl_host_cmd *cmd) |
| 669 | { | 699 | { |
| @@ -677,7 +707,7 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | |||
| 677 | return -EIO; | 707 | return -EIO; |
| 678 | 708 | ||
| 679 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) { | 709 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) { |
| 680 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | 710 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); |
| 681 | return -EIO; | 711 | return -EIO; |
| 682 | } | 712 | } |
| 683 | 713 | ||
| @@ -719,7 +749,7 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
| 719 | return -EIO; | 749 | return -EIO; |
| 720 | 750 | ||
| 721 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) | 751 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 722 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | 752 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); |
| 723 | 753 | ||
| 724 | return trans->ops->tx(trans, skb, dev_cmd, queue); | 754 | return trans->ops->tx(trans, skb, dev_cmd, queue); |
| 725 | } | 755 | } |
| @@ -728,7 +758,7 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, | |||
| 728 | int ssn, struct sk_buff_head *skbs) | 758 | int ssn, struct sk_buff_head *skbs) |
| 729 | { | 759 | { |
| 730 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) | 760 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 731 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | 761 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); |
| 732 | 762 | ||
| 733 | trans->ops->reclaim(trans, queue, ssn, skbs); | 763 | trans->ops->reclaim(trans, queue, ssn, skbs); |
| 734 | } | 764 | } |
| @@ -745,7 +775,7 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, | |||
| 745 | might_sleep(); | 775 | might_sleep(); |
| 746 | 776 | ||
| 747 | if (unlikely((trans->state != IWL_TRANS_FW_ALIVE))) | 777 | if (unlikely((trans->state != IWL_TRANS_FW_ALIVE))) |
| 748 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | 778 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); |
| 749 | 779 | ||
| 750 | trans->ops->txq_enable(trans, queue, fifo, sta_id, tid, | 780 | trans->ops->txq_enable(trans, queue, fifo, sta_id, tid, |
| 751 | frame_limit, ssn); | 781 | frame_limit, ssn); |
| @@ -762,7 +792,7 @@ static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans, | |||
| 762 | u32 txq_bm) | 792 | u32 txq_bm) |
| 763 | { | 793 | { |
| 764 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) | 794 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 765 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | 795 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); |
| 766 | 796 | ||
| 767 | return trans->ops->wait_tx_queue_empty(trans, txq_bm); | 797 | return trans->ops->wait_tx_queue_empty(trans, txq_bm); |
| 768 | } | 798 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile index ccdd3b7c4cce..c30d7f64ec1e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/iwlwifi/mvm/Makefile | |||
| @@ -3,8 +3,9 @@ iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o | |||
| 3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o | 3 | iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o |
| 4 | iwlmvm-y += scan.o time-event.o rs.o | 4 | iwlmvm-y += scan.o time-event.o rs.o |
| 5 | iwlmvm-y += power.o coex.o | 5 | iwlmvm-y += power.o coex.o |
| 6 | iwlmvm-y += led.o tt.o offloading.o | 6 | iwlmvm-y += tt.o offloading.o |
| 7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o | 7 | iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o |
| 8 | iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o | ||
| 8 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o | 9 | iwlmvm-$(CONFIG_PM_SLEEP) += d3.o |
| 9 | 10 | ||
| 10 | ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ | 11 | ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index 4284672d0397..c8c3b38228f0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c | |||
| @@ -106,7 +106,7 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { | |||
| 106 | 106 | ||
| 107 | static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) | 107 | static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) |
| 108 | { | 108 | { |
| 109 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC, | 109 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, 0, |
| 110 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), | 110 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), |
| 111 | &iwl_bt_prio_tbl); | 111 | &iwl_bt_prio_tbl); |
| 112 | } | 112 | } |
| @@ -124,10 +124,10 @@ const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { | |||
| 124 | }; | 124 | }; |
| 125 | 125 | ||
| 126 | static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { | 126 | static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { |
| 127 | cpu_to_le32(0xf0f0f0f0), | 127 | cpu_to_le32(0xf0f0f0f0), /* 50% */ |
| 128 | cpu_to_le32(0xc0c0c0c0), | 128 | cpu_to_le32(0xc0c0c0c0), /* 25% */ |
| 129 | cpu_to_le32(0xfcfcfcfc), | 129 | cpu_to_le32(0xfcfcfcfc), /* 75% */ |
| 130 | cpu_to_le32(0xff00ff00), | 130 | cpu_to_le32(0xfefefefe), /* 87.5% */ |
| 131 | }; | 131 | }; |
| 132 | 132 | ||
| 133 | static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { | 133 | static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { |
| @@ -300,8 +300,8 @@ static const __le64 iwl_ci_mask[][3] = { | |||
| 300 | }; | 300 | }; |
| 301 | 301 | ||
| 302 | static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = { | 302 | static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = { |
| 303 | cpu_to_le32(0x22002200), | 303 | cpu_to_le32(0x28412201), |
| 304 | cpu_to_le32(0x33113311), | 304 | cpu_to_le32(0x11118451), |
| 305 | }; | 305 | }; |
| 306 | 306 | ||
| 307 | struct corunning_block_luts { | 307 | struct corunning_block_luts { |
| @@ -565,7 +565,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
| 565 | .id = BT_CONFIG, | 565 | .id = BT_CONFIG, |
| 566 | .len = { sizeof(*bt_cmd), }, | 566 | .len = { sizeof(*bt_cmd), }, |
| 567 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, | 567 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, |
| 568 | .flags = CMD_SYNC, | ||
| 569 | }; | 568 | }; |
| 570 | int ret; | 569 | int ret; |
| 571 | u32 flags; | 570 | u32 flags; |
| @@ -663,7 +662,6 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, | |||
| 663 | .data[0] = &bt_cmd, | 662 | .data[0] = &bt_cmd, |
| 664 | .len = { sizeof(*bt_cmd), }, | 663 | .len = { sizeof(*bt_cmd), }, |
| 665 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, | 664 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, |
| 666 | .flags = CMD_SYNC, | ||
| 667 | }; | 665 | }; |
| 668 | int ret = 0; | 666 | int ret = 0; |
| 669 | 667 | ||
| @@ -717,7 +715,8 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, | |||
| 717 | return ret; | 715 | return ret; |
| 718 | } | 716 | } |
| 719 | 717 | ||
| 720 | int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable) | 718 | static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, |
| 719 | bool enable) | ||
| 721 | { | 720 | { |
| 722 | struct iwl_bt_coex_cmd *bt_cmd; | 721 | struct iwl_bt_coex_cmd *bt_cmd; |
| 723 | /* Send ASYNC since this can be sent from an atomic context */ | 722 | /* Send ASYNC since this can be sent from an atomic context */ |
| @@ -735,8 +734,7 @@ int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable) | |||
| 735 | return 0; | 734 | return 0; |
| 736 | 735 | ||
| 737 | /* nothing to do */ | 736 | /* nothing to do */ |
| 738 | if (mvmsta->bt_reduced_txpower_dbg || | 737 | if (mvmsta->bt_reduced_txpower == enable) |
| 739 | mvmsta->bt_reduced_txpower == enable) | ||
| 740 | return 0; | 738 | return 0; |
| 741 | 739 | ||
| 742 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC); | 740 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC); |
| @@ -803,23 +801,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
| 803 | 801 | ||
| 804 | switch (vif->type) { | 802 | switch (vif->type) { |
| 805 | case NL80211_IFTYPE_STATION: | 803 | case NL80211_IFTYPE_STATION: |
| 804 | /* Count BSSes vifs */ | ||
| 805 | data->num_bss_ifaces++; | ||
| 806 | /* default smps_mode for BSS / P2P client is AUTOMATIC */ | 806 | /* default smps_mode for BSS / P2P client is AUTOMATIC */ |
| 807 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | 807 | smps_mode = IEEE80211_SMPS_AUTOMATIC; |
| 808 | data->num_bss_ifaces++; | ||
| 809 | |||
| 810 | /* | ||
| 811 | * Count unassoc BSSes, relax SMSP constraints | ||
| 812 | * and disable reduced Tx Power | ||
| 813 | */ | ||
| 814 | if (!vif->bss_conf.assoc) { | ||
| 815 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
| 816 | smps_mode); | ||
| 817 | if (iwl_mvm_bt_coex_reduced_txp(mvm, | ||
| 818 | mvmvif->ap_sta_id, | ||
| 819 | false)) | ||
| 820 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | ||
| 821 | return; | ||
| 822 | } | ||
| 823 | break; | 808 | break; |
| 824 | case NL80211_IFTYPE_AP: | 809 | case NL80211_IFTYPE_AP: |
| 825 | /* default smps_mode for AP / GO is OFF */ | 810 | /* default smps_mode for AP / GO is OFF */ |
| @@ -845,8 +830,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
| 845 | /* ... relax constraints and disable rssi events */ | 830 | /* ... relax constraints and disable rssi events */ |
| 846 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | 831 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, |
| 847 | smps_mode); | 832 | smps_mode); |
| 848 | if (vif->type == NL80211_IFTYPE_STATION) | 833 | data->reduced_tx_power = false; |
| 834 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
| 835 | iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, | ||
| 836 | false); | ||
| 849 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | 837 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); |
| 838 | } | ||
| 850 | return; | 839 | return; |
| 851 | } | 840 | } |
| 852 | 841 | ||
| @@ -857,6 +846,11 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
| 857 | smps_mode = vif->type == NL80211_IFTYPE_AP ? | 846 | smps_mode = vif->type == NL80211_IFTYPE_AP ? |
| 858 | IEEE80211_SMPS_OFF : | 847 | IEEE80211_SMPS_OFF : |
| 859 | IEEE80211_SMPS_DYNAMIC; | 848 | IEEE80211_SMPS_DYNAMIC; |
| 849 | |||
| 850 | /* relax SMPS contraints for next association */ | ||
| 851 | if (!vif->bss_conf.assoc) | ||
| 852 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | ||
| 853 | |||
| 860 | IWL_DEBUG_COEX(data->mvm, | 854 | IWL_DEBUG_COEX(data->mvm, |
| 861 | "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n", | 855 | "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n", |
| 862 | mvmvif->id, data->notif->bt_status, bt_activity_grading, | 856 | mvmvif->id, data->notif->bt_status, bt_activity_grading, |
| @@ -903,22 +897,18 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
| 903 | /* if secondary is not NULL, it might be a GO */ | 897 | /* if secondary is not NULL, it might be a GO */ |
| 904 | data->secondary = chanctx_conf; | 898 | data->secondary = chanctx_conf; |
| 905 | 899 | ||
| 906 | /* don't reduce the Tx power if in loose scheme */ | 900 | /* |
| 901 | * don't reduce the Tx power if one of these is true: | ||
| 902 | * we are in LOOSE | ||
| 903 | * single share antenna product | ||
| 904 | * BT is active | ||
| 905 | * we are associated | ||
| 906 | */ | ||
| 907 | if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || | 907 | if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || |
| 908 | mvm->cfg->bt_shared_single_ant) { | 908 | mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc || |
| 909 | data->reduced_tx_power = false; | 909 | !data->notif->bt_status) { |
| 910 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | ||
| 911 | return; | ||
| 912 | } | ||
| 913 | |||
| 914 | /* reduced Txpower only if BT is on, so ...*/ | ||
| 915 | if (!data->notif->bt_status) { | ||
| 916 | /* ... cancel reduced Tx power ... */ | ||
| 917 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) | ||
| 918 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | ||
| 919 | data->reduced_tx_power = false; | 910 | data->reduced_tx_power = false; |
| 920 | 911 | iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false); | |
| 921 | /* ... and there is no need to get reports on RSSI any more. */ | ||
| 922 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | 912 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); |
| 923 | return; | 913 | return; |
| 924 | } | 914 | } |
| @@ -1022,9 +1012,9 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
| 1022 | 1012 | ||
| 1023 | /* Don't spam the fw with the same command over and over */ | 1013 | /* Don't spam the fw with the same command over and over */ |
| 1024 | if (memcmp(&cmd, &mvm->last_bt_ci_cmd, sizeof(cmd))) { | 1014 | if (memcmp(&cmd, &mvm->last_bt_ci_cmd, sizeof(cmd))) { |
| 1025 | if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, CMD_SYNC, | 1015 | if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, 0, |
| 1026 | sizeof(cmd), &cmd)) | 1016 | sizeof(cmd), &cmd)) |
| 1027 | IWL_ERR(mvm, "Failed to send BT_CI cmd"); | 1017 | IWL_ERR(mvm, "Failed to send BT_CI cmd\n"); |
| 1028 | memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); | 1018 | memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); |
| 1029 | } | 1019 | } |
| 1030 | 1020 | ||
| @@ -1039,7 +1029,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
| 1039 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | 1029 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); |
| 1040 | } | 1030 | } |
| 1041 | 1031 | ||
| 1042 | /* upon association, the fw will send in BT Coex notification */ | ||
| 1043 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | 1032 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, |
| 1044 | struct iwl_rx_cmd_buffer *rxb, | 1033 | struct iwl_rx_cmd_buffer *rxb, |
| 1045 | struct iwl_device_cmd *dev_cmd) | 1034 | struct iwl_device_cmd *dev_cmd) |
| @@ -1278,7 +1267,6 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, | |||
| 1278 | .id = BT_CONFIG, | 1267 | .id = BT_CONFIG, |
| 1279 | .len = { sizeof(*bt_cmd), }, | 1268 | .len = { sizeof(*bt_cmd), }, |
| 1280 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, | 1269 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, |
| 1281 | .flags = CMD_SYNC, | ||
| 1282 | }; | 1270 | }; |
| 1283 | 1271 | ||
| 1284 | if (!IWL_MVM_BT_COEX_CORUNNING) | 1272 | if (!IWL_MVM_BT_COEX_CORUNNING) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 7694472a303e..645b3cfc29a5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
| @@ -193,8 +193,7 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, | |||
| 193 | wkc.wep_key.key_offset = data->wep_key_idx; | 193 | wkc.wep_key.key_offset = data->wep_key_idx; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, CMD_SYNC, | 196 | ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, 0, sizeof(wkc), &wkc); |
| 197 | sizeof(wkc), &wkc); | ||
| 198 | data->error = ret != 0; | 197 | data->error = ret != 0; |
| 199 | 198 | ||
| 200 | mvm->ptk_ivlen = key->iv_len; | 199 | mvm->ptk_ivlen = key->iv_len; |
| @@ -341,7 +340,6 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm, | |||
| 341 | struct iwl_host_cmd cmd = { | 340 | struct iwl_host_cmd cmd = { |
| 342 | .id = WOWLAN_PATTERNS, | 341 | .id = WOWLAN_PATTERNS, |
| 343 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | 342 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, |
| 344 | .flags = CMD_SYNC, | ||
| 345 | }; | 343 | }; |
| 346 | int i, err; | 344 | int i, err; |
| 347 | 345 | ||
| @@ -518,7 +516,6 @@ static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm, | |||
| 518 | .id = REMOTE_WAKE_CONFIG_CMD, | 516 | .id = REMOTE_WAKE_CONFIG_CMD, |
| 519 | .len = { sizeof(*cfg), }, | 517 | .len = { sizeof(*cfg), }, |
| 520 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, | 518 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, |
| 521 | .flags = CMD_SYNC, | ||
| 522 | }; | 519 | }; |
| 523 | int ret; | 520 | int ret; |
| 524 | 521 | ||
| @@ -666,10 +663,8 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 666 | 663 | ||
| 667 | if (WARN_ON(!vif->bss_conf.assoc)) | 664 | if (WARN_ON(!vif->bss_conf.assoc)) |
| 668 | return -EINVAL; | 665 | return -EINVAL; |
| 669 | /* hack */ | 666 | |
| 670 | vif->bss_conf.assoc = false; | ||
| 671 | ret = iwl_mvm_mac_ctxt_add(mvm, vif); | 667 | ret = iwl_mvm_mac_ctxt_add(mvm, vif); |
| 672 | vif->bss_conf.assoc = true; | ||
| 673 | if (ret) | 668 | if (ret) |
| 674 | return ret; | 669 | return ret; |
| 675 | 670 | ||
| @@ -705,7 +700,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 705 | return ret; | 700 | return ret; |
| 706 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], ap_sta); | 701 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], ap_sta); |
| 707 | 702 | ||
| 708 | ret = iwl_mvm_mac_ctxt_changed(mvm, vif); | 703 | ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false); |
| 709 | if (ret) | 704 | if (ret) |
| 710 | return ret; | 705 | return ret; |
| 711 | 706 | ||
| @@ -719,7 +714,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 719 | for (i = 1; i < MAX_BINDINGS; i++) | 714 | for (i = 1; i < MAX_BINDINGS; i++) |
| 720 | quota_cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID); | 715 | quota_cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID); |
| 721 | 716 | ||
| 722 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC, | 717 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0, |
| 723 | sizeof(quota_cmd), "a_cmd); | 718 | sizeof(quota_cmd), "a_cmd); |
| 724 | if (ret) | 719 | if (ret) |
| 725 | IWL_ERR(mvm, "Failed to send quota: %d\n", ret); | 720 | IWL_ERR(mvm, "Failed to send quota: %d\n", ret); |
| @@ -739,7 +734,7 @@ static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm, | |||
| 739 | }; | 734 | }; |
| 740 | struct iwl_host_cmd cmd = { | 735 | struct iwl_host_cmd cmd = { |
| 741 | .id = NON_QOS_TX_COUNTER_CMD, | 736 | .id = NON_QOS_TX_COUNTER_CMD, |
| 742 | .flags = CMD_SYNC | CMD_WANT_SKB, | 737 | .flags = CMD_WANT_SKB, |
| 743 | }; | 738 | }; |
| 744 | int err; | 739 | int err; |
| 745 | u32 size; | 740 | u32 size; |
| @@ -781,7 +776,7 @@ void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 781 | 776 | ||
| 782 | mvmvif->seqno_valid = false; | 777 | mvmvif->seqno_valid = false; |
| 783 | 778 | ||
| 784 | if (iwl_mvm_send_cmd_pdu(mvm, NON_QOS_TX_COUNTER_CMD, CMD_SYNC, | 779 | if (iwl_mvm_send_cmd_pdu(mvm, NON_QOS_TX_COUNTER_CMD, 0, |
| 785 | sizeof(query_cmd), &query_cmd)) | 780 | sizeof(query_cmd), &query_cmd)) |
| 786 | IWL_ERR(mvm, "failed to set non-QoS seqno\n"); | 781 | IWL_ERR(mvm, "failed to set non-QoS seqno\n"); |
| 787 | } | 782 | } |
| @@ -796,7 +791,7 @@ iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm, | |||
| 796 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID) | 791 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID) |
| 797 | cmd_len = sizeof(*cmd); | 792 | cmd_len = sizeof(*cmd); |
| 798 | 793 | ||
| 799 | return iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, CMD_SYNC, | 794 | return iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0, |
| 800 | cmd_len, cmd); | 795 | cmd_len, cmd); |
| 801 | } | 796 | } |
| 802 | 797 | ||
| @@ -825,7 +820,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 825 | }; | 820 | }; |
| 826 | struct iwl_host_cmd d3_cfg_cmd = { | 821 | struct iwl_host_cmd d3_cfg_cmd = { |
| 827 | .id = D3_CONFIG_CMD, | 822 | .id = D3_CONFIG_CMD, |
| 828 | .flags = CMD_SYNC | CMD_WANT_SKB, | 823 | .flags = CMD_WANT_SKB, |
| 829 | .data[0] = &d3_cfg_cmd_data, | 824 | .data[0] = &d3_cfg_cmd_data, |
| 830 | .len[0] = sizeof(d3_cfg_cmd_data), | 825 | .len[0] = sizeof(d3_cfg_cmd_data), |
| 831 | }; | 826 | }; |
| @@ -975,7 +970,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 975 | if (key_data.use_rsc_tsc) { | 970 | if (key_data.use_rsc_tsc) { |
| 976 | struct iwl_host_cmd rsc_tsc_cmd = { | 971 | struct iwl_host_cmd rsc_tsc_cmd = { |
| 977 | .id = WOWLAN_TSC_RSC_PARAM, | 972 | .id = WOWLAN_TSC_RSC_PARAM, |
| 978 | .flags = CMD_SYNC, | ||
| 979 | .data[0] = key_data.rsc_tsc, | 973 | .data[0] = key_data.rsc_tsc, |
| 980 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | 974 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, |
| 981 | .len[0] = sizeof(*key_data.rsc_tsc), | 975 | .len[0] = sizeof(*key_data.rsc_tsc), |
| @@ -989,7 +983,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 989 | if (key_data.use_tkip) { | 983 | if (key_data.use_tkip) { |
| 990 | ret = iwl_mvm_send_cmd_pdu(mvm, | 984 | ret = iwl_mvm_send_cmd_pdu(mvm, |
| 991 | WOWLAN_TKIP_PARAM, | 985 | WOWLAN_TKIP_PARAM, |
| 992 | CMD_SYNC, sizeof(tkip_cmd), | 986 | 0, sizeof(tkip_cmd), |
| 993 | &tkip_cmd); | 987 | &tkip_cmd); |
| 994 | if (ret) | 988 | if (ret) |
| 995 | goto out; | 989 | goto out; |
| @@ -1006,8 +1000,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 1006 | kek_kck_cmd.replay_ctr = mvmvif->rekey_data.replay_ctr; | 1000 | kek_kck_cmd.replay_ctr = mvmvif->rekey_data.replay_ctr; |
| 1007 | 1001 | ||
| 1008 | ret = iwl_mvm_send_cmd_pdu(mvm, | 1002 | ret = iwl_mvm_send_cmd_pdu(mvm, |
| 1009 | WOWLAN_KEK_KCK_MATERIAL, | 1003 | WOWLAN_KEK_KCK_MATERIAL, 0, |
| 1010 | CMD_SYNC, | ||
| 1011 | sizeof(kek_kck_cmd), | 1004 | sizeof(kek_kck_cmd), |
| 1012 | &kek_kck_cmd); | 1005 | &kek_kck_cmd); |
| 1013 | if (ret) | 1006 | if (ret) |
| @@ -1023,7 +1016,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 1023 | if (ret) | 1016 | if (ret) |
| 1024 | goto out; | 1017 | goto out; |
| 1025 | 1018 | ||
| 1026 | ret = iwl_mvm_send_proto_offload(mvm, vif, false, CMD_SYNC); | 1019 | ret = iwl_mvm_send_proto_offload(mvm, vif, false, 0); |
| 1027 | if (ret) | 1020 | if (ret) |
| 1028 | goto out; | 1021 | goto out; |
| 1029 | 1022 | ||
| @@ -1035,7 +1028,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 1035 | if (ret) | 1028 | if (ret) |
| 1036 | goto out; | 1029 | goto out; |
| 1037 | 1030 | ||
| 1038 | ret = iwl_mvm_power_update_mac(mvm, vif); | 1031 | ret = iwl_mvm_power_update_mac(mvm); |
| 1039 | if (ret) | 1032 | if (ret) |
| 1040 | goto out; | 1033 | goto out; |
| 1041 | 1034 | ||
| @@ -1466,7 +1459,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1466 | } err_info; | 1459 | } err_info; |
| 1467 | struct iwl_host_cmd cmd = { | 1460 | struct iwl_host_cmd cmd = { |
| 1468 | .id = WOWLAN_GET_STATUSES, | 1461 | .id = WOWLAN_GET_STATUSES, |
| 1469 | .flags = CMD_SYNC | CMD_WANT_SKB, | 1462 | .flags = CMD_WANT_SKB, |
| 1470 | }; | 1463 | }; |
| 1471 | struct iwl_wowlan_status_data status; | 1464 | struct iwl_wowlan_status_data status; |
| 1472 | struct iwl_wowlan_status *fw_status; | 1465 | struct iwl_wowlan_status *fw_status; |
| @@ -1492,7 +1485,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1492 | } | 1485 | } |
| 1493 | 1486 | ||
| 1494 | /* only for tracing for now */ | 1487 | /* only for tracing for now */ |
| 1495 | ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, CMD_SYNC, 0, NULL); | 1488 | ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, 0, 0, NULL); |
| 1496 | if (ret) | 1489 | if (ret) |
| 1497 | IWL_ERR(mvm, "failed to query offload statistics (%d)\n", ret); | 1490 | IWL_ERR(mvm, "failed to query offload statistics (%d)\n", ret); |
| 1498 | 1491 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 6047cfdafb95..2e90ff795c13 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | |||
| @@ -175,7 +175,7 @@ static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf, | |||
| 175 | 175 | ||
| 176 | mutex_lock(&mvm->mutex); | 176 | mutex_lock(&mvm->mutex); |
| 177 | iwl_dbgfs_update_pm(mvm, vif, param, val); | 177 | iwl_dbgfs_update_pm(mvm, vif, param, val); |
| 178 | ret = iwl_mvm_power_update_mac(mvm, vif); | 178 | ret = iwl_mvm_power_update_mac(mvm); |
| 179 | mutex_unlock(&mvm->mutex); | 179 | mutex_unlock(&mvm->mutex); |
| 180 | 180 | ||
| 181 | return ret ?: count; | 181 | return ret ?: count; |
| @@ -262,10 +262,9 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file, | |||
| 262 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | 262 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
| 263 | 263 | ||
| 264 | pos += scnprintf(buf+pos, bufsz-pos, | 264 | pos += scnprintf(buf+pos, bufsz-pos, |
| 265 | "ap_sta_id %d - reduced Tx power %d force %d\n", | 265 | "ap_sta_id %d - reduced Tx power %d\n", |
| 266 | ap_sta_id, | 266 | ap_sta_id, |
| 267 | mvm_sta->bt_reduced_txpower, | 267 | mvm_sta->bt_reduced_txpower); |
| 268 | mvm_sta->bt_reduced_txpower_dbg); | ||
| 269 | } | 268 | } |
| 270 | } | 269 | } |
| 271 | 270 | ||
| @@ -283,41 +282,6 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file, | |||
| 283 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 282 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
| 284 | } | 283 | } |
| 285 | 284 | ||
| 286 | static ssize_t iwl_dbgfs_reduced_txp_write(struct ieee80211_vif *vif, | ||
| 287 | char *buf, size_t count, | ||
| 288 | loff_t *ppos) | ||
| 289 | { | ||
| 290 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 291 | struct iwl_mvm *mvm = mvmvif->mvm; | ||
| 292 | struct iwl_mvm_sta *mvmsta; | ||
| 293 | bool reduced_tx_power; | ||
| 294 | int ret; | ||
| 295 | |||
| 296 | if (mvmvif->ap_sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id)) | ||
| 297 | return -ENOTCONN; | ||
| 298 | |||
| 299 | if (strtobool(buf, &reduced_tx_power) != 0) | ||
| 300 | return -EINVAL; | ||
| 301 | |||
| 302 | mutex_lock(&mvm->mutex); | ||
| 303 | |||
| 304 | mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id); | ||
| 305 | if (IS_ERR_OR_NULL(mvmsta)) { | ||
| 306 | mutex_unlock(&mvm->mutex); | ||
| 307 | return -ENOTCONN; | ||
| 308 | } | ||
| 309 | |||
| 310 | mvmsta->bt_reduced_txpower_dbg = false; | ||
| 311 | ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, | ||
| 312 | reduced_tx_power); | ||
| 313 | if (!ret) | ||
| 314 | mvmsta->bt_reduced_txpower_dbg = true; | ||
| 315 | |||
| 316 | mutex_unlock(&mvm->mutex); | ||
| 317 | |||
| 318 | return ret ? : count; | ||
| 319 | } | ||
| 320 | |||
| 321 | static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif, | 285 | static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif, |
| 322 | enum iwl_dbgfs_bf_mask param, int value) | 286 | enum iwl_dbgfs_bf_mask param, int value) |
| 323 | { | 287 | { |
| @@ -452,9 +416,9 @@ static ssize_t iwl_dbgfs_bf_params_write(struct ieee80211_vif *vif, char *buf, | |||
| 452 | mutex_lock(&mvm->mutex); | 416 | mutex_lock(&mvm->mutex); |
| 453 | iwl_dbgfs_update_bf(vif, param, value); | 417 | iwl_dbgfs_update_bf(vif, param, value); |
| 454 | if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) | 418 | if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) |
| 455 | ret = iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC); | 419 | ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); |
| 456 | else | 420 | else |
| 457 | ret = iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC); | 421 | ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0); |
| 458 | mutex_unlock(&mvm->mutex); | 422 | mutex_unlock(&mvm->mutex); |
| 459 | 423 | ||
| 460 | return ret ?: count; | 424 | return ret ?: count; |
| @@ -558,7 +522,6 @@ MVM_DEBUGFS_READ_FILE_OPS(mac_params); | |||
| 558 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32); | 522 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32); |
| 559 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256); | 523 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256); |
| 560 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10); | 524 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10); |
| 561 | MVM_DEBUGFS_WRITE_FILE_OPS(reduced_txp, 10); | ||
| 562 | 525 | ||
| 563 | void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 526 | void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
| 564 | { | 527 | { |
| @@ -590,7 +553,6 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 590 | S_IRUSR); | 553 | S_IRUSR); |
| 591 | 554 | ||
| 592 | MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR); | 555 | MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR); |
| 593 | MVM_DEBUGFS_ADD_FILE_VIF(reduced_txp, mvmvif->dbgfs_dir, S_IWUSR); | ||
| 594 | MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir, | 556 | MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir, |
| 595 | S_IRUSR | S_IWUSR); | 557 | S_IRUSR | S_IWUSR); |
| 596 | 558 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index f462c9baa2b5..29ca72695eaa 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
| @@ -65,9 +65,8 @@ | |||
| 65 | #include "mvm.h" | 65 | #include "mvm.h" |
| 66 | #include "sta.h" | 66 | #include "sta.h" |
| 67 | #include "iwl-io.h" | 67 | #include "iwl-io.h" |
| 68 | #include "iwl-prph.h" | ||
| 69 | #include "debugfs.h" | 68 | #include "debugfs.h" |
| 70 | #include "fw-error-dump.h" | 69 | #include "iwl-fw-error-dump.h" |
| 71 | 70 | ||
| 72 | static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, | 71 | static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, |
| 73 | size_t count, loff_t *ppos) | 72 | size_t count, loff_t *ppos) |
| @@ -681,7 +680,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, | |||
| 681 | mvm->restart_fw++; | 680 | mvm->restart_fw++; |
| 682 | 681 | ||
| 683 | /* take the return value to make compiler happy - it will fail anyway */ | 682 | /* take the return value to make compiler happy - it will fail anyway */ |
| 684 | ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL); | 683 | ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, 0, 0, NULL); |
| 685 | 684 | ||
| 686 | mutex_unlock(&mvm->mutex); | 685 | mutex_unlock(&mvm->mutex); |
| 687 | 686 | ||
| @@ -691,7 +690,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, | |||
| 691 | static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf, | 690 | static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf, |
| 692 | size_t count, loff_t *ppos) | 691 | size_t count, loff_t *ppos) |
| 693 | { | 692 | { |
| 694 | iwl_write_prph(mvm->trans, DEVICE_SET_NMI_REG, 1); | 693 | iwl_force_nmi(mvm->trans); |
| 695 | 694 | ||
| 696 | return count; | 695 | return count; |
| 697 | } | 696 | } |
| @@ -838,7 +837,7 @@ static ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf, | |||
| 838 | /* send updated bcast filtering configuration */ | 837 | /* send updated bcast filtering configuration */ |
| 839 | if (mvm->dbgfs_bcast_filtering.override && | 838 | if (mvm->dbgfs_bcast_filtering.override && |
| 840 | iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) | 839 | iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) |
| 841 | err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC, | 840 | err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0, |
| 842 | sizeof(cmd), &cmd); | 841 | sizeof(cmd), &cmd); |
| 843 | mutex_unlock(&mvm->mutex); | 842 | mutex_unlock(&mvm->mutex); |
| 844 | 843 | ||
| @@ -910,7 +909,7 @@ static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm, | |||
| 910 | /* send updated bcast filtering configuration */ | 909 | /* send updated bcast filtering configuration */ |
| 911 | if (mvm->dbgfs_bcast_filtering.override && | 910 | if (mvm->dbgfs_bcast_filtering.override && |
| 912 | iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) | 911 | iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) |
| 913 | err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC, | 912 | err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0, |
| 914 | sizeof(cmd), &cmd); | 913 | sizeof(cmd), &cmd); |
| 915 | mutex_unlock(&mvm->mutex); | 914 | mutex_unlock(&mvm->mutex); |
| 916 | 915 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 3d99cf564ba6..883e702152d5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
| @@ -99,7 +99,7 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant) | |||
| 99 | }; | 99 | }; |
| 100 | 100 | ||
| 101 | IWL_DEBUG_FW(mvm, "select valid tx ant: %u\n", valid_tx_ant); | 101 | IWL_DEBUG_FW(mvm, "select valid tx ant: %u\n", valid_tx_ant); |
| 102 | return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC, | 102 | return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, 0, |
| 103 | sizeof(tx_ant_cmd), &tx_ant_cmd); | 103 | sizeof(tx_ant_cmd), &tx_ant_cmd); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| @@ -137,6 +137,8 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | |||
| 137 | alive_data->scd_base_addr = le32_to_cpu(palive2->scd_base_ptr); | 137 | alive_data->scd_base_addr = le32_to_cpu(palive2->scd_base_ptr); |
| 138 | mvm->umac_error_event_table = | 138 | mvm->umac_error_event_table = |
| 139 | le32_to_cpu(palive2->error_info_addr); | 139 | le32_to_cpu(palive2->error_info_addr); |
| 140 | mvm->sf_space.addr = le32_to_cpu(palive2->st_fwrd_addr); | ||
| 141 | mvm->sf_space.size = le32_to_cpu(palive2->st_fwrd_size); | ||
| 140 | 142 | ||
| 141 | alive_data->valid = le16_to_cpu(palive2->status) == | 143 | alive_data->valid = le16_to_cpu(palive2->status) == |
| 142 | IWL_ALIVE_STATUS_OK; | 144 | IWL_ALIVE_STATUS_OK; |
| @@ -180,6 +182,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
| 180 | int ret, i; | 182 | int ret, i; |
| 181 | enum iwl_ucode_type old_type = mvm->cur_ucode; | 183 | enum iwl_ucode_type old_type = mvm->cur_ucode; |
| 182 | static const u8 alive_cmd[] = { MVM_ALIVE }; | 184 | static const u8 alive_cmd[] = { MVM_ALIVE }; |
| 185 | struct iwl_sf_region st_fwrd_space; | ||
| 183 | 186 | ||
| 184 | fw = iwl_get_ucode_image(mvm, ucode_type); | 187 | fw = iwl_get_ucode_image(mvm, ucode_type); |
| 185 | if (WARN_ON(!fw)) | 188 | if (WARN_ON(!fw)) |
| @@ -215,6 +218,14 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
| 215 | return -EIO; | 218 | return -EIO; |
| 216 | } | 219 | } |
| 217 | 220 | ||
| 221 | /* | ||
| 222 | * update the sdio allocation according to the pointer we get in the | ||
| 223 | * alive notification. | ||
| 224 | */ | ||
| 225 | st_fwrd_space.addr = mvm->sf_space.addr; | ||
| 226 | st_fwrd_space.size = mvm->sf_space.size; | ||
| 227 | ret = iwl_trans_update_sf(mvm->trans, &st_fwrd_space); | ||
| 228 | |||
| 218 | iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr); | 229 | iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr); |
| 219 | 230 | ||
| 220 | /* | 231 | /* |
| @@ -256,7 +267,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) | |||
| 256 | IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n", | 267 | IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n", |
| 257 | phy_cfg_cmd.phy_cfg); | 268 | phy_cfg_cmd.phy_cfg); |
| 258 | 269 | ||
| 259 | return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, CMD_SYNC, | 270 | return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, 0, |
| 260 | sizeof(phy_cfg_cmd), &phy_cfg_cmd); | 271 | sizeof(phy_cfg_cmd), &phy_cfg_cmd); |
| 261 | } | 272 | } |
| 262 | 273 | ||
| @@ -295,7 +306,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
| 295 | /* Read the NVM only at driver load time, no need to do this twice */ | 306 | /* Read the NVM only at driver load time, no need to do this twice */ |
| 296 | if (read_nvm) { | 307 | if (read_nvm) { |
| 297 | /* Read nvm */ | 308 | /* Read nvm */ |
| 298 | ret = iwl_nvm_init(mvm); | 309 | ret = iwl_nvm_init(mvm, true); |
| 299 | if (ret) { | 310 | if (ret) { |
| 300 | IWL_ERR(mvm, "Failed to read NVM: %d\n", ret); | 311 | IWL_ERR(mvm, "Failed to read NVM: %d\n", ret); |
| 301 | goto error; | 312 | goto error; |
| @@ -303,7 +314,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
| 303 | } | 314 | } |
| 304 | 315 | ||
| 305 | /* In case we read the NVM from external file, load it to the NIC */ | 316 | /* In case we read the NVM from external file, load it to the NIC */ |
| 306 | if (iwlwifi_mod_params.nvm_file) | 317 | if (mvm->nvm_file_name) |
| 307 | iwl_mvm_load_nvm_to_nic(mvm); | 318 | iwl_mvm_load_nvm_to_nic(mvm); |
| 308 | 319 | ||
| 309 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); | 320 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 7110ec2605d6..8b5302777632 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
| @@ -685,7 +685,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, | |||
| 685 | static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm, | 685 | static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm, |
| 686 | struct iwl_mac_ctx_cmd *cmd) | 686 | struct iwl_mac_ctx_cmd *cmd) |
| 687 | { | 687 | { |
| 688 | int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, CMD_SYNC, | 688 | int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0, |
| 689 | sizeof(*cmd), cmd); | 689 | sizeof(*cmd), cmd); |
| 690 | if (ret) | 690 | if (ret) |
| 691 | IWL_ERR(mvm, "Failed to send MAC context (action:%d): %d\n", | 691 | IWL_ERR(mvm, "Failed to send MAC context (action:%d): %d\n", |
| @@ -693,19 +693,39 @@ static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm, | |||
| 693 | return ret; | 693 | return ret; |
| 694 | } | 694 | } |
| 695 | 695 | ||
| 696 | /* | 696 | static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, |
| 697 | * Fill the specific data for mac context of type station or p2p client | 697 | struct ieee80211_vif *vif, |
| 698 | */ | 698 | u32 action, bool force_assoc_off) |
| 699 | static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm, | ||
| 700 | struct ieee80211_vif *vif, | ||
| 701 | struct iwl_mac_data_sta *ctxt_sta, | ||
| 702 | bool force_assoc_off) | ||
| 703 | { | 699 | { |
| 700 | struct iwl_mac_ctx_cmd cmd = {}; | ||
| 701 | struct iwl_mac_data_sta *ctxt_sta; | ||
| 702 | |||
| 703 | WARN_ON(vif->type != NL80211_IFTYPE_STATION); | ||
| 704 | |||
| 705 | /* Fill the common data for all mac context types */ | ||
| 706 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | ||
| 707 | |||
| 708 | if (vif->p2p) { | ||
| 709 | struct ieee80211_p2p_noa_attr *noa = | ||
| 710 | &vif->bss_conf.p2p_noa_attr; | ||
| 711 | |||
| 712 | cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow & | ||
| 713 | IEEE80211_P2P_OPPPS_CTWINDOW_MASK); | ||
| 714 | ctxt_sta = &cmd.p2p_sta.sta; | ||
| 715 | } else { | ||
| 716 | ctxt_sta = &cmd.sta; | ||
| 717 | } | ||
| 718 | |||
| 704 | /* We need the dtim_period to set the MAC as associated */ | 719 | /* We need the dtim_period to set the MAC as associated */ |
| 705 | if (vif->bss_conf.assoc && vif->bss_conf.dtim_period && | 720 | if (vif->bss_conf.assoc && vif->bss_conf.dtim_period && |
| 706 | !force_assoc_off) { | 721 | !force_assoc_off) { |
| 707 | u32 dtim_offs; | 722 | u32 dtim_offs; |
| 708 | 723 | ||
| 724 | /* Allow beacons to pass through as long as we are not | ||
| 725 | * associated, or we do not have dtim period information. | ||
| 726 | */ | ||
| 727 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON); | ||
| 728 | |||
| 709 | /* | 729 | /* |
| 710 | * The DTIM count counts down, so when it is N that means N | 730 | * The DTIM count counts down, so when it is N that means N |
| 711 | * more beacon intervals happen until the DTIM TBTT. Therefore | 731 | * more beacon intervals happen until the DTIM TBTT. Therefore |
| @@ -752,51 +772,6 @@ static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm, | |||
| 752 | 772 | ||
| 753 | ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval); | 773 | ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval); |
| 754 | ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid); | 774 | ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid); |
| 755 | } | ||
| 756 | |||
| 757 | static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm, | ||
| 758 | struct ieee80211_vif *vif, | ||
| 759 | u32 action) | ||
| 760 | { | ||
| 761 | struct iwl_mac_ctx_cmd cmd = {}; | ||
| 762 | |||
| 763 | WARN_ON(vif->type != NL80211_IFTYPE_STATION || vif->p2p); | ||
| 764 | |||
| 765 | /* Fill the common data for all mac context types */ | ||
| 766 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | ||
| 767 | |||
| 768 | /* Allow beacons to pass through as long as we are not associated,or we | ||
| 769 | * do not have dtim period information */ | ||
| 770 | if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period) | ||
| 771 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON); | ||
| 772 | else | ||
| 773 | cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON); | ||
| 774 | |||
| 775 | /* Fill the data specific for station mode */ | ||
| 776 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta, | ||
| 777 | action == FW_CTXT_ACTION_ADD); | ||
| 778 | |||
| 779 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | ||
| 780 | } | ||
| 781 | |||
| 782 | static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm, | ||
| 783 | struct ieee80211_vif *vif, | ||
| 784 | u32 action) | ||
| 785 | { | ||
| 786 | struct iwl_mac_ctx_cmd cmd = {}; | ||
| 787 | struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr; | ||
| 788 | |||
| 789 | WARN_ON(vif->type != NL80211_IFTYPE_STATION || !vif->p2p); | ||
| 790 | |||
| 791 | /* Fill the common data for all mac context types */ | ||
| 792 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | ||
| 793 | |||
| 794 | /* Fill the data specific for station mode */ | ||
| 795 | iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta, | ||
| 796 | action == FW_CTXT_ACTION_ADD); | ||
| 797 | |||
| 798 | cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow & | ||
| 799 | IEEE80211_P2P_OPPPS_CTWINDOW_MASK); | ||
| 800 | 775 | ||
| 801 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 776 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
| 802 | } | 777 | } |
| @@ -1134,16 +1109,12 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm, | |||
| 1134 | } | 1109 | } |
| 1135 | 1110 | ||
| 1136 | static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 1111 | static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| 1137 | u32 action) | 1112 | u32 action, bool force_assoc_off) |
| 1138 | { | 1113 | { |
| 1139 | switch (vif->type) { | 1114 | switch (vif->type) { |
| 1140 | case NL80211_IFTYPE_STATION: | 1115 | case NL80211_IFTYPE_STATION: |
| 1141 | if (!vif->p2p) | 1116 | return iwl_mvm_mac_ctxt_cmd_sta(mvm, vif, action, |
| 1142 | return iwl_mvm_mac_ctxt_cmd_station(mvm, vif, | 1117 | force_assoc_off); |
| 1143 | action); | ||
| 1144 | else | ||
| 1145 | return iwl_mvm_mac_ctxt_cmd_p2p_client(mvm, vif, | ||
| 1146 | action); | ||
| 1147 | break; | 1118 | break; |
| 1148 | case NL80211_IFTYPE_AP: | 1119 | case NL80211_IFTYPE_AP: |
| 1149 | if (!vif->p2p) | 1120 | if (!vif->p2p) |
| @@ -1173,7 +1144,8 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 1173 | vif->addr, ieee80211_vif_type_p2p(vif))) | 1144 | vif->addr, ieee80211_vif_type_p2p(vif))) |
| 1174 | return -EIO; | 1145 | return -EIO; |
| 1175 | 1146 | ||
| 1176 | ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD); | 1147 | ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD, |
| 1148 | true); | ||
| 1177 | if (ret) | 1149 | if (ret) |
| 1178 | return ret; | 1150 | return ret; |
| 1179 | 1151 | ||
| @@ -1184,7 +1156,8 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 1184 | return 0; | 1156 | return 0; |
| 1185 | } | 1157 | } |
| 1186 | 1158 | ||
| 1187 | int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 1159 | int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| 1160 | bool force_assoc_off) | ||
| 1188 | { | 1161 | { |
| 1189 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 1162 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 1190 | 1163 | ||
| @@ -1192,7 +1165,8 @@ int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 1192 | vif->addr, ieee80211_vif_type_p2p(vif))) | 1165 | vif->addr, ieee80211_vif_type_p2p(vif))) |
| 1193 | return -EIO; | 1166 | return -EIO; |
| 1194 | 1167 | ||
| 1195 | return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY); | 1168 | return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY, |
| 1169 | force_assoc_off); | ||
| 1196 | } | 1170 | } |
| 1197 | 1171 | ||
| 1198 | int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 1172 | int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
| @@ -1211,7 +1185,7 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 1211 | mvmvif->color)); | 1185 | mvmvif->color)); |
| 1212 | cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE); | 1186 | cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE); |
| 1213 | 1187 | ||
| 1214 | ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, CMD_SYNC, | 1188 | ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0, |
| 1215 | sizeof(cmd), &cmd); | 1189 | sizeof(cmd), &cmd); |
| 1216 | if (ret) { | 1190 | if (ret) { |
| 1217 | IWL_ERR(mvm, "Failed to remove MAC context: %d\n", ret); | 1191 | IWL_ERR(mvm, "Failed to remove MAC context: %d\n", ret); |
| @@ -1237,11 +1211,23 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | |||
| 1237 | u32 rate __maybe_unused = | 1211 | u32 rate __maybe_unused = |
| 1238 | le32_to_cpu(beacon->beacon_notify_hdr.initial_rate); | 1212 | le32_to_cpu(beacon->beacon_notify_hdr.initial_rate); |
| 1239 | 1213 | ||
| 1214 | lockdep_assert_held(&mvm->mutex); | ||
| 1215 | |||
| 1240 | IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n", | 1216 | IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n", |
| 1241 | status & TX_STATUS_MSK, | 1217 | status & TX_STATUS_MSK, |
| 1242 | beacon->beacon_notify_hdr.failure_frame, | 1218 | beacon->beacon_notify_hdr.failure_frame, |
| 1243 | le64_to_cpu(beacon->tsf), | 1219 | le64_to_cpu(beacon->tsf), |
| 1244 | rate); | 1220 | rate); |
| 1221 | |||
| 1222 | if (unlikely(mvm->csa_vif && mvm->csa_vif->csa_active)) { | ||
| 1223 | if (!ieee80211_csa_is_complete(mvm->csa_vif)) { | ||
| 1224 | iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm->csa_vif); | ||
| 1225 | } else { | ||
| 1226 | ieee80211_csa_finish(mvm->csa_vif); | ||
| 1227 | mvm->csa_vif = NULL; | ||
| 1228 | } | ||
| 1229 | } | ||
| 1230 | |||
| 1245 | return 0; | 1231 | return 0; |
| 1246 | } | 1232 | } |
| 1247 | 1233 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 32682edfe5a4..7215f5980186 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
| @@ -276,7 +276,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 276 | IEEE80211_HW_AMPDU_AGGREGATION | | 276 | IEEE80211_HW_AMPDU_AGGREGATION | |
| 277 | IEEE80211_HW_TIMING_BEACON_ONLY | | 277 | IEEE80211_HW_TIMING_BEACON_ONLY | |
| 278 | IEEE80211_HW_CONNECTION_MONITOR | | 278 | IEEE80211_HW_CONNECTION_MONITOR | |
| 279 | IEEE80211_HW_SUPPORTS_UAPSD | | ||
| 280 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 279 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
| 281 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | 280 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; |
| 282 | 281 | ||
| @@ -286,8 +285,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 286 | IEEE80211_RADIOTAP_MCS_HAVE_STBC; | 285 | IEEE80211_RADIOTAP_MCS_HAVE_STBC; |
| 287 | hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC; | 286 | hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC; |
| 288 | hw->rate_control_algorithm = "iwl-mvm-rs"; | 287 | hw->rate_control_algorithm = "iwl-mvm-rs"; |
| 289 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; | ||
| 290 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
| 291 | 288 | ||
| 292 | /* | 289 | /* |
| 293 | * Enable 11w if advertised by firmware and software crypto | 290 | * Enable 11w if advertised by firmware and software crypto |
| @@ -298,9 +295,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 298 | !iwlwifi_mod_params.sw_crypto) | 295 | !iwlwifi_mod_params.sw_crypto) |
| 299 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | 296 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; |
| 300 | 297 | ||
| 301 | /* Disable uAPSD due to firmware issues */ | 298 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT && |
| 302 | if (true) | 299 | IWL_UCODE_API(mvm->fw->ucode_ver) >= 9 && |
| 303 | hw->flags &= ~IEEE80211_HW_SUPPORTS_UAPSD; | 300 | !iwlwifi_mod_params.uapsd_disable) { |
| 301 | hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD; | ||
| 302 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; | ||
| 303 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
| 304 | } | ||
| 304 | 305 | ||
| 305 | hw->sta_data_size = sizeof(struct iwl_mvm_sta); | 306 | hw->sta_data_size = sizeof(struct iwl_mvm_sta); |
| 306 | hw->vif_data_size = sizeof(struct iwl_mvm_vif); | 307 | hw->vif_data_size = sizeof(struct iwl_mvm_vif); |
| @@ -320,6 +321,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 320 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD) | 321 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD) |
| 321 | hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; | 322 | hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; |
| 322 | 323 | ||
| 324 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_CSA_FLOW) | ||
| 325 | hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; | ||
| 326 | |||
| 323 | hw->wiphy->iface_combinations = iwl_mvm_iface_combinations; | 327 | hw->wiphy->iface_combinations = iwl_mvm_iface_combinations; |
| 324 | hw->wiphy->n_iface_combinations = | 328 | hw->wiphy->n_iface_combinations = |
| 325 | ARRAY_SIZE(iwl_mvm_iface_combinations); | 329 | ARRAY_SIZE(iwl_mvm_iface_combinations); |
| @@ -539,13 +543,22 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
| 539 | return -EACCES; | 543 | return -EACCES; |
| 540 | 544 | ||
| 541 | /* return from D0i3 before starting a new Tx aggregation */ | 545 | /* return from D0i3 before starting a new Tx aggregation */ |
| 542 | if (action == IEEE80211_AMPDU_TX_START) { | 546 | switch (action) { |
| 547 | case IEEE80211_AMPDU_TX_START: | ||
| 548 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
| 549 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
| 550 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
| 551 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
| 543 | iwl_mvm_ref(mvm, IWL_MVM_REF_TX_AGG); | 552 | iwl_mvm_ref(mvm, IWL_MVM_REF_TX_AGG); |
| 544 | tx_agg_ref = true; | 553 | tx_agg_ref = true; |
| 545 | 554 | ||
| 546 | /* | 555 | /* |
| 547 | * wait synchronously until D0i3 exit to get the correct | 556 | * for tx start, wait synchronously until D0i3 exit to |
| 548 | * sequence number for the tid | 557 | * get the correct sequence number for the tid. |
| 558 | * additionally, some other ampdu actions use direct | ||
| 559 | * target access, which is not handled automatically | ||
| 560 | * by the trans layer (unlike commands), so wait for | ||
| 561 | * d0i3 exit in these cases as well. | ||
| 549 | */ | 562 | */ |
| 550 | if (!wait_event_timeout(mvm->d0i3_exit_waitq, | 563 | if (!wait_event_timeout(mvm->d0i3_exit_waitq, |
| 551 | !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status), HZ)) { | 564 | !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status), HZ)) { |
| @@ -553,6 +566,9 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
| 553 | iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG); | 566 | iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG); |
| 554 | return -EIO; | 567 | return -EIO; |
| 555 | } | 568 | } |
| 569 | break; | ||
| 570 | default: | ||
| 571 | break; | ||
| 556 | } | 572 | } |
| 557 | 573 | ||
| 558 | mutex_lock(&mvm->mutex); | 574 | mutex_lock(&mvm->mutex); |
| @@ -757,7 +773,7 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 757 | .pwr_restriction = cpu_to_le16(tx_power), | 773 | .pwr_restriction = cpu_to_le16(tx_power), |
| 758 | }; | 774 | }; |
| 759 | 775 | ||
| 760 | return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC, | 776 | return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, |
| 761 | sizeof(reduce_txpwr_cmd), | 777 | sizeof(reduce_txpwr_cmd), |
| 762 | &reduce_txpwr_cmd); | 778 | &reduce_txpwr_cmd); |
| 763 | } | 779 | } |
| @@ -816,12 +832,12 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
| 816 | if (ret) | 832 | if (ret) |
| 817 | goto out_release; | 833 | goto out_release; |
| 818 | 834 | ||
| 819 | ret = iwl_mvm_power_update_mac(mvm, vif); | 835 | ret = iwl_mvm_power_update_mac(mvm); |
| 820 | if (ret) | 836 | if (ret) |
| 821 | goto out_release; | 837 | goto out_release; |
| 822 | 838 | ||
| 823 | /* beacon filtering */ | 839 | /* beacon filtering */ |
| 824 | ret = iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC); | 840 | ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); |
| 825 | if (ret) | 841 | if (ret) |
| 826 | goto out_remove_mac; | 842 | goto out_remove_mac; |
| 827 | 843 | ||
| @@ -967,7 +983,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
| 967 | if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE) | 983 | if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE) |
| 968 | mvm->vif_count--; | 984 | mvm->vif_count--; |
| 969 | 985 | ||
| 970 | iwl_mvm_power_update_mac(mvm, vif); | 986 | iwl_mvm_power_update_mac(mvm); |
| 971 | iwl_mvm_mac_ctxt_remove(mvm, vif); | 987 | iwl_mvm_mac_ctxt_remove(mvm, vif); |
| 972 | 988 | ||
| 973 | out_release: | 989 | out_release: |
| @@ -1228,7 +1244,7 @@ static int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm, | |||
| 1228 | if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) | 1244 | if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) |
| 1229 | return 0; | 1245 | return 0; |
| 1230 | 1246 | ||
| 1231 | return iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC, | 1247 | return iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0, |
| 1232 | sizeof(cmd), &cmd); | 1248 | sizeof(cmd), &cmd); |
| 1233 | } | 1249 | } |
| 1234 | #else | 1250 | #else |
| @@ -1255,7 +1271,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 1255 | if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) | 1271 | if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) |
| 1256 | iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif); | 1272 | iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif); |
| 1257 | 1273 | ||
| 1258 | ret = iwl_mvm_mac_ctxt_changed(mvm, vif); | 1274 | ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false); |
| 1259 | if (ret) | 1275 | if (ret) |
| 1260 | IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr); | 1276 | IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr); |
| 1261 | 1277 | ||
| @@ -1335,10 +1351,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 1335 | iwl_mvm_remove_time_event(mvm, mvmvif, | 1351 | iwl_mvm_remove_time_event(mvm, mvmvif, |
| 1336 | &mvmvif->time_event_data); | 1352 | &mvmvif->time_event_data); |
| 1337 | iwl_mvm_sf_update(mvm, vif, false); | 1353 | iwl_mvm_sf_update(mvm, vif, false); |
| 1338 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC)); | 1354 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); |
| 1339 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | | 1355 | } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | |
| 1340 | BSS_CHANGED_QOS)) { | 1356 | BSS_CHANGED_QOS)) { |
| 1341 | ret = iwl_mvm_power_update_mac(mvm, vif); | 1357 | ret = iwl_mvm_power_update_mac(mvm); |
| 1342 | if (ret) | 1358 | if (ret) |
| 1343 | IWL_ERR(mvm, "failed to update power mode\n"); | 1359 | IWL_ERR(mvm, "failed to update power mode\n"); |
| 1344 | } | 1360 | } |
| @@ -1349,16 +1365,19 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 1349 | } | 1365 | } |
| 1350 | 1366 | ||
| 1351 | if (changes & BSS_CHANGED_CQM) { | 1367 | if (changes & BSS_CHANGED_CQM) { |
| 1352 | IWL_DEBUG_MAC80211(mvm, "cqm info_changed"); | 1368 | IWL_DEBUG_MAC80211(mvm, "cqm info_changed\n"); |
| 1353 | /* reset cqm events tracking */ | 1369 | /* reset cqm events tracking */ |
| 1354 | mvmvif->bf_data.last_cqm_event = 0; | 1370 | mvmvif->bf_data.last_cqm_event = 0; |
| 1355 | ret = iwl_mvm_update_beacon_filter(mvm, vif, false, CMD_SYNC); | 1371 | if (mvmvif->bf_data.bf_enabled) { |
| 1356 | if (ret) | 1372 | ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0); |
| 1357 | IWL_ERR(mvm, "failed to update CQM thresholds\n"); | 1373 | if (ret) |
| 1374 | IWL_ERR(mvm, | ||
| 1375 | "failed to update CQM thresholds\n"); | ||
| 1376 | } | ||
| 1358 | } | 1377 | } |
| 1359 | 1378 | ||
| 1360 | if (changes & BSS_CHANGED_ARP_FILTER) { | 1379 | if (changes & BSS_CHANGED_ARP_FILTER) { |
| 1361 | IWL_DEBUG_MAC80211(mvm, "arp filter changed"); | 1380 | IWL_DEBUG_MAC80211(mvm, "arp filter changed\n"); |
| 1362 | iwl_mvm_configure_bcast_filter(mvm, vif); | 1381 | iwl_mvm_configure_bcast_filter(mvm, vif); |
| 1363 | } | 1382 | } |
| 1364 | } | 1383 | } |
| @@ -1404,7 +1423,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
| 1404 | mvmvif->ap_ibss_active = true; | 1423 | mvmvif->ap_ibss_active = true; |
| 1405 | 1424 | ||
| 1406 | /* power updated needs to be done before quotas */ | 1425 | /* power updated needs to be done before quotas */ |
| 1407 | iwl_mvm_power_update_mac(mvm, vif); | 1426 | iwl_mvm_power_update_mac(mvm); |
| 1408 | 1427 | ||
| 1409 | ret = iwl_mvm_update_quotas(mvm, vif); | 1428 | ret = iwl_mvm_update_quotas(mvm, vif); |
| 1410 | if (ret) | 1429 | if (ret) |
| @@ -1412,7 +1431,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
| 1412 | 1431 | ||
| 1413 | /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ | 1432 | /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ |
| 1414 | if (vif->p2p && mvm->p2p_device_vif) | 1433 | if (vif->p2p && mvm->p2p_device_vif) |
| 1415 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif); | 1434 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false); |
| 1416 | 1435 | ||
| 1417 | iwl_mvm_ref(mvm, IWL_MVM_REF_AP_IBSS); | 1436 | iwl_mvm_ref(mvm, IWL_MVM_REF_AP_IBSS); |
| 1418 | 1437 | ||
| @@ -1422,7 +1441,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
| 1422 | return 0; | 1441 | return 0; |
| 1423 | 1442 | ||
| 1424 | out_quota_failed: | 1443 | out_quota_failed: |
| 1425 | iwl_mvm_power_update_mac(mvm, vif); | 1444 | iwl_mvm_power_update_mac(mvm); |
| 1426 | mvmvif->ap_ibss_active = false; | 1445 | mvmvif->ap_ibss_active = false; |
| 1427 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); | 1446 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); |
| 1428 | out_unbind: | 1447 | out_unbind: |
| @@ -1452,13 +1471,13 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, | |||
| 1452 | 1471 | ||
| 1453 | /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ | 1472 | /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ |
| 1454 | if (vif->p2p && mvm->p2p_device_vif) | 1473 | if (vif->p2p && mvm->p2p_device_vif) |
| 1455 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif); | 1474 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false); |
| 1456 | 1475 | ||
| 1457 | iwl_mvm_update_quotas(mvm, NULL); | 1476 | iwl_mvm_update_quotas(mvm, NULL); |
| 1458 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); | 1477 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); |
| 1459 | iwl_mvm_binding_remove_vif(mvm, vif); | 1478 | iwl_mvm_binding_remove_vif(mvm, vif); |
| 1460 | 1479 | ||
| 1461 | iwl_mvm_power_update_mac(mvm, vif); | 1480 | iwl_mvm_power_update_mac(mvm); |
| 1462 | 1481 | ||
| 1463 | iwl_mvm_mac_ctxt_remove(mvm, vif); | 1482 | iwl_mvm_mac_ctxt_remove(mvm, vif); |
| 1464 | 1483 | ||
| @@ -1479,7 +1498,7 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm, | |||
| 1479 | 1498 | ||
| 1480 | if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT | | 1499 | if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT | |
| 1481 | BSS_CHANGED_BANDWIDTH) && | 1500 | BSS_CHANGED_BANDWIDTH) && |
| 1482 | iwl_mvm_mac_ctxt_changed(mvm, vif)) | 1501 | iwl_mvm_mac_ctxt_changed(mvm, vif, false)) |
| 1483 | IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr); | 1502 | IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr); |
| 1484 | 1503 | ||
| 1485 | /* Need to send a new beacon template to the FW */ | 1504 | /* Need to send a new beacon template to the FW */ |
| @@ -1497,6 +1516,9 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1497 | 1516 | ||
| 1498 | mutex_lock(&mvm->mutex); | 1517 | mutex_lock(&mvm->mutex); |
| 1499 | 1518 | ||
| 1519 | if (changes & BSS_CHANGED_IDLE && !bss_conf->idle) | ||
| 1520 | iwl_mvm_sched_scan_stop(mvm, true); | ||
| 1521 | |||
| 1500 | switch (vif->type) { | 1522 | switch (vif->type) { |
| 1501 | case NL80211_IFTYPE_STATION: | 1523 | case NL80211_IFTYPE_STATION: |
| 1502 | iwl_mvm_bss_info_changed_station(mvm, vif, bss_conf, changes); | 1524 | iwl_mvm_bss_info_changed_station(mvm, vif, bss_conf, changes); |
| @@ -1527,7 +1549,7 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | |||
| 1527 | 1549 | ||
| 1528 | switch (mvm->scan_status) { | 1550 | switch (mvm->scan_status) { |
| 1529 | case IWL_MVM_SCAN_SCHED: | 1551 | case IWL_MVM_SCAN_SCHED: |
| 1530 | ret = iwl_mvm_sched_scan_stop(mvm); | 1552 | ret = iwl_mvm_sched_scan_stop(mvm, true); |
| 1531 | if (ret) { | 1553 | if (ret) { |
| 1532 | ret = -EBUSY; | 1554 | ret = -EBUSY; |
| 1533 | goto out; | 1555 | goto out; |
| @@ -1715,14 +1737,12 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | |||
| 1715 | } else if (old_state == IEEE80211_STA_ASSOC && | 1737 | } else if (old_state == IEEE80211_STA_ASSOC && |
| 1716 | new_state == IEEE80211_STA_AUTHORIZED) { | 1738 | new_state == IEEE80211_STA_AUTHORIZED) { |
| 1717 | /* enable beacon filtering */ | 1739 | /* enable beacon filtering */ |
| 1718 | if (vif->bss_conf.dtim_period) | 1740 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); |
| 1719 | WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, | ||
| 1720 | CMD_SYNC)); | ||
| 1721 | ret = 0; | 1741 | ret = 0; |
| 1722 | } else if (old_state == IEEE80211_STA_AUTHORIZED && | 1742 | } else if (old_state == IEEE80211_STA_AUTHORIZED && |
| 1723 | new_state == IEEE80211_STA_ASSOC) { | 1743 | new_state == IEEE80211_STA_ASSOC) { |
| 1724 | /* disable beacon filtering */ | 1744 | /* disable beacon filtering */ |
| 1725 | WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC)); | 1745 | WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, 0)); |
| 1726 | ret = 0; | 1746 | ret = 0; |
| 1727 | } else if (old_state == IEEE80211_STA_ASSOC && | 1747 | } else if (old_state == IEEE80211_STA_ASSOC && |
| 1728 | new_state == IEEE80211_STA_AUTH) { | 1748 | new_state == IEEE80211_STA_AUTH) { |
| @@ -1779,7 +1799,7 @@ static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw, | |||
| 1779 | int ret; | 1799 | int ret; |
| 1780 | 1800 | ||
| 1781 | mutex_lock(&mvm->mutex); | 1801 | mutex_lock(&mvm->mutex); |
| 1782 | ret = iwl_mvm_mac_ctxt_changed(mvm, vif); | 1802 | ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false); |
| 1783 | mutex_unlock(&mvm->mutex); | 1803 | mutex_unlock(&mvm->mutex); |
| 1784 | return ret; | 1804 | return ret; |
| 1785 | } | 1805 | } |
| @@ -1872,7 +1892,7 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw, | |||
| 1872 | int ret; | 1892 | int ret; |
| 1873 | 1893 | ||
| 1874 | mutex_lock(&mvm->mutex); | 1894 | mutex_lock(&mvm->mutex); |
| 1875 | ret = iwl_mvm_sched_scan_stop(mvm); | 1895 | ret = iwl_mvm_sched_scan_stop(mvm, false); |
| 1876 | mutex_unlock(&mvm->mutex); | 1896 | mutex_unlock(&mvm->mutex); |
| 1877 | iwl_mvm_wait_for_async_handlers(mvm); | 1897 | iwl_mvm_wait_for_async_handlers(mvm); |
| 1878 | 1898 | ||
| @@ -2168,10 +2188,10 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, | |||
| 2168 | return; | 2188 | return; |
| 2169 | 2189 | ||
| 2170 | mutex_lock(&mvm->mutex); | 2190 | mutex_lock(&mvm->mutex); |
| 2191 | iwl_mvm_bt_coex_vif_change(mvm); | ||
| 2171 | iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def, | 2192 | iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def, |
| 2172 | ctx->rx_chains_static, | 2193 | ctx->rx_chains_static, |
| 2173 | ctx->rx_chains_dynamic); | 2194 | ctx->rx_chains_dynamic); |
| 2174 | iwl_mvm_bt_coex_vif_change(mvm); | ||
| 2175 | mutex_unlock(&mvm->mutex); | 2195 | mutex_unlock(&mvm->mutex); |
| 2176 | } | 2196 | } |
| 2177 | 2197 | ||
| @@ -2191,6 +2211,11 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
| 2191 | 2211 | ||
| 2192 | switch (vif->type) { | 2212 | switch (vif->type) { |
| 2193 | case NL80211_IFTYPE_AP: | 2213 | case NL80211_IFTYPE_AP: |
| 2214 | /* Unless it's a CSA flow we have nothing to do here */ | ||
| 2215 | if (vif->csa_active) { | ||
| 2216 | mvmvif->ap_ibss_active = true; | ||
| 2217 | break; | ||
| 2218 | } | ||
| 2194 | case NL80211_IFTYPE_ADHOC: | 2219 | case NL80211_IFTYPE_ADHOC: |
| 2195 | /* | 2220 | /* |
| 2196 | * The AP binding flow is handled as part of the start_ap flow | 2221 | * The AP binding flow is handled as part of the start_ap flow |
| @@ -2214,7 +2239,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
| 2214 | * Power state must be updated before quotas, | 2239 | * Power state must be updated before quotas, |
| 2215 | * otherwise fw will complain. | 2240 | * otherwise fw will complain. |
| 2216 | */ | 2241 | */ |
| 2217 | iwl_mvm_power_update_mac(mvm, vif); | 2242 | iwl_mvm_power_update_mac(mvm); |
| 2218 | 2243 | ||
| 2219 | /* Setting the quota at this stage is only required for monitor | 2244 | /* Setting the quota at this stage is only required for monitor |
| 2220 | * interfaces. For the other types, the bss_info changed flow | 2245 | * interfaces. For the other types, the bss_info changed flow |
| @@ -2227,11 +2252,17 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
| 2227 | goto out_remove_binding; | 2252 | goto out_remove_binding; |
| 2228 | } | 2253 | } |
| 2229 | 2254 | ||
| 2255 | /* Handle binding during CSA */ | ||
| 2256 | if (vif->type == NL80211_IFTYPE_AP) { | ||
| 2257 | iwl_mvm_update_quotas(mvm, vif); | ||
| 2258 | iwl_mvm_mac_ctxt_changed(mvm, vif, false); | ||
| 2259 | } | ||
| 2260 | |||
| 2230 | goto out_unlock; | 2261 | goto out_unlock; |
| 2231 | 2262 | ||
| 2232 | out_remove_binding: | 2263 | out_remove_binding: |
| 2233 | iwl_mvm_binding_remove_vif(mvm, vif); | 2264 | iwl_mvm_binding_remove_vif(mvm, vif); |
| 2234 | iwl_mvm_power_update_mac(mvm, vif); | 2265 | iwl_mvm_power_update_mac(mvm); |
| 2235 | out_unlock: | 2266 | out_unlock: |
| 2236 | mutex_unlock(&mvm->mutex); | 2267 | mutex_unlock(&mvm->mutex); |
| 2237 | if (ret) | 2268 | if (ret) |
| @@ -2251,22 +2282,29 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
| 2251 | iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); | 2282 | iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); |
| 2252 | 2283 | ||
| 2253 | switch (vif->type) { | 2284 | switch (vif->type) { |
| 2254 | case NL80211_IFTYPE_AP: | ||
| 2255 | case NL80211_IFTYPE_ADHOC: | 2285 | case NL80211_IFTYPE_ADHOC: |
| 2256 | goto out_unlock; | 2286 | goto out_unlock; |
| 2257 | case NL80211_IFTYPE_MONITOR: | 2287 | case NL80211_IFTYPE_MONITOR: |
| 2258 | mvmvif->monitor_active = false; | 2288 | mvmvif->monitor_active = false; |
| 2259 | iwl_mvm_update_quotas(mvm, NULL); | 2289 | iwl_mvm_update_quotas(mvm, NULL); |
| 2260 | break; | 2290 | break; |
| 2291 | case NL80211_IFTYPE_AP: | ||
| 2292 | /* This part is triggered only during CSA */ | ||
| 2293 | if (!vif->csa_active || !mvmvif->ap_ibss_active) | ||
| 2294 | goto out_unlock; | ||
| 2295 | |||
| 2296 | mvmvif->ap_ibss_active = false; | ||
| 2297 | iwl_mvm_update_quotas(mvm, NULL); | ||
| 2298 | /*TODO: bt_coex notification here? */ | ||
| 2261 | default: | 2299 | default: |
| 2262 | break; | 2300 | break; |
| 2263 | } | 2301 | } |
| 2264 | 2302 | ||
| 2265 | iwl_mvm_binding_remove_vif(mvm, vif); | 2303 | iwl_mvm_binding_remove_vif(mvm, vif); |
| 2266 | iwl_mvm_power_update_mac(mvm, vif); | ||
| 2267 | 2304 | ||
| 2268 | out_unlock: | 2305 | out_unlock: |
| 2269 | mvmvif->phy_ctxt = NULL; | 2306 | mvmvif->phy_ctxt = NULL; |
| 2307 | iwl_mvm_power_update_mac(mvm); | ||
| 2270 | mutex_unlock(&mvm->mutex); | 2308 | mutex_unlock(&mvm->mutex); |
| 2271 | } | 2309 | } |
| 2272 | 2310 | ||
| @@ -2330,9 +2368,8 @@ static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm, | |||
| 2330 | return -EINVAL; | 2368 | return -EINVAL; |
| 2331 | 2369 | ||
| 2332 | if (nla_get_u32(tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE])) | 2370 | if (nla_get_u32(tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE])) |
| 2333 | return iwl_mvm_enable_beacon_filter(mvm, vif, | 2371 | return iwl_mvm_enable_beacon_filter(mvm, vif, 0); |
| 2334 | CMD_SYNC); | 2372 | return iwl_mvm_disable_beacon_filter(mvm, vif, 0); |
| 2335 | return iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC); | ||
| 2336 | } | 2373 | } |
| 2337 | 2374 | ||
| 2338 | return -EOPNOTSUPP; | 2375 | return -EOPNOTSUPP; |
| @@ -2353,6 +2390,53 @@ static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw, | |||
| 2353 | } | 2390 | } |
| 2354 | #endif | 2391 | #endif |
| 2355 | 2392 | ||
| 2393 | static void iwl_mvm_channel_switch_beacon(struct ieee80211_hw *hw, | ||
| 2394 | struct ieee80211_vif *vif, | ||
| 2395 | struct cfg80211_chan_def *chandef) | ||
| 2396 | { | ||
| 2397 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
| 2398 | |||
| 2399 | mutex_lock(&mvm->mutex); | ||
| 2400 | if (WARN(mvm->csa_vif && mvm->csa_vif->csa_active, | ||
| 2401 | "Another CSA is already in progress")) | ||
| 2402 | goto out_unlock; | ||
| 2403 | |||
| 2404 | IWL_DEBUG_MAC80211(mvm, "CSA started to freq %d\n", | ||
| 2405 | chandef->center_freq1); | ||
| 2406 | mvm->csa_vif = vif; | ||
| 2407 | |||
| 2408 | out_unlock: | ||
| 2409 | mutex_unlock(&mvm->mutex); | ||
| 2410 | } | ||
| 2411 | |||
| 2412 | static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, | ||
| 2413 | struct ieee80211_vif *vif, u32 queues, bool drop) | ||
| 2414 | { | ||
| 2415 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
| 2416 | struct iwl_mvm_vif *mvmvif; | ||
| 2417 | struct iwl_mvm_sta *mvmsta; | ||
| 2418 | |||
| 2419 | if (!vif || vif->type != NL80211_IFTYPE_STATION) | ||
| 2420 | return; | ||
| 2421 | |||
| 2422 | mutex_lock(&mvm->mutex); | ||
| 2423 | mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 2424 | mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id); | ||
| 2425 | |||
| 2426 | if (WARN_ON_ONCE(!mvmsta)) | ||
| 2427 | goto done; | ||
| 2428 | |||
| 2429 | if (drop) { | ||
| 2430 | if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true)) | ||
| 2431 | IWL_ERR(mvm, "flush request fail\n"); | ||
| 2432 | } else { | ||
| 2433 | iwl_trans_wait_tx_queue_empty(mvm->trans, | ||
| 2434 | mvmsta->tfd_queue_msk); | ||
| 2435 | } | ||
| 2436 | done: | ||
| 2437 | mutex_unlock(&mvm->mutex); | ||
| 2438 | } | ||
| 2439 | |||
| 2356 | const struct ieee80211_ops iwl_mvm_hw_ops = { | 2440 | const struct ieee80211_ops iwl_mvm_hw_ops = { |
| 2357 | .tx = iwl_mvm_mac_tx, | 2441 | .tx = iwl_mvm_mac_tx, |
| 2358 | .ampdu_action = iwl_mvm_mac_ampdu_action, | 2442 | .ampdu_action = iwl_mvm_mac_ampdu_action, |
| @@ -2376,6 +2460,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { | |||
| 2376 | .sta_rc_update = iwl_mvm_sta_rc_update, | 2460 | .sta_rc_update = iwl_mvm_sta_rc_update, |
| 2377 | .conf_tx = iwl_mvm_mac_conf_tx, | 2461 | .conf_tx = iwl_mvm_mac_conf_tx, |
| 2378 | .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, | 2462 | .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, |
| 2463 | .flush = iwl_mvm_mac_flush, | ||
| 2379 | .sched_scan_start = iwl_mvm_mac_sched_scan_start, | 2464 | .sched_scan_start = iwl_mvm_mac_sched_scan_start, |
| 2380 | .sched_scan_stop = iwl_mvm_mac_sched_scan_stop, | 2465 | .sched_scan_stop = iwl_mvm_mac_sched_scan_stop, |
| 2381 | .set_key = iwl_mvm_mac_set_key, | 2466 | .set_key = iwl_mvm_mac_set_key, |
| @@ -2395,6 +2480,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { | |||
| 2395 | 2480 | ||
| 2396 | .set_tim = iwl_mvm_set_tim, | 2481 | .set_tim = iwl_mvm_set_tim, |
| 2397 | 2482 | ||
| 2483 | .channel_switch_beacon = iwl_mvm_channel_switch_beacon, | ||
| 2484 | |||
| 2398 | CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd) | 2485 | CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd) |
| 2399 | 2486 | ||
| 2400 | #ifdef CONFIG_PM_SLEEP | 2487 | #ifdef CONFIG_PM_SLEEP |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 107d864b3c0e..fcc6c29482d0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
| @@ -490,6 +490,7 @@ struct iwl_mvm { | |||
| 490 | u32 log_event_table; | 490 | u32 log_event_table; |
| 491 | u32 umac_error_event_table; | 491 | u32 umac_error_event_table; |
| 492 | bool support_umac_log; | 492 | bool support_umac_log; |
| 493 | struct iwl_sf_region sf_space; | ||
| 493 | 494 | ||
| 494 | u32 ampdu_ref; | 495 | u32 ampdu_ref; |
| 495 | 496 | ||
| @@ -501,6 +502,7 @@ struct iwl_mvm { | |||
| 501 | u8 queue_to_mac80211[IWL_MAX_HW_QUEUES]; | 502 | u8 queue_to_mac80211[IWL_MAX_HW_QUEUES]; |
| 502 | atomic_t queue_stop_count[IWL_MAX_HW_QUEUES]; | 503 | atomic_t queue_stop_count[IWL_MAX_HW_QUEUES]; |
| 503 | 504 | ||
| 505 | const char *nvm_file_name; | ||
| 504 | struct iwl_nvm_data *nvm_data; | 506 | struct iwl_nvm_data *nvm_data; |
| 505 | /* NVM sections */ | 507 | /* NVM sections */ |
| 506 | struct iwl_nvm_section nvm_sections[NVM_MAX_NUM_SECTIONS]; | 508 | struct iwl_nvm_section nvm_sections[NVM_MAX_NUM_SECTIONS]; |
| @@ -589,7 +591,9 @@ struct iwl_mvm { | |||
| 589 | u32 *fw_error_rxf; | 591 | u32 *fw_error_rxf; |
| 590 | u32 fw_error_rxf_len; | 592 | u32 fw_error_rxf_len; |
| 591 | 593 | ||
| 594 | #ifdef CONFIG_IWLWIFI_LEDS | ||
| 592 | struct led_classdev led; | 595 | struct led_classdev led; |
| 596 | #endif | ||
| 593 | 597 | ||
| 594 | struct ieee80211_vif *p2p_device_vif; | 598 | struct ieee80211_vif *p2p_device_vif; |
| 595 | 599 | ||
| @@ -642,6 +646,8 @@ struct iwl_mvm { | |||
| 642 | 646 | ||
| 643 | /* Indicate if device power save is allowed */ | 647 | /* Indicate if device power save is allowed */ |
| 644 | bool ps_disabled; | 648 | bool ps_disabled; |
| 649 | |||
| 650 | struct ieee80211_vif *csa_vif; | ||
| 645 | }; | 651 | }; |
| 646 | 652 | ||
| 647 | /* Extract MVM priv from op_mode and _hw */ | 653 | /* Extract MVM priv from op_mode and _hw */ |
| @@ -757,7 +763,7 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, | |||
| 757 | struct iwl_device_cmd *cmd); | 763 | struct iwl_device_cmd *cmd); |
| 758 | 764 | ||
| 759 | /* NVM */ | 765 | /* NVM */ |
| 760 | int iwl_nvm_init(struct iwl_mvm *mvm); | 766 | int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic); |
| 761 | int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm); | 767 | int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm); |
| 762 | 768 | ||
| 763 | int iwl_mvm_up(struct iwl_mvm *mvm); | 769 | int iwl_mvm_up(struct iwl_mvm *mvm); |
| @@ -808,7 +814,8 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, | |||
| 808 | int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 814 | int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
| 809 | void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 815 | void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
| 810 | int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 816 | int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
| 811 | int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 817 | int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| 818 | bool force_assoc_off); | ||
| 812 | int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 819 | int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
| 813 | u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, | 820 | u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, |
| 814 | struct ieee80211_vif *vif); | 821 | struct ieee80211_vif *vif); |
| @@ -852,7 +859,7 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, | |||
| 852 | struct cfg80211_sched_scan_request *req); | 859 | struct cfg80211_sched_scan_request *req); |
| 853 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | 860 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, |
| 854 | struct cfg80211_sched_scan_request *req); | 861 | struct cfg80211_sched_scan_request *req); |
| 855 | int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm); | 862 | int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm, bool notify); |
| 856 | int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm, | 863 | int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm, |
| 857 | struct iwl_rx_cmd_buffer *rxb, | 864 | struct iwl_rx_cmd_buffer *rxb, |
| 858 | struct iwl_device_cmd *cmd); | 865 | struct iwl_device_cmd *cmd); |
| @@ -887,7 +894,7 @@ int rs_pretty_print_rate(char *buf, const u32 rate); | |||
| 887 | 894 | ||
| 888 | /* power management */ | 895 | /* power management */ |
| 889 | int iwl_mvm_power_update_device(struct iwl_mvm *mvm); | 896 | int iwl_mvm_power_update_device(struct iwl_mvm *mvm); |
| 890 | int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 897 | int iwl_mvm_power_update_mac(struct iwl_mvm *mvm); |
| 891 | int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 898 | int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| 892 | char *buf, int bufsz); | 899 | char *buf, int bufsz); |
| 893 | 900 | ||
| @@ -896,8 +903,18 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, | |||
| 896 | struct iwl_rx_cmd_buffer *rxb, | 903 | struct iwl_rx_cmd_buffer *rxb, |
| 897 | struct iwl_device_cmd *cmd); | 904 | struct iwl_device_cmd *cmd); |
| 898 | 905 | ||
| 906 | #ifdef CONFIG_IWLWIFI_LEDS | ||
| 899 | int iwl_mvm_leds_init(struct iwl_mvm *mvm); | 907 | int iwl_mvm_leds_init(struct iwl_mvm *mvm); |
| 900 | void iwl_mvm_leds_exit(struct iwl_mvm *mvm); | 908 | void iwl_mvm_leds_exit(struct iwl_mvm *mvm); |
| 909 | #else | ||
| 910 | static inline int iwl_mvm_leds_init(struct iwl_mvm *mvm) | ||
| 911 | { | ||
| 912 | return 0; | ||
| 913 | } | ||
| 914 | static inline void iwl_mvm_leds_exit(struct iwl_mvm *mvm) | ||
| 915 | { | ||
| 916 | } | ||
| 917 | #endif | ||
| 901 | 918 | ||
| 902 | /* D3 (WoWLAN, NetDetect) */ | 919 | /* D3 (WoWLAN, NetDetect) */ |
| 903 | int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); | 920 | int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); |
| @@ -950,7 +967,6 @@ bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, | |||
| 950 | enum ieee80211_band band); | 967 | enum ieee80211_band band); |
| 951 | u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, | 968 | u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, |
| 952 | struct ieee80211_tx_info *info, u8 ac); | 969 | struct ieee80211_tx_info *info, u8 ac); |
| 953 | int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable); | ||
| 954 | 970 | ||
| 955 | enum iwl_bt_kill_msk { | 971 | enum iwl_bt_kill_msk { |
| 956 | BT_KILL_MSK_DEFAULT, | 972 | BT_KILL_MSK_DEFAULT, |
| @@ -981,17 +997,11 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, | |||
| 981 | int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, | 997 | int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, |
| 982 | struct ieee80211_vif *vif, | 998 | struct ieee80211_vif *vif, |
| 983 | u32 flags); | 999 | u32 flags); |
| 984 | int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, | ||
| 985 | struct ieee80211_vif *vif, bool enable); | ||
| 986 | int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm, | ||
| 987 | struct ieee80211_vif *vif, | ||
| 988 | bool force, | ||
| 989 | u32 flags); | ||
| 990 | |||
| 991 | /* SMPS */ | 1000 | /* SMPS */ |
| 992 | void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 1001 | void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| 993 | enum iwl_mvm_smps_type_request req_type, | 1002 | enum iwl_mvm_smps_type_request req_type, |
| 994 | enum ieee80211_smps_mode smps_request); | 1003 | enum ieee80211_smps_mode smps_request); |
| 1004 | bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm); | ||
| 995 | 1005 | ||
| 996 | /* Low latency */ | 1006 | /* Low latency */ |
| 997 | int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 1007 | int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index cf2d09f53782..808f78f6fbf9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
| @@ -74,6 +74,12 @@ | |||
| 74 | #define NVM_WRITE_OPCODE 1 | 74 | #define NVM_WRITE_OPCODE 1 |
| 75 | #define NVM_READ_OPCODE 0 | 75 | #define NVM_READ_OPCODE 0 |
| 76 | 76 | ||
| 77 | /* load nvm chunk response */ | ||
| 78 | enum { | ||
| 79 | READ_NVM_CHUNK_SUCCEED = 0, | ||
| 80 | READ_NVM_CHUNK_NOT_VALID_ADDRESS = 1 | ||
| 81 | }; | ||
| 82 | |||
| 77 | /* | 83 | /* |
| 78 | * prepare the NVM host command w/ the pointers to the nvm buffer | 84 | * prepare the NVM host command w/ the pointers to the nvm buffer |
| 79 | * and send it to fw | 85 | * and send it to fw |
| @@ -90,7 +96,7 @@ static int iwl_nvm_write_chunk(struct iwl_mvm *mvm, u16 section, | |||
| 90 | struct iwl_host_cmd cmd = { | 96 | struct iwl_host_cmd cmd = { |
| 91 | .id = NVM_ACCESS_CMD, | 97 | .id = NVM_ACCESS_CMD, |
| 92 | .len = { sizeof(struct iwl_nvm_access_cmd), length }, | 98 | .len = { sizeof(struct iwl_nvm_access_cmd), length }, |
| 93 | .flags = CMD_SYNC | CMD_SEND_IN_RFKILL, | 99 | .flags = CMD_SEND_IN_RFKILL, |
| 94 | .data = { &nvm_access_cmd, data }, | 100 | .data = { &nvm_access_cmd, data }, |
| 95 | /* data may come from vmalloc, so use _DUP */ | 101 | /* data may come from vmalloc, so use _DUP */ |
| 96 | .dataflags = { 0, IWL_HCMD_DFL_DUP }, | 102 | .dataflags = { 0, IWL_HCMD_DFL_DUP }, |
| @@ -112,7 +118,7 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | |||
| 112 | struct iwl_rx_packet *pkt; | 118 | struct iwl_rx_packet *pkt; |
| 113 | struct iwl_host_cmd cmd = { | 119 | struct iwl_host_cmd cmd = { |
| 114 | .id = NVM_ACCESS_CMD, | 120 | .id = NVM_ACCESS_CMD, |
| 115 | .flags = CMD_SYNC | CMD_WANT_SKB | CMD_SEND_IN_RFKILL, | 121 | .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL, |
| 116 | .data = { &nvm_access_cmd, }, | 122 | .data = { &nvm_access_cmd, }, |
| 117 | }; | 123 | }; |
| 118 | int ret, bytes_read, offset_read; | 124 | int ret, bytes_read, offset_read; |
| @@ -139,10 +145,26 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | |||
| 139 | offset_read = le16_to_cpu(nvm_resp->offset); | 145 | offset_read = le16_to_cpu(nvm_resp->offset); |
| 140 | resp_data = nvm_resp->data; | 146 | resp_data = nvm_resp->data; |
| 141 | if (ret) { | 147 | if (ret) { |
| 142 | IWL_ERR(mvm, | 148 | if ((offset != 0) && |
| 143 | "NVM access command failed with status %d (device: %s)\n", | 149 | (ret == READ_NVM_CHUNK_NOT_VALID_ADDRESS)) { |
| 144 | ret, mvm->cfg->name); | 150 | /* |
| 145 | ret = -EINVAL; | 151 | * meaning of NOT_VALID_ADDRESS: |
| 152 | * driver try to read chunk from address that is | ||
| 153 | * multiple of 2K and got an error since addr is empty. | ||
| 154 | * meaning of (offset != 0): driver already | ||
| 155 | * read valid data from another chunk so this case | ||
| 156 | * is not an error. | ||
| 157 | */ | ||
| 158 | IWL_DEBUG_EEPROM(mvm->trans->dev, | ||
| 159 | "NVM access command failed on offset 0x%x since that section size is multiple 2K\n", | ||
| 160 | offset); | ||
| 161 | ret = 0; | ||
| 162 | } else { | ||
| 163 | IWL_DEBUG_EEPROM(mvm->trans->dev, | ||
| 164 | "NVM access command failed with status %d (device: %s)\n", | ||
| 165 | ret, mvm->cfg->name); | ||
| 166 | ret = -EIO; | ||
| 167 | } | ||
| 146 | goto exit; | 168 | goto exit; |
| 147 | } | 169 | } |
| 148 | 170 | ||
| @@ -211,9 +233,9 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, | |||
| 211 | while (ret == length) { | 233 | while (ret == length) { |
| 212 | ret = iwl_nvm_read_chunk(mvm, section, offset, length, data); | 234 | ret = iwl_nvm_read_chunk(mvm, section, offset, length, data); |
| 213 | if (ret < 0) { | 235 | if (ret < 0) { |
| 214 | IWL_ERR(mvm, | 236 | IWL_DEBUG_EEPROM(mvm->trans->dev, |
| 215 | "Cannot read NVM from section %d offset %d, length %d\n", | 237 | "Cannot read NVM from section %d offset %d, length %d\n", |
| 216 | section, offset, length); | 238 | section, offset, length); |
| 217 | return ret; | 239 | return ret; |
| 218 | } | 240 | } |
| 219 | offset += ret; | 241 | offset += ret; |
| @@ -238,13 +260,20 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
| 238 | return NULL; | 260 | return NULL; |
| 239 | } | 261 | } |
| 240 | } else { | 262 | } else { |
| 263 | /* SW and REGULATORY sections are mandatory */ | ||
| 241 | if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || | 264 | if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || |
| 242 | !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data || | ||
| 243 | !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) { | 265 | !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) { |
| 244 | IWL_ERR(mvm, | 266 | IWL_ERR(mvm, |
| 245 | "Can't parse empty family 8000 NVM sections\n"); | 267 | "Can't parse empty family 8000 NVM sections\n"); |
| 246 | return NULL; | 268 | return NULL; |
| 247 | } | 269 | } |
| 270 | /* MAC_OVERRIDE or at least HW section must exist */ | ||
| 271 | if (!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data && | ||
| 272 | !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data) { | ||
| 273 | IWL_ERR(mvm, | ||
| 274 | "Can't parse mac_address, empty sections\n"); | ||
| 275 | return NULL; | ||
| 276 | } | ||
| 248 | } | 277 | } |
| 249 | 278 | ||
| 250 | if (WARN_ON(!mvm->cfg)) | 279 | if (WARN_ON(!mvm->cfg)) |
| @@ -311,16 +340,16 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
| 311 | * get here after that we assume the NVM request can be satisfied | 340 | * get here after that we assume the NVM request can be satisfied |
| 312 | * synchronously. | 341 | * synchronously. |
| 313 | */ | 342 | */ |
| 314 | ret = request_firmware(&fw_entry, iwlwifi_mod_params.nvm_file, | 343 | ret = request_firmware(&fw_entry, mvm->nvm_file_name, |
| 315 | mvm->trans->dev); | 344 | mvm->trans->dev); |
| 316 | if (ret) { | 345 | if (ret) { |
| 317 | IWL_ERR(mvm, "ERROR: %s isn't available %d\n", | 346 | IWL_ERR(mvm, "ERROR: %s isn't available %d\n", |
| 318 | iwlwifi_mod_params.nvm_file, ret); | 347 | mvm->nvm_file_name, ret); |
| 319 | return ret; | 348 | return ret; |
| 320 | } | 349 | } |
| 321 | 350 | ||
| 322 | IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n", | 351 | IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n", |
| 323 | iwlwifi_mod_params.nvm_file, fw_entry->size); | 352 | mvm->nvm_file_name, fw_entry->size); |
| 324 | 353 | ||
| 325 | if (fw_entry->size < sizeof(*file_sec)) { | 354 | if (fw_entry->size < sizeof(*file_sec)) { |
| 326 | IWL_ERR(mvm, "NVM file too small\n"); | 355 | IWL_ERR(mvm, "NVM file too small\n"); |
| @@ -427,53 +456,28 @@ int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm) | |||
| 427 | return ret; | 456 | return ret; |
| 428 | } | 457 | } |
| 429 | 458 | ||
| 430 | int iwl_nvm_init(struct iwl_mvm *mvm) | 459 | int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic) |
| 431 | { | 460 | { |
| 432 | int ret, i, section; | 461 | int ret, section; |
| 433 | u8 *nvm_buffer, *temp; | 462 | u8 *nvm_buffer, *temp; |
| 434 | int nvm_to_read[NVM_MAX_NUM_SECTIONS]; | ||
| 435 | int num_of_sections_to_read; | ||
| 436 | 463 | ||
| 437 | if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS)) | 464 | if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS)) |
| 438 | return -EINVAL; | 465 | return -EINVAL; |
| 439 | 466 | ||
| 440 | /* load external NVM if configured */ | 467 | /* load NVM values from nic */ |
| 441 | if (iwlwifi_mod_params.nvm_file) { | 468 | if (read_nvm_from_nic) { |
| 442 | /* move to External NVM flow */ | ||
| 443 | ret = iwl_mvm_read_external_nvm(mvm); | ||
| 444 | if (ret) | ||
| 445 | return ret; | ||
| 446 | } else { | ||
| 447 | /* list of NVM sections we are allowed/need to read */ | ||
| 448 | if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { | ||
| 449 | nvm_to_read[0] = mvm->cfg->nvm_hw_section_num; | ||
| 450 | nvm_to_read[1] = NVM_SECTION_TYPE_SW; | ||
| 451 | nvm_to_read[2] = NVM_SECTION_TYPE_CALIBRATION; | ||
| 452 | nvm_to_read[3] = NVM_SECTION_TYPE_PRODUCTION; | ||
| 453 | num_of_sections_to_read = 4; | ||
| 454 | } else { | ||
| 455 | nvm_to_read[0] = NVM_SECTION_TYPE_SW; | ||
| 456 | nvm_to_read[1] = NVM_SECTION_TYPE_CALIBRATION; | ||
| 457 | nvm_to_read[2] = NVM_SECTION_TYPE_PRODUCTION; | ||
| 458 | nvm_to_read[3] = NVM_SECTION_TYPE_REGULATORY; | ||
| 459 | nvm_to_read[4] = NVM_SECTION_TYPE_MAC_OVERRIDE; | ||
| 460 | num_of_sections_to_read = 5; | ||
| 461 | } | ||
| 462 | |||
| 463 | /* Read From FW NVM */ | 469 | /* Read From FW NVM */ |
| 464 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); | 470 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); |
| 465 | 471 | ||
| 466 | /* TODO: find correct NVM max size for a section */ | ||
| 467 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, | 472 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, |
| 468 | GFP_KERNEL); | 473 | GFP_KERNEL); |
| 469 | if (!nvm_buffer) | 474 | if (!nvm_buffer) |
| 470 | return -ENOMEM; | 475 | return -ENOMEM; |
| 471 | for (i = 0; i < num_of_sections_to_read; i++) { | 476 | for (section = 0; section < NVM_MAX_NUM_SECTIONS; section++) { |
| 472 | section = nvm_to_read[i]; | ||
| 473 | /* we override the constness for initial read */ | 477 | /* we override the constness for initial read */ |
| 474 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); | 478 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); |
| 475 | if (ret < 0) | 479 | if (ret < 0) |
| 476 | break; | 480 | continue; |
| 477 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); | 481 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); |
| 478 | if (!temp) { | 482 | if (!temp) { |
| 479 | ret = -ENOMEM; | 483 | ret = -ENOMEM; |
| @@ -502,15 +506,21 @@ int iwl_nvm_init(struct iwl_mvm *mvm) | |||
| 502 | mvm->nvm_hw_blob.size = ret; | 506 | mvm->nvm_hw_blob.size = ret; |
| 503 | break; | 507 | break; |
| 504 | } | 508 | } |
| 505 | WARN(1, "section: %d", section); | ||
| 506 | } | 509 | } |
| 507 | #endif | 510 | #endif |
| 508 | } | 511 | } |
| 509 | kfree(nvm_buffer); | 512 | kfree(nvm_buffer); |
| 510 | if (ret < 0) | 513 | } |
| 514 | |||
| 515 | /* load external NVM if configured */ | ||
| 516 | if (mvm->nvm_file_name) { | ||
| 517 | /* move to External NVM flow */ | ||
| 518 | ret = iwl_mvm_read_external_nvm(mvm); | ||
| 519 | if (ret) | ||
| 511 | return ret; | 520 | return ret; |
| 512 | } | 521 | } |
| 513 | 522 | ||
| 523 | /* parse the relevant nvm sections */ | ||
| 514 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); | 524 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); |
| 515 | if (!mvm->nvm_data) | 525 | if (!mvm->nvm_data) |
| 516 | return -ENODATA; | 526 | return -ENODATA; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 7a5a8bac5fd0..cc2f7de396de 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
| @@ -79,8 +79,8 @@ | |||
| 79 | #include "iwl-prph.h" | 79 | #include "iwl-prph.h" |
| 80 | #include "rs.h" | 80 | #include "rs.h" |
| 81 | #include "fw-api-scan.h" | 81 | #include "fw-api-scan.h" |
| 82 | #include "fw-error-dump.h" | ||
| 83 | #include "time-event.h" | 82 | #include "time-event.h" |
| 83 | #include "iwl-fw-error-dump.h" | ||
| 84 | 84 | ||
| 85 | /* | 85 | /* |
| 86 | * module name, copyright, version, etc. | 86 | * module name, copyright, version, etc. |
| @@ -220,7 +220,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
| 220 | RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false), | 220 | RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false), |
| 221 | 221 | ||
| 222 | RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), | 222 | RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), |
| 223 | RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false), | 223 | RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, true), |
| 224 | RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true), | 224 | RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true), |
| 225 | RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION, | 225 | RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION, |
| 226 | iwl_mvm_rx_ant_coupling_notif, true), | 226 | iwl_mvm_rx_ant_coupling_notif, true), |
| @@ -466,13 +466,24 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 466 | 466 | ||
| 467 | min_backoff = calc_min_backoff(trans, cfg); | 467 | min_backoff = calc_min_backoff(trans, cfg); |
| 468 | iwl_mvm_tt_initialize(mvm, min_backoff); | 468 | iwl_mvm_tt_initialize(mvm, min_backoff); |
| 469 | /* set the nvm_file_name according to priority */ | ||
| 470 | if (iwlwifi_mod_params.nvm_file) | ||
| 471 | mvm->nvm_file_name = iwlwifi_mod_params.nvm_file; | ||
| 472 | else | ||
| 473 | mvm->nvm_file_name = mvm->cfg->default_nvm_file; | ||
| 474 | |||
| 475 | if (WARN(cfg->no_power_up_nic_in_init && !mvm->nvm_file_name, | ||
| 476 | "not allowing power-up and not having nvm_file\n")) | ||
| 477 | goto out_free; | ||
| 469 | 478 | ||
| 470 | /* | 479 | /* |
| 471 | * If the NVM exists in an external file, | 480 | * Even if nvm exists in the nvm_file driver should read agin the nvm |
| 472 | * there is no need to unnecessarily power up the NIC at driver load | 481 | * from the nic because there might be entries that exist in the OTP |
| 482 | * and not in the file. | ||
| 483 | * for nics with no_power_up_nic_in_init: rely completley on nvm_file | ||
| 473 | */ | 484 | */ |
| 474 | if (iwlwifi_mod_params.nvm_file) { | 485 | if (cfg->no_power_up_nic_in_init && mvm->nvm_file_name) { |
| 475 | err = iwl_nvm_init(mvm); | 486 | err = iwl_nvm_init(mvm, false); |
| 476 | if (err) | 487 | if (err) |
| 477 | goto out_free; | 488 | goto out_free; |
| 478 | } else { | 489 | } else { |
| @@ -519,7 +530,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 519 | out_free: | 530 | out_free: |
| 520 | iwl_phy_db_free(mvm->phy_db); | 531 | iwl_phy_db_free(mvm->phy_db); |
| 521 | kfree(mvm->scan_cmd); | 532 | kfree(mvm->scan_cmd); |
| 522 | if (!iwlwifi_mod_params.nvm_file) | 533 | if (!cfg->no_power_up_nic_in_init || !mvm->nvm_file_name) |
| 523 | iwl_trans_op_mode_leave(trans); | 534 | iwl_trans_op_mode_leave(trans); |
| 524 | ieee80211_free_hw(mvm->hw); | 535 | ieee80211_free_hw(mvm->hw); |
| 525 | return NULL; | 536 | return NULL; |
| @@ -816,6 +827,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
| 816 | struct iwl_fw_error_dump_file *dump_file; | 827 | struct iwl_fw_error_dump_file *dump_file; |
| 817 | struct iwl_fw_error_dump_data *dump_data; | 828 | struct iwl_fw_error_dump_data *dump_data; |
| 818 | u32 file_len; | 829 | u32 file_len; |
| 830 | u32 trans_len; | ||
| 819 | 831 | ||
| 820 | lockdep_assert_held(&mvm->mutex); | 832 | lockdep_assert_held(&mvm->mutex); |
| 821 | 833 | ||
| @@ -827,6 +839,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
| 827 | sizeof(*dump_file) + | 839 | sizeof(*dump_file) + |
| 828 | sizeof(*dump_data) * 2; | 840 | sizeof(*dump_data) * 2; |
| 829 | 841 | ||
| 842 | trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0); | ||
| 843 | if (trans_len) | ||
| 844 | file_len += trans_len; | ||
| 845 | |||
| 830 | dump_file = vmalloc(file_len); | 846 | dump_file = vmalloc(file_len); |
| 831 | if (!dump_file) | 847 | if (!dump_file) |
| 832 | return; | 848 | return; |
| @@ -840,7 +856,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
| 840 | dump_data->len = cpu_to_le32(mvm->fw_error_rxf_len); | 856 | dump_data->len = cpu_to_le32(mvm->fw_error_rxf_len); |
| 841 | memcpy(dump_data->data, mvm->fw_error_rxf, mvm->fw_error_rxf_len); | 857 | memcpy(dump_data->data, mvm->fw_error_rxf, mvm->fw_error_rxf_len); |
| 842 | 858 | ||
| 843 | dump_data = (void *)((u8 *)dump_data->data + mvm->fw_error_rxf_len); | 859 | dump_data = iwl_mvm_fw_error_next_data(dump_data); |
| 844 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM); | 860 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM); |
| 845 | dump_data->len = cpu_to_le32(mvm->fw_error_sram_len); | 861 | dump_data->len = cpu_to_le32(mvm->fw_error_sram_len); |
| 846 | 862 | ||
| @@ -858,6 +874,15 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
| 858 | kfree(mvm->fw_error_sram); | 874 | kfree(mvm->fw_error_sram); |
| 859 | mvm->fw_error_sram = NULL; | 875 | mvm->fw_error_sram = NULL; |
| 860 | mvm->fw_error_sram_len = 0; | 876 | mvm->fw_error_sram_len = 0; |
| 877 | |||
| 878 | if (trans_len) { | ||
| 879 | void *buf = iwl_mvm_fw_error_next_data(dump_data); | ||
| 880 | u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf, | ||
| 881 | trans_len); | ||
| 882 | dump_data = (void *)((u8 *)buf + real_trans_len); | ||
| 883 | dump_file->file_len = | ||
| 884 | cpu_to_le32(file_len - trans_len + real_trans_len); | ||
| 885 | } | ||
| 861 | } | 886 | } |
| 862 | #endif | 887 | #endif |
| 863 | 888 | ||
| @@ -1143,7 +1168,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) | |||
| 1143 | struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, d0i3_exit_work); | 1168 | struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, d0i3_exit_work); |
| 1144 | struct iwl_host_cmd get_status_cmd = { | 1169 | struct iwl_host_cmd get_status_cmd = { |
| 1145 | .id = WOWLAN_GET_STATUSES, | 1170 | .id = WOWLAN_GET_STATUSES, |
| 1146 | .flags = CMD_SYNC | CMD_HIGH_PRIO | CMD_WANT_SKB, | 1171 | .flags = CMD_HIGH_PRIO | CMD_WANT_SKB, |
| 1147 | }; | 1172 | }; |
| 1148 | struct iwl_wowlan_status *status; | 1173 | struct iwl_wowlan_status *status; |
| 1149 | int ret; | 1174 | int ret; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index 237efe0ac1c4..539f3a942d43 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | |||
| @@ -156,6 +156,18 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, | |||
| 156 | idle_cnt = chains_static; | 156 | idle_cnt = chains_static; |
| 157 | active_cnt = chains_dynamic; | 157 | active_cnt = chains_dynamic; |
| 158 | 158 | ||
| 159 | /* In scenarios where we only ever use a single-stream rates, | ||
| 160 | * i.e. legacy 11b/g/a associations, single-stream APs or even | ||
| 161 | * static SMPS, enable both chains to get diversity, improving | ||
| 162 | * the case where we're far enough from the AP that attenuation | ||
| 163 | * between the two antennas is sufficiently different to impact | ||
| 164 | * performance. | ||
| 165 | */ | ||
| 166 | if (active_cnt == 1 && iwl_mvm_rx_diversity_allowed(mvm)) { | ||
| 167 | idle_cnt = 2; | ||
| 168 | active_cnt = 2; | ||
| 169 | } | ||
| 170 | |||
| 159 | cmd->rxchain_info = cpu_to_le32(mvm->fw->valid_rx_ant << | 171 | cmd->rxchain_info = cpu_to_le32(mvm->fw->valid_rx_ant << |
| 160 | PHY_RX_CHAIN_VALID_POS); | 172 | PHY_RX_CHAIN_VALID_POS); |
| 161 | cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); | 173 | cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); |
| @@ -187,7 +199,7 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm, | |||
| 187 | iwl_mvm_phy_ctxt_cmd_data(mvm, &cmd, chandef, | 199 | iwl_mvm_phy_ctxt_cmd_data(mvm, &cmd, chandef, |
| 188 | chains_static, chains_dynamic); | 200 | chains_static, chains_dynamic); |
| 189 | 201 | ||
| 190 | ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, CMD_SYNC, | 202 | ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, 0, |
| 191 | sizeof(struct iwl_phy_context_cmd), | 203 | sizeof(struct iwl_phy_context_cmd), |
| 192 | &cmd); | 204 | &cmd); |
| 193 | if (ret) | 205 | if (ret) |
| @@ -202,18 +214,15 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, | |||
| 202 | struct cfg80211_chan_def *chandef, | 214 | struct cfg80211_chan_def *chandef, |
| 203 | u8 chains_static, u8 chains_dynamic) | 215 | u8 chains_static, u8 chains_dynamic) |
| 204 | { | 216 | { |
| 205 | int ret; | ||
| 206 | |||
| 207 | WARN_ON(!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && | 217 | WARN_ON(!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && |
| 208 | ctxt->ref); | 218 | ctxt->ref); |
| 209 | lockdep_assert_held(&mvm->mutex); | 219 | lockdep_assert_held(&mvm->mutex); |
| 210 | 220 | ||
| 211 | ctxt->channel = chandef->chan; | 221 | ctxt->channel = chandef->chan; |
| 212 | ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, | ||
| 213 | chains_static, chains_dynamic, | ||
| 214 | FW_CTXT_ACTION_ADD, 0); | ||
| 215 | 222 | ||
| 216 | return ret; | 223 | return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, |
| 224 | chains_static, chains_dynamic, | ||
| 225 | FW_CTXT_ACTION_ADD, 0); | ||
| 217 | } | 226 | } |
| 218 | 227 | ||
| 219 | /* | 228 | /* |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 78309f7d0b7b..c182a8baf685 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
| @@ -123,28 +123,6 @@ void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm, | |||
| 123 | cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled); | 123 | cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled); |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, | ||
| 127 | struct ieee80211_vif *vif, bool enable) | ||
| 128 | { | ||
| 129 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 130 | struct iwl_beacon_filter_cmd cmd = { | ||
| 131 | IWL_BF_CMD_CONFIG_DEFAULTS, | ||
| 132 | .bf_enable_beacon_filter = cpu_to_le32(1), | ||
| 133 | .ba_enable_beacon_abort = cpu_to_le32(enable), | ||
| 134 | }; | ||
| 135 | |||
| 136 | if (!mvmvif->bf_data.bf_enabled) | ||
| 137 | return 0; | ||
| 138 | |||
| 139 | if (mvm->cur_ucode == IWL_UCODE_WOWLAN) | ||
| 140 | cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3); | ||
| 141 | |||
| 142 | mvmvif->bf_data.ba_enabled = enable; | ||
| 143 | iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, &cmd); | ||
| 144 | iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); | ||
| 145 | return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, CMD_SYNC); | ||
| 146 | } | ||
| 147 | |||
| 148 | static void iwl_mvm_power_log(struct iwl_mvm *mvm, | 126 | static void iwl_mvm_power_log(struct iwl_mvm *mvm, |
| 149 | struct iwl_mac_power_cmd *cmd) | 127 | struct iwl_mac_power_cmd *cmd) |
| 150 | { | 128 | { |
| @@ -268,10 +246,30 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, | |||
| 268 | IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; | 246 | IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; |
| 269 | } | 247 | } |
| 270 | 248 | ||
| 249 | static void iwl_mvm_binding_iterator(void *_data, u8 *mac, | ||
| 250 | struct ieee80211_vif *vif) | ||
| 251 | { | ||
| 252 | unsigned long *data = _data; | ||
| 253 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 254 | |||
| 255 | if (!mvmvif->phy_ctxt) | ||
| 256 | return; | ||
| 257 | |||
| 258 | if (vif->type == NL80211_IFTYPE_STATION || | ||
| 259 | vif->type == NL80211_IFTYPE_AP) | ||
| 260 | __set_bit(mvmvif->phy_ctxt->id, data); | ||
| 261 | } | ||
| 262 | |||
| 271 | static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, | 263 | static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, |
| 272 | struct ieee80211_vif *vif) | 264 | struct ieee80211_vif *vif) |
| 273 | { | 265 | { |
| 274 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 266 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 267 | unsigned long phy_ctxt_counter = 0; | ||
| 268 | |||
| 269 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | ||
| 270 | IEEE80211_IFACE_ITER_NORMAL, | ||
| 271 | iwl_mvm_binding_iterator, | ||
| 272 | &phy_ctxt_counter); | ||
| 275 | 273 | ||
| 276 | if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid, | 274 | if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid, |
| 277 | ETH_ALEN)) | 275 | ETH_ALEN)) |
| @@ -289,6 +287,13 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, | |||
| 289 | IEEE80211_P2P_OPPPS_ENABLE_BIT)) | 287 | IEEE80211_P2P_OPPPS_ENABLE_BIT)) |
| 290 | return false; | 288 | return false; |
| 291 | 289 | ||
| 290 | /* | ||
| 291 | * Avoid using uAPSD if client is in DCM - | ||
| 292 | * low latency issue in Miracast | ||
| 293 | */ | ||
| 294 | if (hweight8(phy_ctxt_counter) >= 2) | ||
| 295 | return false; | ||
| 296 | |||
| 292 | return true; | 297 | return true; |
| 293 | } | 298 | } |
| 294 | 299 | ||
| @@ -429,7 +434,7 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, | |||
| 429 | memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd)); | 434 | memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd)); |
| 430 | #endif | 435 | #endif |
| 431 | 436 | ||
| 432 | return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC, | 437 | return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, 0, |
| 433 | sizeof(cmd), &cmd); | 438 | sizeof(cmd), &cmd); |
| 434 | } | 439 | } |
| 435 | 440 | ||
| @@ -455,7 +460,7 @@ int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | |||
| 455 | "Sending device power command with flags = 0x%X\n", | 460 | "Sending device power command with flags = 0x%X\n", |
| 456 | cmd.flags); | 461 | cmd.flags); |
| 457 | 462 | ||
| 458 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, sizeof(cmd), | 463 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, 0, sizeof(cmd), |
| 459 | &cmd); | 464 | &cmd); |
| 460 | } | 465 | } |
| 461 | 466 | ||
| @@ -613,11 +618,15 @@ iwl_mvm_power_set_pm(struct iwl_mvm *mvm, | |||
| 613 | ap_same_channel = (bss_mvmvif->phy_ctxt->id == | 618 | ap_same_channel = (bss_mvmvif->phy_ctxt->id == |
| 614 | ap_mvmvif->phy_ctxt->id); | 619 | ap_mvmvif->phy_ctxt->id); |
| 615 | 620 | ||
| 616 | /* bss is not stand alone: enable PM if alone on its channel */ | 621 | /* clients are not stand alone: enable PM if DCM */ |
| 617 | if (vifs->bss_active && !(client_same_channel || ap_same_channel) && | 622 | if (!(client_same_channel || ap_same_channel) && |
| 618 | (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) { | 623 | (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) { |
| 624 | if (vifs->bss_active) | ||
| 619 | bss_mvmvif->pm_enabled = true; | 625 | bss_mvmvif->pm_enabled = true; |
| 620 | return; | 626 | if (vifs->p2p_active && |
| 627 | (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM)) | ||
| 628 | p2p_mvmvif->pm_enabled = true; | ||
| 629 | return; | ||
| 621 | } | 630 | } |
| 622 | 631 | ||
| 623 | /* | 632 | /* |
| @@ -633,55 +642,6 @@ iwl_mvm_power_set_pm(struct iwl_mvm *mvm, | |||
| 633 | } | 642 | } |
| 634 | } | 643 | } |
| 635 | 644 | ||
| 636 | int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
| 637 | { | ||
| 638 | struct iwl_mvm_vif *mvmvif; | ||
| 639 | struct iwl_power_vifs vifs = {}; | ||
| 640 | bool ba_enable; | ||
| 641 | int ret; | ||
| 642 | |||
| 643 | lockdep_assert_held(&mvm->mutex); | ||
| 644 | |||
| 645 | iwl_mvm_power_set_pm(mvm, &vifs); | ||
| 646 | |||
| 647 | /* disable PS if CAM */ | ||
| 648 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) { | ||
| 649 | mvm->ps_disabled = true; | ||
| 650 | } else { | ||
| 651 | /* don't update device power state unless we add / remove monitor */ | ||
| 652 | if (vifs.monitor_vif) { | ||
| 653 | if (vifs.monitor_active) | ||
| 654 | mvm->ps_disabled = true; | ||
| 655 | ret = iwl_mvm_power_update_device(mvm); | ||
| 656 | if (ret) | ||
| 657 | return ret; | ||
| 658 | } | ||
| 659 | } | ||
| 660 | |||
| 661 | if (vifs.bss_vif) { | ||
| 662 | ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif); | ||
| 663 | if (ret) | ||
| 664 | return ret; | ||
| 665 | } | ||
| 666 | |||
| 667 | if (vifs.p2p_vif) { | ||
| 668 | ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif); | ||
| 669 | if (ret) | ||
| 670 | return ret; | ||
| 671 | } | ||
| 672 | |||
| 673 | if (!vifs.bf_vif) | ||
| 674 | return 0; | ||
| 675 | |||
| 676 | vif = vifs.bf_vif; | ||
| 677 | mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 678 | |||
| 679 | ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled || | ||
| 680 | !vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif)); | ||
| 681 | |||
| 682 | return iwl_mvm_update_beacon_abort(mvm, vifs.bf_vif, ba_enable); | ||
| 683 | } | ||
| 684 | |||
| 685 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 645 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 686 | int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, | 646 | int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, |
| 687 | struct ieee80211_vif *vif, char *buf, | 647 | struct ieee80211_vif *vif, char *buf, |
| @@ -801,7 +761,7 @@ static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, | |||
| 801 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 761 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 802 | int ret; | 762 | int ret; |
| 803 | 763 | ||
| 804 | if (mvmvif != mvm->bf_allowed_vif || | 764 | if (mvmvif != mvm->bf_allowed_vif || !vif->bss_conf.dtim_period || |
| 805 | vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 765 | vif->type != NL80211_IFTYPE_STATION || vif->p2p) |
| 806 | return 0; | 766 | return 0; |
| 807 | 767 | ||
| @@ -829,6 +789,26 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, | |||
| 829 | return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false); | 789 | return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false); |
| 830 | } | 790 | } |
| 831 | 791 | ||
| 792 | static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, | ||
| 793 | struct ieee80211_vif *vif, | ||
| 794 | bool enable) | ||
| 795 | { | ||
| 796 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 797 | struct iwl_beacon_filter_cmd cmd = { | ||
| 798 | IWL_BF_CMD_CONFIG_DEFAULTS, | ||
| 799 | .bf_enable_beacon_filter = cpu_to_le32(1), | ||
| 800 | }; | ||
| 801 | |||
| 802 | if (!mvmvif->bf_data.bf_enabled) | ||
| 803 | return 0; | ||
| 804 | |||
| 805 | if (mvm->cur_ucode == IWL_UCODE_WOWLAN) | ||
| 806 | cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3); | ||
| 807 | |||
| 808 | mvmvif->bf_data.ba_enabled = enable; | ||
| 809 | return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false); | ||
| 810 | } | ||
| 811 | |||
| 832 | int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, | 812 | int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, |
| 833 | struct ieee80211_vif *vif, | 813 | struct ieee80211_vif *vif, |
| 834 | u32 flags) | 814 | u32 flags) |
| @@ -848,6 +828,55 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, | |||
| 848 | return ret; | 828 | return ret; |
| 849 | } | 829 | } |
| 850 | 830 | ||
| 831 | int iwl_mvm_power_update_mac(struct iwl_mvm *mvm) | ||
| 832 | { | ||
| 833 | struct iwl_mvm_vif *mvmvif; | ||
| 834 | struct iwl_power_vifs vifs = {}; | ||
| 835 | bool ba_enable; | ||
| 836 | int ret; | ||
| 837 | |||
| 838 | lockdep_assert_held(&mvm->mutex); | ||
| 839 | |||
| 840 | iwl_mvm_power_set_pm(mvm, &vifs); | ||
| 841 | |||
| 842 | /* disable PS if CAM */ | ||
| 843 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) { | ||
| 844 | mvm->ps_disabled = true; | ||
| 845 | } else { | ||
| 846 | /* don't update device power state unless we add / remove monitor */ | ||
| 847 | if (vifs.monitor_vif) { | ||
| 848 | if (vifs.monitor_active) | ||
| 849 | mvm->ps_disabled = true; | ||
| 850 | ret = iwl_mvm_power_update_device(mvm); | ||
| 851 | if (ret) | ||
| 852 | return ret; | ||
| 853 | } | ||
| 854 | } | ||
| 855 | |||
| 856 | if (vifs.bss_vif) { | ||
| 857 | ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif); | ||
| 858 | if (ret) | ||
| 859 | return ret; | ||
| 860 | } | ||
| 861 | |||
| 862 | if (vifs.p2p_vif) { | ||
| 863 | ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif); | ||
| 864 | if (ret) | ||
| 865 | return ret; | ||
| 866 | } | ||
| 867 | |||
| 868 | if (!vifs.bf_vif) | ||
| 869 | return 0; | ||
| 870 | |||
| 871 | mvmvif = iwl_mvm_vif_from_mac80211(vifs.bf_vif); | ||
| 872 | |||
| 873 | ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled || | ||
| 874 | !vifs.bf_vif->bss_conf.ps || | ||
| 875 | iwl_mvm_vif_low_latency(mvmvif)); | ||
| 876 | |||
| 877 | return iwl_mvm_update_beacon_abort(mvm, vifs.bf_vif, ba_enable); | ||
| 878 | } | ||
| 879 | |||
| 851 | int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, | 880 | int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, |
| 852 | struct ieee80211_vif *vif, | 881 | struct ieee80211_vif *vif, |
| 853 | bool enable, u32 flags) | 882 | bool enable, u32 flags) |
| @@ -871,9 +900,10 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, | |||
| 871 | if (WARN_ON(!dtimper_msec)) | 900 | if (WARN_ON(!dtimper_msec)) |
| 872 | return 0; | 901 | return 0; |
| 873 | 902 | ||
| 874 | cmd.flags |= | ||
| 875 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); | ||
| 876 | cmd.skip_dtim_periods = 300 / dtimper_msec; | 903 | cmd.skip_dtim_periods = 300 / dtimper_msec; |
| 904 | if (cmd.skip_dtim_periods) | ||
| 905 | cmd.flags |= | ||
| 906 | cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); | ||
| 877 | } | 907 | } |
| 878 | iwl_mvm_power_log(mvm, &cmd); | 908 | iwl_mvm_power_log(mvm, &cmd); |
| 879 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 909 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| @@ -904,23 +934,3 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, | |||
| 904 | 934 | ||
| 905 | return ret; | 935 | return ret; |
| 906 | } | 936 | } |
| 907 | |||
| 908 | int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm, | ||
| 909 | struct ieee80211_vif *vif, | ||
| 910 | bool force, | ||
| 911 | u32 flags) | ||
| 912 | { | ||
| 913 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 914 | |||
| 915 | if (mvmvif != mvm->bf_allowed_vif) | ||
| 916 | return 0; | ||
| 917 | |||
| 918 | if (!mvmvif->bf_data.bf_enabled) { | ||
| 919 | /* disable beacon filtering explicitly if force is true */ | ||
| 920 | if (force) | ||
| 921 | return iwl_mvm_disable_beacon_filter(mvm, vif, flags); | ||
| 922 | return 0; | ||
| 923 | } | ||
| 924 | |||
| 925 | return iwl_mvm_enable_beacon_filter(mvm, vif, flags); | ||
| 926 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index 35e86e06dffd..ba68d7b84505 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
| @@ -285,7 +285,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | |||
| 285 | 285 | ||
| 286 | iwl_mvm_adjust_quota_for_noa(mvm, &cmd); | 286 | iwl_mvm_adjust_quota_for_noa(mvm, &cmd); |
| 287 | 287 | ||
| 288 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC, | 288 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0, |
| 289 | sizeof(cmd), &cmd); | 289 | sizeof(cmd), &cmd); |
| 290 | if (ret) | 290 | if (ret) |
| 291 | IWL_ERR(mvm, "Failed to send quota: %d\n", ret); | 291 | IWL_ERR(mvm, "Failed to send quota: %d\n", ret); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 857ddaf6f48c..306a6caa4868 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
| @@ -211,7 +211,7 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 211 | .next_columns = { | 211 | .next_columns = { |
| 212 | RS_COLUMN_LEGACY_ANT_B, | 212 | RS_COLUMN_LEGACY_ANT_B, |
| 213 | RS_COLUMN_SISO_ANT_A, | 213 | RS_COLUMN_SISO_ANT_A, |
| 214 | RS_COLUMN_SISO_ANT_B, | 214 | RS_COLUMN_MIMO2, |
| 215 | RS_COLUMN_INVALID, | 215 | RS_COLUMN_INVALID, |
| 216 | RS_COLUMN_INVALID, | 216 | RS_COLUMN_INVALID, |
| 217 | RS_COLUMN_INVALID, | 217 | RS_COLUMN_INVALID, |
| @@ -223,8 +223,8 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 223 | .ant = ANT_B, | 223 | .ant = ANT_B, |
| 224 | .next_columns = { | 224 | .next_columns = { |
| 225 | RS_COLUMN_LEGACY_ANT_A, | 225 | RS_COLUMN_LEGACY_ANT_A, |
| 226 | RS_COLUMN_SISO_ANT_A, | ||
| 227 | RS_COLUMN_SISO_ANT_B, | 226 | RS_COLUMN_SISO_ANT_B, |
| 227 | RS_COLUMN_MIMO2, | ||
| 228 | RS_COLUMN_INVALID, | 228 | RS_COLUMN_INVALID, |
| 229 | RS_COLUMN_INVALID, | 229 | RS_COLUMN_INVALID, |
| 230 | RS_COLUMN_INVALID, | 230 | RS_COLUMN_INVALID, |
| @@ -238,10 +238,10 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 238 | RS_COLUMN_SISO_ANT_B, | 238 | RS_COLUMN_SISO_ANT_B, |
| 239 | RS_COLUMN_MIMO2, | 239 | RS_COLUMN_MIMO2, |
| 240 | RS_COLUMN_SISO_ANT_A_SGI, | 240 | RS_COLUMN_SISO_ANT_A_SGI, |
| 241 | RS_COLUMN_SISO_ANT_B_SGI, | ||
| 242 | RS_COLUMN_LEGACY_ANT_A, | 241 | RS_COLUMN_LEGACY_ANT_A, |
| 243 | RS_COLUMN_LEGACY_ANT_B, | 242 | RS_COLUMN_LEGACY_ANT_B, |
| 244 | RS_COLUMN_INVALID, | 243 | RS_COLUMN_INVALID, |
| 244 | RS_COLUMN_INVALID, | ||
| 245 | }, | 245 | }, |
| 246 | .checks = { | 246 | .checks = { |
| 247 | rs_siso_allow, | 247 | rs_siso_allow, |
| @@ -254,10 +254,10 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 254 | RS_COLUMN_SISO_ANT_A, | 254 | RS_COLUMN_SISO_ANT_A, |
| 255 | RS_COLUMN_MIMO2, | 255 | RS_COLUMN_MIMO2, |
| 256 | RS_COLUMN_SISO_ANT_B_SGI, | 256 | RS_COLUMN_SISO_ANT_B_SGI, |
| 257 | RS_COLUMN_SISO_ANT_A_SGI, | ||
| 258 | RS_COLUMN_LEGACY_ANT_A, | 257 | RS_COLUMN_LEGACY_ANT_A, |
| 259 | RS_COLUMN_LEGACY_ANT_B, | 258 | RS_COLUMN_LEGACY_ANT_B, |
| 260 | RS_COLUMN_INVALID, | 259 | RS_COLUMN_INVALID, |
| 260 | RS_COLUMN_INVALID, | ||
| 261 | }, | 261 | }, |
| 262 | .checks = { | 262 | .checks = { |
| 263 | rs_siso_allow, | 263 | rs_siso_allow, |
| @@ -271,10 +271,10 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 271 | RS_COLUMN_SISO_ANT_B_SGI, | 271 | RS_COLUMN_SISO_ANT_B_SGI, |
| 272 | RS_COLUMN_MIMO2_SGI, | 272 | RS_COLUMN_MIMO2_SGI, |
| 273 | RS_COLUMN_SISO_ANT_A, | 273 | RS_COLUMN_SISO_ANT_A, |
| 274 | RS_COLUMN_SISO_ANT_B, | ||
| 275 | RS_COLUMN_MIMO2, | ||
| 276 | RS_COLUMN_LEGACY_ANT_A, | 274 | RS_COLUMN_LEGACY_ANT_A, |
| 277 | RS_COLUMN_LEGACY_ANT_B, | 275 | RS_COLUMN_LEGACY_ANT_B, |
| 276 | RS_COLUMN_INVALID, | ||
| 277 | RS_COLUMN_INVALID, | ||
| 278 | }, | 278 | }, |
| 279 | .checks = { | 279 | .checks = { |
| 280 | rs_siso_allow, | 280 | rs_siso_allow, |
| @@ -289,10 +289,10 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 289 | RS_COLUMN_SISO_ANT_A_SGI, | 289 | RS_COLUMN_SISO_ANT_A_SGI, |
| 290 | RS_COLUMN_MIMO2_SGI, | 290 | RS_COLUMN_MIMO2_SGI, |
| 291 | RS_COLUMN_SISO_ANT_B, | 291 | RS_COLUMN_SISO_ANT_B, |
| 292 | RS_COLUMN_SISO_ANT_A, | ||
| 293 | RS_COLUMN_MIMO2, | ||
| 294 | RS_COLUMN_LEGACY_ANT_A, | 292 | RS_COLUMN_LEGACY_ANT_A, |
| 295 | RS_COLUMN_LEGACY_ANT_B, | 293 | RS_COLUMN_LEGACY_ANT_B, |
| 294 | RS_COLUMN_INVALID, | ||
| 295 | RS_COLUMN_INVALID, | ||
| 296 | }, | 296 | }, |
| 297 | .checks = { | 297 | .checks = { |
| 298 | rs_siso_allow, | 298 | rs_siso_allow, |
| @@ -304,12 +304,12 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 304 | .ant = ANT_AB, | 304 | .ant = ANT_AB, |
| 305 | .next_columns = { | 305 | .next_columns = { |
| 306 | RS_COLUMN_SISO_ANT_A, | 306 | RS_COLUMN_SISO_ANT_A, |
| 307 | RS_COLUMN_SISO_ANT_B, | ||
| 308 | RS_COLUMN_SISO_ANT_A_SGI, | ||
| 309 | RS_COLUMN_SISO_ANT_B_SGI, | ||
| 310 | RS_COLUMN_MIMO2_SGI, | 307 | RS_COLUMN_MIMO2_SGI, |
| 311 | RS_COLUMN_LEGACY_ANT_A, | 308 | RS_COLUMN_LEGACY_ANT_A, |
| 312 | RS_COLUMN_LEGACY_ANT_B, | 309 | RS_COLUMN_LEGACY_ANT_B, |
| 310 | RS_COLUMN_INVALID, | ||
| 311 | RS_COLUMN_INVALID, | ||
| 312 | RS_COLUMN_INVALID, | ||
| 313 | }, | 313 | }, |
| 314 | .checks = { | 314 | .checks = { |
| 315 | rs_mimo_allow, | 315 | rs_mimo_allow, |
| @@ -321,12 +321,12 @@ static const struct rs_tx_column rs_tx_columns[] = { | |||
| 321 | .sgi = true, | 321 | .sgi = true, |
| 322 | .next_columns = { | 322 | .next_columns = { |
| 323 | RS_COLUMN_SISO_ANT_A_SGI, | 323 | RS_COLUMN_SISO_ANT_A_SGI, |
| 324 | RS_COLUMN_SISO_ANT_B_SGI, | ||
| 325 | RS_COLUMN_SISO_ANT_A, | ||
| 326 | RS_COLUMN_SISO_ANT_B, | ||
| 327 | RS_COLUMN_MIMO2, | 324 | RS_COLUMN_MIMO2, |
| 328 | RS_COLUMN_LEGACY_ANT_A, | 325 | RS_COLUMN_LEGACY_ANT_A, |
| 329 | RS_COLUMN_LEGACY_ANT_B, | 326 | RS_COLUMN_LEGACY_ANT_B, |
| 327 | RS_COLUMN_INVALID, | ||
| 328 | RS_COLUMN_INVALID, | ||
| 329 | RS_COLUMN_INVALID, | ||
| 330 | }, | 330 | }, |
| 331 | .checks = { | 331 | .checks = { |
| 332 | rs_mimo_allow, | 332 | rs_mimo_allow, |
| @@ -1335,105 +1335,50 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, | |||
| 1335 | tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw); | 1335 | tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw); |
| 1336 | } | 1336 | } |
| 1337 | 1337 | ||
| 1338 | /* | ||
| 1339 | * Find starting rate for new "search" high-throughput mode of modulation. | ||
| 1340 | * Goal is to find lowest expected rate (under perfect conditions) that is | ||
| 1341 | * above the current measured throughput of "active" mode, to give new mode | ||
| 1342 | * a fair chance to prove itself without too many challenges. | ||
| 1343 | * | ||
| 1344 | * This gets called when transitioning to more aggressive modulation | ||
| 1345 | * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive | ||
| 1346 | * (i.e. MIMO to SISO). When moving to MIMO, bit rate will typically need | ||
| 1347 | * to decrease to match "active" throughput. When moving from MIMO to SISO, | ||
| 1348 | * bit rate will typically need to increase, but not if performance was bad. | ||
| 1349 | */ | ||
| 1350 | static s32 rs_get_best_rate(struct iwl_mvm *mvm, | 1338 | static s32 rs_get_best_rate(struct iwl_mvm *mvm, |
| 1351 | struct iwl_lq_sta *lq_sta, | 1339 | struct iwl_lq_sta *lq_sta, |
| 1352 | struct iwl_scale_tbl_info *tbl, /* "search" */ | 1340 | struct iwl_scale_tbl_info *tbl, /* "search" */ |
| 1353 | u16 rate_mask, s8 index) | 1341 | unsigned long rate_mask, s8 index) |
| 1354 | { | 1342 | { |
| 1355 | /* "active" values */ | ||
| 1356 | struct iwl_scale_tbl_info *active_tbl = | 1343 | struct iwl_scale_tbl_info *active_tbl = |
| 1357 | &(lq_sta->lq_info[lq_sta->active_tbl]); | 1344 | &(lq_sta->lq_info[lq_sta->active_tbl]); |
| 1358 | s32 active_sr = active_tbl->win[index].success_ratio; | 1345 | s32 success_ratio = active_tbl->win[index].success_ratio; |
| 1359 | s32 active_tpt = active_tbl->expected_tpt[index]; | 1346 | u16 expected_current_tpt = active_tbl->expected_tpt[index]; |
| 1360 | /* expected "search" throughput */ | ||
| 1361 | const u16 *tpt_tbl = tbl->expected_tpt; | 1347 | const u16 *tpt_tbl = tbl->expected_tpt; |
| 1362 | |||
| 1363 | s32 new_rate, high, low, start_hi; | ||
| 1364 | u16 high_low; | 1348 | u16 high_low; |
| 1365 | s8 rate = index; | 1349 | u32 target_tpt; |
| 1366 | 1350 | int rate_idx; | |
| 1367 | new_rate = high = low = start_hi = IWL_RATE_INVALID; | ||
| 1368 | |||
| 1369 | while (1) { | ||
| 1370 | high_low = rs_get_adjacent_rate(mvm, rate, rate_mask, | ||
| 1371 | tbl->rate.type); | ||
| 1372 | |||
| 1373 | low = high_low & 0xff; | ||
| 1374 | high = (high_low >> 8) & 0xff; | ||
| 1375 | 1351 | ||
| 1376 | /* | 1352 | if (success_ratio > RS_SR_NO_DECREASE) { |
| 1377 | * Lower the "search" bit rate, to give new "search" mode | 1353 | target_tpt = 100 * expected_current_tpt; |
| 1378 | * approximately the same throughput as "active" if: | 1354 | IWL_DEBUG_RATE(mvm, |
| 1379 | * | 1355 | "SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n", |
| 1380 | * 1) "Active" mode has been working modestly well (but not | 1356 | success_ratio, target_tpt); |
| 1381 | * great), and expected "search" throughput (under perfect | 1357 | } else { |
| 1382 | * conditions) at candidate rate is above the actual | 1358 | target_tpt = lq_sta->last_tpt; |
| 1383 | * measured "active" throughput (but less than expected | 1359 | IWL_DEBUG_RATE(mvm, |
| 1384 | * "active" throughput under perfect conditions). | 1360 | "SR %d not thag good. Find rate exceeding ACTUAL_TPT %d\n", |
| 1385 | * OR | 1361 | success_ratio, target_tpt); |
| 1386 | * 2) "Active" mode has been working perfectly or very well | 1362 | } |
| 1387 | * and expected "search" throughput (under perfect | ||
| 1388 | * conditions) at candidate rate is above expected | ||
| 1389 | * "active" throughput (under perfect conditions). | ||
| 1390 | */ | ||
| 1391 | if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) && | ||
| 1392 | ((active_sr > RS_SR_FORCE_DECREASE) && | ||
| 1393 | (active_sr <= IWL_RATE_HIGH_TH) && | ||
| 1394 | (tpt_tbl[rate] <= active_tpt))) || | ||
| 1395 | ((active_sr >= IWL_RATE_SCALE_SWITCH) && | ||
| 1396 | (tpt_tbl[rate] > active_tpt))) { | ||
| 1397 | /* (2nd or later pass) | ||
| 1398 | * If we've already tried to raise the rate, and are | ||
| 1399 | * now trying to lower it, use the higher rate. */ | ||
| 1400 | if (start_hi != IWL_RATE_INVALID) { | ||
| 1401 | new_rate = start_hi; | ||
| 1402 | break; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | new_rate = rate; | ||
| 1406 | |||
| 1407 | /* Loop again with lower rate */ | ||
| 1408 | if (low != IWL_RATE_INVALID) | ||
| 1409 | rate = low; | ||
| 1410 | 1363 | ||
| 1411 | /* Lower rate not available, use the original */ | 1364 | rate_idx = find_first_bit(&rate_mask, BITS_PER_LONG); |
| 1412 | else | ||
| 1413 | break; | ||
| 1414 | 1365 | ||
| 1415 | /* Else try to raise the "search" rate to match "active" */ | 1366 | while (rate_idx != IWL_RATE_INVALID) { |
| 1416 | } else { | 1367 | if (target_tpt < (100 * tpt_tbl[rate_idx])) |
| 1417 | /* (2nd or later pass) | 1368 | break; |
| 1418 | * If we've already tried to lower the rate, and are | ||
| 1419 | * now trying to raise it, use the lower rate. */ | ||
| 1420 | if (new_rate != IWL_RATE_INVALID) | ||
| 1421 | break; | ||
| 1422 | 1369 | ||
| 1423 | /* Loop again with higher rate */ | 1370 | high_low = rs_get_adjacent_rate(mvm, rate_idx, rate_mask, |
| 1424 | else if (high != IWL_RATE_INVALID) { | 1371 | tbl->rate.type); |
| 1425 | start_hi = high; | ||
| 1426 | rate = high; | ||
| 1427 | 1372 | ||
| 1428 | /* Higher rate not available, use the original */ | 1373 | rate_idx = (high_low >> 8) & 0xff; |
| 1429 | } else { | ||
| 1430 | new_rate = rate; | ||
| 1431 | break; | ||
| 1432 | } | ||
| 1433 | } | ||
| 1434 | } | 1374 | } |
| 1435 | 1375 | ||
| 1436 | return new_rate; | 1376 | IWL_DEBUG_RATE(mvm, "Best rate found %d target_tp %d expected_new %d\n", |
| 1377 | rate_idx, target_tpt, | ||
| 1378 | rate_idx != IWL_RATE_INVALID ? | ||
| 1379 | 100 * tpt_tbl[rate_idx] : IWL_INVALID_VALUE); | ||
| 1380 | |||
| 1381 | return rate_idx; | ||
| 1437 | } | 1382 | } |
| 1438 | 1383 | ||
| 1439 | static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta) | 1384 | static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta) |
| @@ -1608,7 +1553,7 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, | |||
| 1608 | 1553 | ||
| 1609 | tpt = lq_sta->last_tpt / 100; | 1554 | tpt = lq_sta->last_tpt / 100; |
| 1610 | expected_tpt_tbl = rs_get_expected_tpt_table(lq_sta, next_col, | 1555 | expected_tpt_tbl = rs_get_expected_tpt_table(lq_sta, next_col, |
| 1611 | tbl->rate.bw); | 1556 | rs_bw_from_sta_bw(sta)); |
| 1612 | if (WARN_ON_ONCE(!expected_tpt_tbl)) | 1557 | if (WARN_ON_ONCE(!expected_tpt_tbl)) |
| 1613 | continue; | 1558 | continue; |
| 1614 | 1559 | ||
| @@ -1649,7 +1594,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, | |||
| 1649 | const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column]; | 1594 | const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column]; |
| 1650 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1595 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
| 1651 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1596 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
| 1652 | u16 rate_mask = 0; | 1597 | unsigned long rate_mask = 0; |
| 1653 | u32 rate_idx = 0; | 1598 | u32 rate_idx = 0; |
| 1654 | 1599 | ||
| 1655 | memcpy(search_tbl, tbl, sz); | 1600 | memcpy(search_tbl, tbl, sz); |
| @@ -1691,7 +1636,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, | |||
| 1691 | !(BIT(rate_idx) & rate_mask)) { | 1636 | !(BIT(rate_idx) & rate_mask)) { |
| 1692 | IWL_DEBUG_RATE(mvm, | 1637 | IWL_DEBUG_RATE(mvm, |
| 1693 | "can not switch with index %d" | 1638 | "can not switch with index %d" |
| 1694 | " rate mask %x\n", | 1639 | " rate mask %lx\n", |
| 1695 | rate_idx, rate_mask); | 1640 | rate_idx, rate_mask); |
| 1696 | 1641 | ||
| 1697 | goto err; | 1642 | goto err; |
| @@ -1805,16 +1750,21 @@ static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index, | |||
| 1805 | *stronger = TPC_INVALID; | 1750 | *stronger = TPC_INVALID; |
| 1806 | } | 1751 | } |
| 1807 | 1752 | ||
| 1808 | static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct rs_rate *rate, | 1753 | static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| 1809 | enum ieee80211_band band) | 1754 | struct rs_rate *rate, enum ieee80211_band band) |
| 1810 | { | 1755 | { |
| 1811 | int index = rate->index; | 1756 | int index = rate->index; |
| 1757 | bool cam = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM); | ||
| 1758 | bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION && | ||
| 1759 | !vif->bss_conf.ps); | ||
| 1812 | 1760 | ||
| 1761 | IWL_DEBUG_RATE(mvm, "cam: %d sta_ps_disabled %d\n", | ||
| 1762 | cam, sta_ps_disabled); | ||
| 1813 | /* | 1763 | /* |
| 1814 | * allow tpc only if power management is enabled, or bt coex | 1764 | * allow tpc only if power management is enabled, or bt coex |
| 1815 | * activity grade allows it and we are on 2.4Ghz. | 1765 | * activity grade allows it and we are on 2.4Ghz. |
| 1816 | */ | 1766 | */ |
| 1817 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM && | 1767 | if ((cam || sta_ps_disabled) && |
| 1818 | !iwl_mvm_bt_coex_is_tpc_allowed(mvm, band)) | 1768 | !iwl_mvm_bt_coex_is_tpc_allowed(mvm, band)) |
| 1819 | return false; | 1769 | return false; |
| 1820 | 1770 | ||
| @@ -1916,7 +1866,7 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm, | |||
| 1916 | 1866 | ||
| 1917 | #ifdef CONFIG_MAC80211_DEBUGFS | 1867 | #ifdef CONFIG_MAC80211_DEBUGFS |
| 1918 | if (lq_sta->dbg_fixed_txp_reduction <= TPC_MAX_REDUCTION) { | 1868 | if (lq_sta->dbg_fixed_txp_reduction <= TPC_MAX_REDUCTION) { |
| 1919 | IWL_DEBUG_RATE(mvm, "fixed tpc: %d", | 1869 | IWL_DEBUG_RATE(mvm, "fixed tpc: %d\n", |
| 1920 | lq_sta->dbg_fixed_txp_reduction); | 1870 | lq_sta->dbg_fixed_txp_reduction); |
| 1921 | lq_sta->lq.reduced_tpc = lq_sta->dbg_fixed_txp_reduction; | 1871 | lq_sta->lq.reduced_tpc = lq_sta->dbg_fixed_txp_reduction; |
| 1922 | return cur != lq_sta->dbg_fixed_txp_reduction; | 1872 | return cur != lq_sta->dbg_fixed_txp_reduction; |
| @@ -1931,9 +1881,9 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm, | |||
| 1931 | band = chanctx_conf->def.chan->band; | 1881 | band = chanctx_conf->def.chan->band; |
| 1932 | rcu_read_unlock(); | 1882 | rcu_read_unlock(); |
| 1933 | 1883 | ||
| 1934 | if (!rs_tpc_allowed(mvm, rate, band)) { | 1884 | if (!rs_tpc_allowed(mvm, vif, rate, band)) { |
| 1935 | IWL_DEBUG_RATE(mvm, | 1885 | IWL_DEBUG_RATE(mvm, |
| 1936 | "tpc is not allowed. remove txp restrictions"); | 1886 | "tpc is not allowed. remove txp restrictions\n"); |
| 1937 | lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION; | 1887 | lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION; |
| 1938 | return cur != TPC_NO_REDUCTION; | 1888 | return cur != TPC_NO_REDUCTION; |
| 1939 | } | 1889 | } |
| @@ -1959,12 +1909,12 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm, | |||
| 1959 | 1909 | ||
| 1960 | /* override actions if we are on the edge */ | 1910 | /* override actions if we are on the edge */ |
| 1961 | if (weak == TPC_INVALID && action == TPC_ACTION_DECREASE) { | 1911 | if (weak == TPC_INVALID && action == TPC_ACTION_DECREASE) { |
| 1962 | IWL_DEBUG_RATE(mvm, "already in lowest txp, stay"); | 1912 | IWL_DEBUG_RATE(mvm, "already in lowest txp, stay\n"); |
| 1963 | action = TPC_ACTION_STAY; | 1913 | action = TPC_ACTION_STAY; |
| 1964 | } else if (strong == TPC_INVALID && | 1914 | } else if (strong == TPC_INVALID && |
| 1965 | (action == TPC_ACTION_INCREASE || | 1915 | (action == TPC_ACTION_INCREASE || |
| 1966 | action == TPC_ACTION_NO_RESTIRCTION)) { | 1916 | action == TPC_ACTION_NO_RESTIRCTION)) { |
| 1967 | IWL_DEBUG_RATE(mvm, "already in highest txp, stay"); | 1917 | IWL_DEBUG_RATE(mvm, "already in highest txp, stay\n"); |
| 1968 | action = TPC_ACTION_STAY; | 1918 | action = TPC_ACTION_STAY; |
| 1969 | } | 1919 | } |
| 1970 | 1920 | ||
| @@ -2235,7 +2185,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 2235 | break; | 2185 | break; |
| 2236 | case RS_ACTION_STAY: | 2186 | case RS_ACTION_STAY: |
| 2237 | /* No change */ | 2187 | /* No change */ |
| 2238 | update_lq = rs_tpc_perform(mvm, sta, lq_sta, tbl); | 2188 | if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) |
| 2189 | update_lq = rs_tpc_perform(mvm, sta, lq_sta, tbl); | ||
| 2239 | break; | 2190 | break; |
| 2240 | default: | 2191 | default: |
| 2241 | break; | 2192 | break; |
| @@ -2489,10 +2440,6 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, | |||
| 2489 | if (i == IWL_RATE_9M_INDEX) | 2440 | if (i == IWL_RATE_9M_INDEX) |
| 2490 | continue; | 2441 | continue; |
| 2491 | 2442 | ||
| 2492 | /* Disable MCS9 as a workaround */ | ||
| 2493 | if (i == IWL_RATE_MCS_9_INDEX) | ||
| 2494 | continue; | ||
| 2495 | |||
| 2496 | /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ | 2443 | /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ |
| 2497 | if (i == IWL_RATE_MCS_9_INDEX && | 2444 | if (i == IWL_RATE_MCS_9_INDEX && |
| 2498 | sta->bandwidth == IEEE80211_STA_RX_BW_20) | 2445 | sta->bandwidth == IEEE80211_STA_RX_BW_20) |
| @@ -2511,10 +2458,6 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, | |||
| 2511 | if (i == IWL_RATE_9M_INDEX) | 2458 | if (i == IWL_RATE_9M_INDEX) |
| 2512 | continue; | 2459 | continue; |
| 2513 | 2460 | ||
| 2514 | /* Disable MCS9 as a workaround */ | ||
| 2515 | if (i == IWL_RATE_MCS_9_INDEX) | ||
| 2516 | continue; | ||
| 2517 | |||
| 2518 | /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ | 2461 | /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */ |
| 2519 | if (i == IWL_RATE_MCS_9_INDEX && | 2462 | if (i == IWL_RATE_MCS_9_INDEX && |
| 2520 | sta->bandwidth == IEEE80211_STA_RX_BW_20) | 2463 | sta->bandwidth == IEEE80211_STA_RX_BW_20) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 36ae01a18dee..4b6c7d4bd199 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
| @@ -306,7 +306,6 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
| 306 | .id = SCAN_REQUEST_CMD, | 306 | .id = SCAN_REQUEST_CMD, |
| 307 | .len = { 0, }, | 307 | .len = { 0, }, |
| 308 | .data = { mvm->scan_cmd, }, | 308 | .data = { mvm->scan_cmd, }, |
| 309 | .flags = CMD_SYNC, | ||
| 310 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, | 309 | .dataflags = { IWL_HCMD_DFL_NOCOPY, }, |
| 311 | }; | 310 | }; |
| 312 | struct iwl_scan_cmd *cmd = mvm->scan_cmd; | 311 | struct iwl_scan_cmd *cmd = mvm->scan_cmd; |
| @@ -517,7 +516,7 @@ int iwl_mvm_cancel_scan(struct iwl_mvm *mvm) | |||
| 517 | ARRAY_SIZE(scan_abort_notif), | 516 | ARRAY_SIZE(scan_abort_notif), |
| 518 | iwl_mvm_scan_abort_notif, NULL); | 517 | iwl_mvm_scan_abort_notif, NULL); |
| 519 | 518 | ||
| 520 | ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD, CMD_SYNC, 0, NULL); | 519 | ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD, 0, 0, NULL); |
| 521 | if (ret) { | 520 | if (ret) { |
| 522 | IWL_ERR(mvm, "Couldn't send SCAN_ABORT_CMD: %d\n", ret); | 521 | IWL_ERR(mvm, "Couldn't send SCAN_ABORT_CMD: %d\n", ret); |
| 523 | /* mac80211's state will be cleaned in the nic_restart flow */ | 522 | /* mac80211's state will be cleaned in the nic_restart flow */ |
| @@ -749,7 +748,6 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
| 749 | struct iwl_scan_offload_cfg *scan_cfg; | 748 | struct iwl_scan_offload_cfg *scan_cfg; |
| 750 | struct iwl_host_cmd cmd = { | 749 | struct iwl_host_cmd cmd = { |
| 751 | .id = SCAN_OFFLOAD_CONFIG_CMD, | 750 | .id = SCAN_OFFLOAD_CONFIG_CMD, |
| 752 | .flags = CMD_SYNC, | ||
| 753 | }; | 751 | }; |
| 754 | struct iwl_mvm_scan_params params = {}; | 752 | struct iwl_mvm_scan_params params = {}; |
| 755 | 753 | ||
| @@ -807,7 +805,6 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, | |||
| 807 | struct iwl_scan_offload_blacklist *blacklist; | 805 | struct iwl_scan_offload_blacklist *blacklist; |
| 808 | struct iwl_host_cmd cmd = { | 806 | struct iwl_host_cmd cmd = { |
| 809 | .id = SCAN_OFFLOAD_UPDATE_PROFILES_CMD, | 807 | .id = SCAN_OFFLOAD_UPDATE_PROFILES_CMD, |
| 810 | .flags = CMD_SYNC, | ||
| 811 | .len[1] = sizeof(*profile_cfg), | 808 | .len[1] = sizeof(*profile_cfg), |
| 812 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | 809 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, |
| 813 | .dataflags[1] = IWL_HCMD_DFL_NOCOPY, | 810 | .dataflags[1] = IWL_HCMD_DFL_NOCOPY, |
| @@ -898,7 +895,7 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | |||
| 898 | scan_req.flags |= | 895 | scan_req.flags |= |
| 899 | cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE); | 896 | cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE); |
| 900 | 897 | ||
| 901 | return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, CMD_SYNC, | 898 | return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, 0, |
| 902 | sizeof(scan_req), &scan_req); | 899 | sizeof(scan_req), &scan_req); |
| 903 | } | 900 | } |
| 904 | 901 | ||
| @@ -907,7 +904,6 @@ static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm) | |||
| 907 | int ret; | 904 | int ret; |
| 908 | struct iwl_host_cmd cmd = { | 905 | struct iwl_host_cmd cmd = { |
| 909 | .id = SCAN_OFFLOAD_ABORT_CMD, | 906 | .id = SCAN_OFFLOAD_ABORT_CMD, |
| 910 | .flags = CMD_SYNC, | ||
| 911 | }; | 907 | }; |
| 912 | u32 status; | 908 | u32 status; |
| 913 | 909 | ||
| @@ -936,7 +932,7 @@ static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm) | |||
| 936 | return ret; | 932 | return ret; |
| 937 | } | 933 | } |
| 938 | 934 | ||
| 939 | int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm) | 935 | int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm, bool notify) |
| 940 | { | 936 | { |
| 941 | int ret; | 937 | int ret; |
| 942 | struct iwl_notification_wait wait_scan_done; | 938 | struct iwl_notification_wait wait_scan_done; |
| @@ -974,5 +970,8 @@ int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm) | |||
| 974 | */ | 970 | */ |
| 975 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 971 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
| 976 | 972 | ||
| 973 | if (notify) | ||
| 974 | ieee80211_sched_scan_stopped(mvm->hw); | ||
| 975 | |||
| 977 | return 0; | 976 | return 0; |
| 978 | } | 977 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 3e11b9d802e7..1fb01ea2e704 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
| @@ -327,7 +327,7 @@ static int iwl_mvm_rm_sta_common(struct iwl_mvm *mvm, u8 sta_id) | |||
| 327 | return -EINVAL; | 327 | return -EINVAL; |
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | ret = iwl_mvm_send_cmd_pdu(mvm, REMOVE_STA, CMD_SYNC, | 330 | ret = iwl_mvm_send_cmd_pdu(mvm, REMOVE_STA, 0, |
| 331 | sizeof(rm_sta_cmd), &rm_sta_cmd); | 331 | sizeof(rm_sta_cmd), &rm_sta_cmd); |
| 332 | if (ret) { | 332 | if (ret) { |
| 333 | IWL_ERR(mvm, "Failed to remove station. Id=%d\n", sta_id); | 333 | IWL_ERR(mvm, "Failed to remove station. Id=%d\n", sta_id); |
| @@ -1053,12 +1053,12 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
| 1053 | cmd.sta_id = sta_id; | 1053 | cmd.sta_id = sta_id; |
| 1054 | 1054 | ||
| 1055 | status = ADD_STA_SUCCESS; | 1055 | status = ADD_STA_SUCCESS; |
| 1056 | if (cmd_flags == CMD_SYNC) | 1056 | if (cmd_flags & CMD_ASYNC) |
| 1057 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd), | ||
| 1058 | &cmd, &status); | ||
| 1059 | else | ||
| 1060 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, CMD_ASYNC, | 1057 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, CMD_ASYNC, |
| 1061 | sizeof(cmd), &cmd); | 1058 | sizeof(cmd), &cmd); |
| 1059 | else | ||
| 1060 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd), | ||
| 1061 | &cmd, &status); | ||
| 1062 | 1062 | ||
| 1063 | switch (status) { | 1063 | switch (status) { |
| 1064 | case ADD_STA_SUCCESS: | 1064 | case ADD_STA_SUCCESS: |
| @@ -1111,7 +1111,7 @@ static int iwl_mvm_send_sta_igtk(struct iwl_mvm *mvm, | |||
| 1111 | remove_key ? "removing" : "installing", | 1111 | remove_key ? "removing" : "installing", |
| 1112 | igtk_cmd.sta_id); | 1112 | igtk_cmd.sta_id); |
| 1113 | 1113 | ||
| 1114 | return iwl_mvm_send_cmd_pdu(mvm, MGMT_MCAST_KEY, CMD_SYNC, | 1114 | return iwl_mvm_send_cmd_pdu(mvm, MGMT_MCAST_KEY, 0, |
| 1115 | sizeof(igtk_cmd), &igtk_cmd); | 1115 | sizeof(igtk_cmd), &igtk_cmd); |
| 1116 | } | 1116 | } |
| 1117 | 1117 | ||
| @@ -1198,15 +1198,15 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, | |||
| 1198 | ieee80211_get_key_rx_seq(keyconf, 0, &seq); | 1198 | ieee80211_get_key_rx_seq(keyconf, 0, &seq); |
| 1199 | ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k); | 1199 | ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k); |
| 1200 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id, | 1200 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id, |
| 1201 | seq.tkip.iv32, p1k, CMD_SYNC); | 1201 | seq.tkip.iv32, p1k, 0); |
| 1202 | break; | 1202 | break; |
| 1203 | case WLAN_CIPHER_SUITE_CCMP: | 1203 | case WLAN_CIPHER_SUITE_CCMP: |
| 1204 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id, | 1204 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id, |
| 1205 | 0, NULL, CMD_SYNC); | 1205 | 0, NULL, 0); |
| 1206 | break; | 1206 | break; |
| 1207 | default: | 1207 | default: |
| 1208 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, | 1208 | ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, |
| 1209 | sta_id, 0, NULL, CMD_SYNC); | 1209 | sta_id, 0, NULL, 0); |
| 1210 | } | 1210 | } |
| 1211 | 1211 | ||
| 1212 | if (ret) | 1212 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index e5e3071ff252..d98e8a2142b8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h | |||
| @@ -287,8 +287,6 @@ static inline u16 iwl_mvm_tid_queued(struct iwl_mvm_tid_data *tid_data) | |||
| 287 | * @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for | 287 | * @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for |
| 288 | * tid. | 288 | * tid. |
| 289 | * @max_agg_bufsize: the maximal size of the AGG buffer for this station | 289 | * @max_agg_bufsize: the maximal size of the AGG buffer for this station |
| 290 | * @bt_reduced_txpower_dbg: debug mode in which %bt_reduced_txpower is forced | ||
| 291 | * by debugfs. | ||
| 292 | * @bt_reduced_txpower: is reduced tx power enabled for this station | 290 | * @bt_reduced_txpower: is reduced tx power enabled for this station |
| 293 | * @next_status_eosp: the next reclaimed packet is a PS-Poll response and | 291 | * @next_status_eosp: the next reclaimed packet is a PS-Poll response and |
| 294 | * we need to signal the EOSP | 292 | * we need to signal the EOSP |
| @@ -309,7 +307,6 @@ struct iwl_mvm_sta { | |||
| 309 | u32 mac_id_n_color; | 307 | u32 mac_id_n_color; |
| 310 | u16 tid_disable_agg; | 308 | u16 tid_disable_agg; |
| 311 | u8 max_agg_bufsize; | 309 | u8 max_agg_bufsize; |
| 312 | bool bt_reduced_txpower_dbg; | ||
| 313 | bool bt_reduced_txpower; | 310 | bool bt_reduced_txpower; |
| 314 | bool next_status_eosp; | 311 | bool next_status_eosp; |
| 315 | spinlock_t lock; | 312 | spinlock_t lock; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index a9402937f767..80100f6cc12a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
| @@ -312,7 +312,7 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, | |||
| 312 | ARRAY_SIZE(time_event_response), | 312 | ARRAY_SIZE(time_event_response), |
| 313 | iwl_mvm_time_event_response, te_data); | 313 | iwl_mvm_time_event_response, te_data); |
| 314 | 314 | ||
| 315 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | 315 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0, |
| 316 | sizeof(*te_cmd), te_cmd); | 316 | sizeof(*te_cmd), te_cmd); |
| 317 | if (ret) { | 317 | if (ret) { |
| 318 | IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret); | 318 | IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret); |
| @@ -434,7 +434,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm, | |||
| 434 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); | 434 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); |
| 435 | 435 | ||
| 436 | IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); | 436 | IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); |
| 437 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, | 437 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0, |
| 438 | sizeof(time_cmd), &time_cmd); | 438 | sizeof(time_cmd), &time_cmd); |
| 439 | if (WARN_ON(ret)) | 439 | if (WARN_ON(ret)) |
| 440 | return; | 440 | return; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index 39a3e03a0acd..868561512783 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c | |||
| @@ -409,7 +409,6 @@ void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff) | |||
| 409 | .id = REPLY_THERMAL_MNG_BACKOFF, | 409 | .id = REPLY_THERMAL_MNG_BACKOFF, |
| 410 | .len = { sizeof(u32), }, | 410 | .len = { sizeof(u32), }, |
| 411 | .data = { &backoff, }, | 411 | .data = { &backoff, }, |
| 412 | .flags = CMD_SYNC, | ||
| 413 | }; | 412 | }; |
| 414 | 413 | ||
| 415 | backoff = max(backoff, mvm->thermal_throttle.min_backoff); | 414 | backoff = max(backoff, mvm->thermal_throttle.min_backoff); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index ff1b630e130e..3846a6c41eb1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
| @@ -958,7 +958,7 @@ int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync) | |||
| 958 | .flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH), | 958 | .flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH), |
| 959 | }; | 959 | }; |
| 960 | 960 | ||
| 961 | u32 flags = sync ? CMD_SYNC : CMD_ASYNC; | 961 | u32 flags = sync ? 0 : CMD_ASYNC; |
| 962 | 962 | ||
| 963 | ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags, | 963 | ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags, |
| 964 | sizeof(flush_cmd), &flush_cmd); | 964 | sizeof(flush_cmd), &flush_cmd); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index eb2ca64820fc..aa9fc77e8413 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
| @@ -144,7 +144,7 @@ int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd, | |||
| 144 | "cmd flags %x", cmd->flags)) | 144 | "cmd flags %x", cmd->flags)) |
| 145 | return -EINVAL; | 145 | return -EINVAL; |
| 146 | 146 | ||
| 147 | cmd->flags |= CMD_SYNC | CMD_WANT_SKB; | 147 | cmd->flags |= CMD_WANT_SKB; |
| 148 | 148 | ||
| 149 | ret = iwl_trans_send_cmd(mvm->trans, cmd); | 149 | ret = iwl_trans_send_cmd(mvm->trans, cmd); |
| 150 | if (ret == -ERFKILL) { | 150 | if (ret == -ERFKILL) { |
| @@ -519,6 +519,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | |||
| 519 | iwl_mvm_dump_umac_error_log(mvm); | 519 | iwl_mvm_dump_umac_error_log(mvm); |
| 520 | } | 520 | } |
| 521 | 521 | ||
| 522 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
| 522 | void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm) | 523 | void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm) |
| 523 | { | 524 | { |
| 524 | const struct fw_img *img; | 525 | const struct fw_img *img; |
| @@ -581,6 +582,7 @@ void iwl_mvm_fw_error_rxf_dump(struct iwl_mvm *mvm) | |||
| 581 | } | 582 | } |
| 582 | iwl_trans_release_nic_access(mvm->trans, &flags); | 583 | iwl_trans_release_nic_access(mvm->trans, &flags); |
| 583 | } | 584 | } |
| 585 | #endif | ||
| 584 | 586 | ||
| 585 | /** | 587 | /** |
| 586 | * iwl_mvm_send_lq_cmd() - Send link quality command | 588 | * iwl_mvm_send_lq_cmd() - Send link quality command |
| @@ -597,7 +599,7 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init) | |||
| 597 | struct iwl_host_cmd cmd = { | 599 | struct iwl_host_cmd cmd = { |
| 598 | .id = LQ_CMD, | 600 | .id = LQ_CMD, |
| 599 | .len = { sizeof(struct iwl_lq_cmd), }, | 601 | .len = { sizeof(struct iwl_lq_cmd), }, |
| 600 | .flags = init ? CMD_SYNC : CMD_ASYNC, | 602 | .flags = init ? 0 : CMD_ASYNC, |
| 601 | .data = { lq, }, | 603 | .data = { lq, }, |
| 602 | }; | 604 | }; |
| 603 | 605 | ||
| @@ -648,6 +650,39 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 648 | ieee80211_request_smps(vif, smps_mode); | 650 | ieee80211_request_smps(vif, smps_mode); |
| 649 | } | 651 | } |
| 650 | 652 | ||
| 653 | static void iwl_mvm_diversity_iter(void *_data, u8 *mac, | ||
| 654 | struct ieee80211_vif *vif) | ||
| 655 | { | ||
| 656 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 657 | bool *result = _data; | ||
| 658 | int i; | ||
| 659 | |||
| 660 | for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { | ||
| 661 | if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC || | ||
| 662 | mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) | ||
| 663 | *result = false; | ||
| 664 | } | ||
| 665 | } | ||
| 666 | |||
| 667 | bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm) | ||
| 668 | { | ||
| 669 | bool result = true; | ||
| 670 | |||
| 671 | lockdep_assert_held(&mvm->mutex); | ||
| 672 | |||
| 673 | if (num_of_ant(mvm->fw->valid_rx_ant) == 1) | ||
| 674 | return false; | ||
| 675 | |||
| 676 | if (!mvm->cfg->rx_with_siso_diversity) | ||
| 677 | return false; | ||
| 678 | |||
| 679 | ieee80211_iterate_active_interfaces_atomic( | ||
| 680 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
| 681 | iwl_mvm_diversity_iter, &result); | ||
| 682 | |||
| 683 | return result; | ||
| 684 | } | ||
| 685 | |||
| 651 | int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 686 | int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| 652 | bool value) | 687 | bool value) |
| 653 | { | 688 | { |
| @@ -667,7 +702,7 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 667 | 702 | ||
| 668 | iwl_mvm_bt_coex_vif_change(mvm); | 703 | iwl_mvm_bt_coex_vif_change(mvm); |
| 669 | 704 | ||
| 670 | return iwl_mvm_power_update_mac(mvm, vif); | 705 | return iwl_mvm_power_update_mac(mvm); |
| 671 | } | 706 | } |
| 672 | 707 | ||
| 673 | static void iwl_mvm_ll_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) | 708 | static void iwl_mvm_ll_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) |
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 3d1d57f9f5bc..7091a18d5a72 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
| @@ -417,7 +417,7 @@ static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx) | |||
| 417 | splx->package.count != 2 || | 417 | splx->package.count != 2 || |
| 418 | splx->package.elements[0].type != ACPI_TYPE_INTEGER || | 418 | splx->package.elements[0].type != ACPI_TYPE_INTEGER || |
| 419 | splx->package.elements[0].integer.value != 0) { | 419 | splx->package.elements[0].integer.value != 0) { |
| 420 | IWL_ERR(trans, "Unsupported splx structure"); | 420 | IWL_ERR(trans, "Unsupported splx structure\n"); |
| 421 | return 0; | 421 | return 0; |
| 422 | } | 422 | } |
| 423 | 423 | ||
| @@ -426,14 +426,14 @@ static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx) | |||
| 426 | limits->package.count < 2 || | 426 | limits->package.count < 2 || |
| 427 | limits->package.elements[0].type != ACPI_TYPE_INTEGER || | 427 | limits->package.elements[0].type != ACPI_TYPE_INTEGER || |
| 428 | limits->package.elements[1].type != ACPI_TYPE_INTEGER) { | 428 | limits->package.elements[1].type != ACPI_TYPE_INTEGER) { |
| 429 | IWL_ERR(trans, "Invalid limits element"); | 429 | IWL_ERR(trans, "Invalid limits element\n"); |
| 430 | return 0; | 430 | return 0; |
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | domain_type = &limits->package.elements[0]; | 433 | domain_type = &limits->package.elements[0]; |
| 434 | power_limit = &limits->package.elements[1]; | 434 | power_limit = &limits->package.elements[1]; |
| 435 | if (!(domain_type->integer.value & SPL_DOMAINTYPE_WIFI)) { | 435 | if (!(domain_type->integer.value & SPL_DOMAINTYPE_WIFI)) { |
| 436 | IWL_DEBUG_INFO(trans, "WiFi power is not limited"); | 436 | IWL_DEBUG_INFO(trans, "WiFi power is not limited\n"); |
| 437 | return 0; | 437 | return 0; |
| 438 | } | 438 | } |
| 439 | 439 | ||
| @@ -450,26 +450,26 @@ static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev) | |||
| 450 | pxsx_handle = ACPI_HANDLE(&pdev->dev); | 450 | pxsx_handle = ACPI_HANDLE(&pdev->dev); |
| 451 | if (!pxsx_handle) { | 451 | if (!pxsx_handle) { |
| 452 | IWL_DEBUG_INFO(trans, | 452 | IWL_DEBUG_INFO(trans, |
| 453 | "Could not retrieve root port ACPI handle"); | 453 | "Could not retrieve root port ACPI handle\n"); |
| 454 | return; | 454 | return; |
| 455 | } | 455 | } |
| 456 | 456 | ||
| 457 | /* Get the method's handle */ | 457 | /* Get the method's handle */ |
| 458 | status = acpi_get_handle(pxsx_handle, (acpi_string)SPL_METHOD, &handle); | 458 | status = acpi_get_handle(pxsx_handle, (acpi_string)SPL_METHOD, &handle); |
| 459 | if (ACPI_FAILURE(status)) { | 459 | if (ACPI_FAILURE(status)) { |
| 460 | IWL_DEBUG_INFO(trans, "SPL method not found"); | 460 | IWL_DEBUG_INFO(trans, "SPL method not found\n"); |
| 461 | return; | 461 | return; |
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | /* Call SPLC with no arguments */ | 464 | /* Call SPLC with no arguments */ |
| 465 | status = acpi_evaluate_object(handle, NULL, NULL, &splx); | 465 | status = acpi_evaluate_object(handle, NULL, NULL, &splx); |
| 466 | if (ACPI_FAILURE(status)) { | 466 | if (ACPI_FAILURE(status)) { |
| 467 | IWL_ERR(trans, "SPLC invocation failed (0x%x)", status); | 467 | IWL_ERR(trans, "SPLC invocation failed (0x%x)\n", status); |
| 468 | return; | 468 | return; |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | trans->dflt_pwr_limit = splx_get_pwr_limit(trans, splx.pointer); | 471 | trans->dflt_pwr_limit = splx_get_pwr_limit(trans, splx.pointer); |
| 472 | IWL_DEBUG_INFO(trans, "Default power limit set to %lld", | 472 | IWL_DEBUG_INFO(trans, "Default power limit set to %lld\n", |
| 473 | trans->dflt_pwr_limit); | 473 | trans->dflt_pwr_limit); |
| 474 | kfree(splx.pointer); | 474 | kfree(splx.pointer); |
| 475 | } | 475 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 1b95d856dfd5..6c22b23a2845 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
| @@ -117,21 +117,19 @@ struct iwl_dma_ptr { | |||
| 117 | /** | 117 | /** |
| 118 | * iwl_queue_inc_wrap - increment queue index, wrap back to beginning | 118 | * iwl_queue_inc_wrap - increment queue index, wrap back to beginning |
| 119 | * @index -- current index | 119 | * @index -- current index |
| 120 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
| 121 | */ | 120 | */ |
| 122 | static inline int iwl_queue_inc_wrap(int index, int n_bd) | 121 | static inline int iwl_queue_inc_wrap(int index) |
| 123 | { | 122 | { |
| 124 | return ++index & (n_bd - 1); | 123 | return ++index & (TFD_QUEUE_SIZE_MAX - 1); |
| 125 | } | 124 | } |
| 126 | 125 | ||
| 127 | /** | 126 | /** |
| 128 | * iwl_queue_dec_wrap - decrement queue index, wrap back to end | 127 | * iwl_queue_dec_wrap - decrement queue index, wrap back to end |
| 129 | * @index -- current index | 128 | * @index -- current index |
| 130 | * @n_bd -- total number of entries in queue (must be power of 2) | ||
| 131 | */ | 129 | */ |
| 132 | static inline int iwl_queue_dec_wrap(int index, int n_bd) | 130 | static inline int iwl_queue_dec_wrap(int index) |
| 133 | { | 131 | { |
| 134 | return --index & (n_bd - 1); | 132 | return --index & (TFD_QUEUE_SIZE_MAX - 1); |
| 135 | } | 133 | } |
| 136 | 134 | ||
| 137 | struct iwl_cmd_meta { | 135 | struct iwl_cmd_meta { |
| @@ -145,13 +143,13 @@ struct iwl_cmd_meta { | |||
| 145 | * | 143 | * |
| 146 | * Contains common data for Rx and Tx queues. | 144 | * Contains common data for Rx and Tx queues. |
| 147 | * | 145 | * |
| 148 | * Note the difference between n_bd and n_window: the hardware | 146 | * Note the difference between TFD_QUEUE_SIZE_MAX and n_window: the hardware |
| 149 | * always assumes 256 descriptors, so n_bd is always 256 (unless | 147 | * always assumes 256 descriptors, so TFD_QUEUE_SIZE_MAX is always 256 (unless |
| 150 | * there might be HW changes in the future). For the normal TX | 148 | * there might be HW changes in the future). For the normal TX |
| 151 | * queues, n_window, which is the size of the software queue data | 149 | * queues, n_window, which is the size of the software queue data |
| 152 | * is also 256; however, for the command queue, n_window is only | 150 | * is also 256; however, for the command queue, n_window is only |
| 153 | * 32 since we don't need so many commands pending. Since the HW | 151 | * 32 since we don't need so many commands pending. Since the HW |
| 154 | * still uses 256 BDs for DMA though, n_bd stays 256. As a result, | 152 | * still uses 256 BDs for DMA though, TFD_QUEUE_SIZE_MAX stays 256. As a result, |
| 155 | * the software buffers (in the variables @meta, @txb in struct | 153 | * the software buffers (in the variables @meta, @txb in struct |
| 156 | * iwl_txq) only have 32 entries, while the HW buffers (@tfds in | 154 | * iwl_txq) only have 32 entries, while the HW buffers (@tfds in |
| 157 | * the same struct) have 256. | 155 | * the same struct) have 256. |
| @@ -162,7 +160,6 @@ struct iwl_cmd_meta { | |||
| 162 | * data is a window overlayed over the HW queue. | 160 | * data is a window overlayed over the HW queue. |
| 163 | */ | 161 | */ |
| 164 | struct iwl_queue { | 162 | struct iwl_queue { |
| 165 | int n_bd; /* number of BDs in this queue */ | ||
| 166 | int write_ptr; /* 1-st empty entry (index) host_w*/ | 163 | int write_ptr; /* 1-st empty entry (index) host_w*/ |
| 167 | int read_ptr; /* last used entry (index) host_r*/ | 164 | int read_ptr; /* last used entry (index) host_r*/ |
| 168 | /* use for monitoring and recovering the stuck queue */ | 165 | /* use for monitoring and recovering the stuck queue */ |
| @@ -373,6 +370,13 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
| 373 | struct sk_buff_head *skbs); | 370 | struct sk_buff_head *skbs); |
| 374 | void iwl_trans_pcie_tx_reset(struct iwl_trans *trans); | 371 | void iwl_trans_pcie_tx_reset(struct iwl_trans *trans); |
| 375 | 372 | ||
| 373 | static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) | ||
| 374 | { | ||
| 375 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; | ||
| 376 | |||
| 377 | return le16_to_cpu(tb->hi_n_len) >> 4; | ||
| 378 | } | ||
| 379 | |||
| 376 | /***************************************************** | 380 | /***************************************************** |
| 377 | * Error handling | 381 | * Error handling |
| 378 | ******************************************************/ | 382 | ******************************************************/ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 4a26a082a1ba..a2698e5e062c 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
| @@ -850,7 +850,7 @@ static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans) | |||
| 850 | trans_pcie->ict_index, read); | 850 | trans_pcie->ict_index, read); |
| 851 | trans_pcie->ict_tbl[trans_pcie->ict_index] = 0; | 851 | trans_pcie->ict_tbl[trans_pcie->ict_index] = 0; |
| 852 | trans_pcie->ict_index = | 852 | trans_pcie->ict_index = |
| 853 | iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT); | 853 | ((trans_pcie->ict_index + 1) & (ICT_COUNT - 1)); |
| 854 | 854 | ||
| 855 | read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); | 855 | read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); |
| 856 | trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, | 856 | trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index c76b148e1aba..788085bc65d7 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
| @@ -73,6 +73,7 @@ | |||
| 73 | #include "iwl-csr.h" | 73 | #include "iwl-csr.h" |
| 74 | #include "iwl-prph.h" | 74 | #include "iwl-prph.h" |
| 75 | #include "iwl-agn-hw.h" | 75 | #include "iwl-agn-hw.h" |
| 76 | #include "iwl-fw-error-dump.h" | ||
| 76 | #include "internal.h" | 77 | #include "internal.h" |
| 77 | 78 | ||
| 78 | static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg) | 79 | static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg) |
| @@ -453,6 +454,7 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) | |||
| 453 | { | 454 | { |
| 454 | int ret; | 455 | int ret; |
| 455 | int t = 0; | 456 | int t = 0; |
| 457 | int iter; | ||
| 456 | 458 | ||
| 457 | IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); | 459 | IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); |
| 458 | 460 | ||
| @@ -461,18 +463,23 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) | |||
| 461 | if (ret >= 0) | 463 | if (ret >= 0) |
| 462 | return 0; | 464 | return 0; |
| 463 | 465 | ||
| 464 | /* If HW is not ready, prepare the conditions to check again */ | 466 | for (iter = 0; iter < 10; iter++) { |
| 465 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | 467 | /* If HW is not ready, prepare the conditions to check again */ |
| 466 | CSR_HW_IF_CONFIG_REG_PREPARE); | 468 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, |
| 469 | CSR_HW_IF_CONFIG_REG_PREPARE); | ||
| 470 | |||
| 471 | do { | ||
| 472 | ret = iwl_pcie_set_hw_ready(trans); | ||
| 473 | if (ret >= 0) | ||
| 474 | return 0; | ||
| 467 | 475 | ||
| 468 | do { | 476 | usleep_range(200, 1000); |
| 469 | ret = iwl_pcie_set_hw_ready(trans); | 477 | t += 200; |
| 470 | if (ret >= 0) | 478 | } while (t < 150000); |
| 471 | return 0; | 479 | msleep(25); |
| 480 | } | ||
| 472 | 481 | ||
| 473 | usleep_range(200, 1000); | 482 | IWL_DEBUG_INFO(trans, "got NIC after %d iterations\n", iter); |
| 474 | t += 200; | ||
| 475 | } while (t < 150000); | ||
| 476 | 483 | ||
| 477 | return ret; | 484 | return ret; |
| 478 | } | 485 | } |
| @@ -1337,8 +1344,8 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm) | |||
| 1337 | IWL_ERR(trans, | 1344 | IWL_ERR(trans, |
| 1338 | "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n", | 1345 | "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n", |
| 1339 | cnt, active ? "" : "in", fifo, tbl_dw, | 1346 | cnt, active ? "" : "in", fifo, tbl_dw, |
| 1340 | iwl_read_prph(trans, | 1347 | iwl_read_prph(trans, SCD_QUEUE_RDPTR(cnt)) & |
| 1341 | SCD_QUEUE_RDPTR(cnt)) & (txq->q.n_bd - 1), | 1348 | (TFD_QUEUE_SIZE_MAX - 1), |
| 1342 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt))); | 1349 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt))); |
| 1343 | } | 1350 | } |
| 1344 | 1351 | ||
| @@ -1669,6 +1676,61 @@ err: | |||
| 1669 | IWL_ERR(trans, "failed to create the trans debugfs entry\n"); | 1676 | IWL_ERR(trans, "failed to create the trans debugfs entry\n"); |
| 1670 | return -ENOMEM; | 1677 | return -ENOMEM; |
| 1671 | } | 1678 | } |
| 1679 | |||
| 1680 | static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd) | ||
| 1681 | { | ||
| 1682 | u32 cmdlen = 0; | ||
| 1683 | int i; | ||
| 1684 | |||
| 1685 | for (i = 0; i < IWL_NUM_OF_TBS; i++) | ||
| 1686 | cmdlen += iwl_pcie_tfd_tb_get_len(tfd, i); | ||
| 1687 | |||
| 1688 | return cmdlen; | ||
| 1689 | } | ||
| 1690 | |||
| 1691 | static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans, | ||
| 1692 | void *buf, u32 buflen) | ||
| 1693 | { | ||
| 1694 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
| 1695 | struct iwl_fw_error_dump_data *data; | ||
| 1696 | struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue]; | ||
| 1697 | struct iwl_fw_error_dump_txcmd *txcmd; | ||
| 1698 | u32 len; | ||
| 1699 | int i, ptr; | ||
| 1700 | |||
| 1701 | if (!buf) | ||
| 1702 | return sizeof(*data) + | ||
| 1703 | cmdq->q.n_window * (sizeof(*txcmd) + | ||
| 1704 | TFD_MAX_PAYLOAD_SIZE); | ||
| 1705 | |||
| 1706 | len = 0; | ||
| 1707 | data = buf; | ||
| 1708 | data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD); | ||
| 1709 | txcmd = (void *)data->data; | ||
| 1710 | spin_lock_bh(&cmdq->lock); | ||
| 1711 | ptr = cmdq->q.write_ptr; | ||
| 1712 | for (i = 0; i < cmdq->q.n_window; i++) { | ||
| 1713 | u8 idx = get_cmd_index(&cmdq->q, ptr); | ||
| 1714 | u32 caplen, cmdlen; | ||
| 1715 | |||
| 1716 | cmdlen = iwl_trans_pcie_get_cmdlen(&cmdq->tfds[ptr]); | ||
| 1717 | caplen = min_t(u32, TFD_MAX_PAYLOAD_SIZE, cmdlen); | ||
| 1718 | |||
| 1719 | if (cmdlen) { | ||
| 1720 | len += sizeof(*txcmd) + caplen; | ||
| 1721 | txcmd->cmdlen = cpu_to_le32(cmdlen); | ||
| 1722 | txcmd->caplen = cpu_to_le32(caplen); | ||
| 1723 | memcpy(txcmd->data, cmdq->entries[idx].cmd, caplen); | ||
| 1724 | txcmd = (void *)((u8 *)txcmd->data + caplen); | ||
| 1725 | } | ||
| 1726 | |||
| 1727 | ptr = iwl_queue_dec_wrap(ptr); | ||
| 1728 | } | ||
| 1729 | spin_unlock_bh(&cmdq->lock); | ||
| 1730 | |||
| 1731 | data->len = cpu_to_le32(len); | ||
| 1732 | return sizeof(*data) + len; | ||
| 1733 | } | ||
| 1672 | #else | 1734 | #else |
| 1673 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | 1735 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, |
| 1674 | struct dentry *dir) | 1736 | struct dentry *dir) |
| @@ -1711,6 +1773,10 @@ static const struct iwl_trans_ops trans_ops_pcie = { | |||
| 1711 | .grab_nic_access = iwl_trans_pcie_grab_nic_access, | 1773 | .grab_nic_access = iwl_trans_pcie_grab_nic_access, |
| 1712 | .release_nic_access = iwl_trans_pcie_release_nic_access, | 1774 | .release_nic_access = iwl_trans_pcie_release_nic_access, |
| 1713 | .set_bits_mask = iwl_trans_pcie_set_bits_mask, | 1775 | .set_bits_mask = iwl_trans_pcie_set_bits_mask, |
| 1776 | |||
| 1777 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
| 1778 | .dump_data = iwl_trans_pcie_dump_data, | ||
| 1779 | #endif | ||
| 1714 | }; | 1780 | }; |
| 1715 | 1781 | ||
| 1716 | struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | 1782 | struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index dde6031f4257..038940afbdc5 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
| @@ -70,20 +70,20 @@ static int iwl_queue_space(const struct iwl_queue *q) | |||
| 70 | 70 | ||
| 71 | /* | 71 | /* |
| 72 | * To avoid ambiguity between empty and completely full queues, there | 72 | * To avoid ambiguity between empty and completely full queues, there |
| 73 | * should always be less than q->n_bd elements in the queue. | 73 | * should always be less than TFD_QUEUE_SIZE_MAX elements in the queue. |
| 74 | * If q->n_window is smaller than q->n_bd, there is no need to reserve | 74 | * If q->n_window is smaller than TFD_QUEUE_SIZE_MAX, there is no need |
| 75 | * any queue entries for this purpose. | 75 | * to reserve any queue entries for this purpose. |
| 76 | */ | 76 | */ |
| 77 | if (q->n_window < q->n_bd) | 77 | if (q->n_window < TFD_QUEUE_SIZE_MAX) |
| 78 | max = q->n_window; | 78 | max = q->n_window; |
| 79 | else | 79 | else |
| 80 | max = q->n_bd - 1; | 80 | max = TFD_QUEUE_SIZE_MAX - 1; |
| 81 | 81 | ||
| 82 | /* | 82 | /* |
| 83 | * q->n_bd is a power of 2, so the following is equivalent to modulo by | 83 | * TFD_QUEUE_SIZE_MAX is a power of 2, so the following is equivalent to |
| 84 | * q->n_bd and is well defined for negative dividends. | 84 | * modulo by TFD_QUEUE_SIZE_MAX and is well defined. |
| 85 | */ | 85 | */ |
| 86 | used = (q->write_ptr - q->read_ptr) & (q->n_bd - 1); | 86 | used = (q->write_ptr - q->read_ptr) & (TFD_QUEUE_SIZE_MAX - 1); |
| 87 | 87 | ||
| 88 | if (WARN_ON(used > max)) | 88 | if (WARN_ON(used > max)) |
| 89 | return 0; | 89 | return 0; |
| @@ -94,17 +94,11 @@ static int iwl_queue_space(const struct iwl_queue *q) | |||
| 94 | /* | 94 | /* |
| 95 | * iwl_queue_init - Initialize queue's high/low-water and read/write indexes | 95 | * iwl_queue_init - Initialize queue's high/low-water and read/write indexes |
| 96 | */ | 96 | */ |
| 97 | static int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id) | 97 | static int iwl_queue_init(struct iwl_queue *q, int slots_num, u32 id) |
| 98 | { | 98 | { |
| 99 | q->n_bd = count; | ||
| 100 | q->n_window = slots_num; | 99 | q->n_window = slots_num; |
| 101 | q->id = id; | 100 | q->id = id; |
| 102 | 101 | ||
| 103 | /* count must be power-of-two size, otherwise iwl_queue_inc_wrap | ||
| 104 | * and iwl_queue_dec_wrap are broken. */ | ||
| 105 | if (WARN_ON(!is_power_of_2(count))) | ||
| 106 | return -EINVAL; | ||
| 107 | |||
| 108 | /* slots_num must be power-of-two size, otherwise | 102 | /* slots_num must be power-of-two size, otherwise |
| 109 | * get_cmd_index is broken. */ | 103 | * get_cmd_index is broken. */ |
| 110 | if (WARN_ON(!is_power_of_2(slots_num))) | 104 | if (WARN_ON(!is_power_of_2(slots_num))) |
| @@ -197,17 +191,17 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
| 197 | IWL_ERR(trans, | 191 | IWL_ERR(trans, |
| 198 | "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n", | 192 | "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n", |
| 199 | i, active ? "" : "in", fifo, tbl_dw, | 193 | i, active ? "" : "in", fifo, tbl_dw, |
| 200 | iwl_read_prph(trans, | 194 | iwl_read_prph(trans, SCD_QUEUE_RDPTR(i)) & |
| 201 | SCD_QUEUE_RDPTR(i)) & (txq->q.n_bd - 1), | 195 | (TFD_QUEUE_SIZE_MAX - 1), |
| 202 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(i))); | 196 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(i))); |
| 203 | } | 197 | } |
| 204 | 198 | ||
| 205 | for (i = q->read_ptr; i != q->write_ptr; | 199 | for (i = q->read_ptr; i != q->write_ptr; |
| 206 | i = iwl_queue_inc_wrap(i, q->n_bd)) | 200 | i = iwl_queue_inc_wrap(i)) |
| 207 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, | 201 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, |
| 208 | le32_to_cpu(txq->scratchbufs[i].scratch)); | 202 | le32_to_cpu(txq->scratchbufs[i].scratch)); |
| 209 | 203 | ||
| 210 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1); | 204 | iwl_force_nmi(trans); |
| 211 | } | 205 | } |
| 212 | 206 | ||
| 213 | /* | 207 | /* |
| @@ -338,12 +332,12 @@ void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans) | |||
| 338 | for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { | 332 | for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { |
| 339 | struct iwl_txq *txq = &trans_pcie->txq[i]; | 333 | struct iwl_txq *txq = &trans_pcie->txq[i]; |
| 340 | 334 | ||
| 341 | spin_lock(&txq->lock); | 335 | spin_lock_bh(&txq->lock); |
| 342 | if (trans_pcie->txq[i].need_update) { | 336 | if (trans_pcie->txq[i].need_update) { |
| 343 | iwl_pcie_txq_inc_wr_ptr(trans, txq); | 337 | iwl_pcie_txq_inc_wr_ptr(trans, txq); |
| 344 | trans_pcie->txq[i].need_update = false; | 338 | trans_pcie->txq[i].need_update = false; |
| 345 | } | 339 | } |
| 346 | spin_unlock(&txq->lock); | 340 | spin_unlock_bh(&txq->lock); |
| 347 | } | 341 | } |
| 348 | } | 342 | } |
| 349 | 343 | ||
| @@ -359,13 +353,6 @@ static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) | |||
| 359 | return addr; | 353 | return addr; |
| 360 | } | 354 | } |
| 361 | 355 | ||
| 362 | static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) | ||
| 363 | { | ||
| 364 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; | ||
| 365 | |||
| 366 | return le16_to_cpu(tb->hi_n_len) >> 4; | ||
| 367 | } | ||
| 368 | |||
| 369 | static inline void iwl_pcie_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, | 356 | static inline void iwl_pcie_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, |
| 370 | dma_addr_t addr, u16 len) | 357 | dma_addr_t addr, u16 len) |
| 371 | { | 358 | { |
| @@ -425,13 +412,17 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq) | |||
| 425 | { | 412 | { |
| 426 | struct iwl_tfd *tfd_tmp = txq->tfds; | 413 | struct iwl_tfd *tfd_tmp = txq->tfds; |
| 427 | 414 | ||
| 428 | /* rd_ptr is bounded by n_bd and idx is bounded by n_window */ | 415 | /* rd_ptr is bounded by TFD_QUEUE_SIZE_MAX and |
| 416 | * idx is bounded by n_window | ||
| 417 | */ | ||
| 429 | int rd_ptr = txq->q.read_ptr; | 418 | int rd_ptr = txq->q.read_ptr; |
| 430 | int idx = get_cmd_index(&txq->q, rd_ptr); | 419 | int idx = get_cmd_index(&txq->q, rd_ptr); |
| 431 | 420 | ||
| 432 | lockdep_assert_held(&txq->lock); | 421 | lockdep_assert_held(&txq->lock); |
| 433 | 422 | ||
| 434 | /* We have only q->n_window txq->entries, but we use q->n_bd tfds */ | 423 | /* We have only q->n_window txq->entries, but we use |
| 424 | * TFD_QUEUE_SIZE_MAX tfds | ||
| 425 | */ | ||
| 435 | iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr]); | 426 | iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr]); |
| 436 | 427 | ||
| 437 | /* free SKB */ | 428 | /* free SKB */ |
| @@ -452,7 +443,7 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq) | |||
| 452 | } | 443 | } |
| 453 | 444 | ||
| 454 | static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq, | 445 | static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq, |
| 455 | dma_addr_t addr, u16 len, u8 reset) | 446 | dma_addr_t addr, u16 len, bool reset) |
| 456 | { | 447 | { |
| 457 | struct iwl_queue *q; | 448 | struct iwl_queue *q; |
| 458 | struct iwl_tfd *tfd, *tfd_tmp; | 449 | struct iwl_tfd *tfd, *tfd_tmp; |
| @@ -565,8 +556,7 @@ static int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, | |||
| 565 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); | 556 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); |
| 566 | 557 | ||
| 567 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | 558 | /* Initialize queue's high/low-water marks, and head/tail indexes */ |
| 568 | ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num, | 559 | ret = iwl_queue_init(&txq->q, slots_num, txq_id); |
| 569 | txq_id); | ||
| 570 | if (ret) | 560 | if (ret) |
| 571 | return ret; | 561 | return ret; |
| 572 | 562 | ||
| @@ -591,15 +581,12 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) | |||
| 591 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; | 581 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; |
| 592 | struct iwl_queue *q = &txq->q; | 582 | struct iwl_queue *q = &txq->q; |
| 593 | 583 | ||
| 594 | if (!q->n_bd) | ||
| 595 | return; | ||
| 596 | |||
| 597 | spin_lock_bh(&txq->lock); | 584 | spin_lock_bh(&txq->lock); |
| 598 | while (q->write_ptr != q->read_ptr) { | 585 | while (q->write_ptr != q->read_ptr) { |
| 599 | IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n", | 586 | IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n", |
| 600 | txq_id, q->read_ptr); | 587 | txq_id, q->read_ptr); |
| 601 | iwl_pcie_txq_free_tfd(trans, txq); | 588 | iwl_pcie_txq_free_tfd(trans, txq); |
| 602 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); | 589 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr); |
| 603 | } | 590 | } |
| 604 | txq->active = false; | 591 | txq->active = false; |
| 605 | spin_unlock_bh(&txq->lock); | 592 | spin_unlock_bh(&txq->lock); |
| @@ -636,10 +623,12 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id) | |||
| 636 | } | 623 | } |
| 637 | 624 | ||
| 638 | /* De-alloc circular buffer of TFDs */ | 625 | /* De-alloc circular buffer of TFDs */ |
| 639 | if (txq->q.n_bd) { | 626 | if (txq->tfds) { |
| 640 | dma_free_coherent(dev, sizeof(struct iwl_tfd) * | 627 | dma_free_coherent(dev, |
| 641 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | 628 | sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX, |
| 629 | txq->tfds, txq->q.dma_addr); | ||
| 642 | txq->q.dma_addr = 0; | 630 | txq->q.dma_addr = 0; |
| 631 | txq->tfds = NULL; | ||
| 643 | 632 | ||
| 644 | dma_free_coherent(dev, | 633 | dma_free_coherent(dev, |
| 645 | sizeof(*txq->scratchbufs) * txq->q.n_window, | 634 | sizeof(*txq->scratchbufs) * txq->q.n_window, |
| @@ -948,8 +937,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
| 948 | { | 937 | { |
| 949 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 938 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 950 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; | 939 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; |
| 951 | /* n_bd is usually 256 => n_bd - 1 = 0xff */ | 940 | int tfd_num = ssn & (TFD_QUEUE_SIZE_MAX - 1); |
| 952 | int tfd_num = ssn & (txq->q.n_bd - 1); | ||
| 953 | struct iwl_queue *q = &txq->q; | 941 | struct iwl_queue *q = &txq->q; |
| 954 | int last_to_free; | 942 | int last_to_free; |
| 955 | 943 | ||
| @@ -973,12 +961,12 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
| 973 | 961 | ||
| 974 | /*Since we free until index _not_ inclusive, the one before index is | 962 | /*Since we free until index _not_ inclusive, the one before index is |
| 975 | * the last we will free. This one must be used */ | 963 | * the last we will free. This one must be used */ |
| 976 | last_to_free = iwl_queue_dec_wrap(tfd_num, q->n_bd); | 964 | last_to_free = iwl_queue_dec_wrap(tfd_num); |
| 977 | 965 | ||
| 978 | if (!iwl_queue_used(q, last_to_free)) { | 966 | if (!iwl_queue_used(q, last_to_free)) { |
| 979 | IWL_ERR(trans, | 967 | IWL_ERR(trans, |
| 980 | "%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n", | 968 | "%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n", |
| 981 | __func__, txq_id, last_to_free, q->n_bd, | 969 | __func__, txq_id, last_to_free, TFD_QUEUE_SIZE_MAX, |
| 982 | q->write_ptr, q->read_ptr); | 970 | q->write_ptr, q->read_ptr); |
| 983 | goto out; | 971 | goto out; |
| 984 | } | 972 | } |
| @@ -988,7 +976,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
| 988 | 976 | ||
| 989 | for (; | 977 | for (; |
| 990 | q->read_ptr != tfd_num; | 978 | q->read_ptr != tfd_num; |
| 991 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 979 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr)) { |
| 992 | 980 | ||
| 993 | if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL)) | 981 | if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL)) |
| 994 | continue; | 982 | continue; |
| @@ -1027,21 +1015,21 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) | |||
| 1027 | 1015 | ||
| 1028 | lockdep_assert_held(&txq->lock); | 1016 | lockdep_assert_held(&txq->lock); |
| 1029 | 1017 | ||
| 1030 | if ((idx >= q->n_bd) || (!iwl_queue_used(q, idx))) { | 1018 | if ((idx >= TFD_QUEUE_SIZE_MAX) || (!iwl_queue_used(q, idx))) { |
| 1031 | IWL_ERR(trans, | 1019 | IWL_ERR(trans, |
| 1032 | "%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n", | 1020 | "%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n", |
| 1033 | __func__, txq_id, idx, q->n_bd, | 1021 | __func__, txq_id, idx, TFD_QUEUE_SIZE_MAX, |
| 1034 | q->write_ptr, q->read_ptr); | 1022 | q->write_ptr, q->read_ptr); |
| 1035 | return; | 1023 | return; |
| 1036 | } | 1024 | } |
| 1037 | 1025 | ||
| 1038 | for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; | 1026 | for (idx = iwl_queue_inc_wrap(idx); q->read_ptr != idx; |
| 1039 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 1027 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr)) { |
| 1040 | 1028 | ||
| 1041 | if (nfreed++ > 0) { | 1029 | if (nfreed++ > 0) { |
| 1042 | IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", | 1030 | IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", |
| 1043 | idx, q->write_ptr, q->read_ptr); | 1031 | idx, q->write_ptr, q->read_ptr); |
| 1044 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1); | 1032 | iwl_force_nmi(trans); |
| 1045 | } | 1033 | } |
| 1046 | } | 1034 | } |
| 1047 | 1035 | ||
| @@ -1327,28 +1315,39 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
| 1327 | cmd_pos = offsetof(struct iwl_device_cmd, payload); | 1315 | cmd_pos = offsetof(struct iwl_device_cmd, payload); |
| 1328 | copy_size = sizeof(out_cmd->hdr); | 1316 | copy_size = sizeof(out_cmd->hdr); |
| 1329 | for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { | 1317 | for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { |
| 1330 | int copy = 0; | 1318 | int copy; |
| 1331 | 1319 | ||
| 1332 | if (!cmd->len[i]) | 1320 | if (!cmd->len[i]) |
| 1333 | continue; | 1321 | continue; |
| 1334 | 1322 | ||
| 1335 | /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */ | ||
| 1336 | if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) { | ||
| 1337 | copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size; | ||
| 1338 | |||
| 1339 | if (copy > cmd->len[i]) | ||
| 1340 | copy = cmd->len[i]; | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | /* copy everything if not nocopy/dup */ | 1323 | /* copy everything if not nocopy/dup */ |
| 1344 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | | 1324 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | |
| 1345 | IWL_HCMD_DFL_DUP))) | 1325 | IWL_HCMD_DFL_DUP))) { |
| 1346 | copy = cmd->len[i]; | 1326 | copy = cmd->len[i]; |
| 1347 | 1327 | ||
| 1348 | if (copy) { | ||
| 1349 | memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); | 1328 | memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); |
| 1350 | cmd_pos += copy; | 1329 | cmd_pos += copy; |
| 1351 | copy_size += copy; | 1330 | copy_size += copy; |
| 1331 | continue; | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | /* | ||
| 1335 | * Otherwise we need at least IWL_HCMD_SCRATCHBUF_SIZE copied | ||
| 1336 | * in total (for the scratchbuf handling), but copy up to what | ||
| 1337 | * we can fit into the payload for debug dump purposes. | ||
| 1338 | */ | ||
| 1339 | copy = min_t(int, TFD_MAX_PAYLOAD_SIZE - cmd_pos, cmd->len[i]); | ||
| 1340 | |||
| 1341 | memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); | ||
| 1342 | cmd_pos += copy; | ||
| 1343 | |||
| 1344 | /* However, treat copy_size the proper way, we need it below */ | ||
| 1345 | if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) { | ||
| 1346 | copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size; | ||
| 1347 | |||
| 1348 | if (copy > cmd->len[i]) | ||
| 1349 | copy = cmd->len[i]; | ||
| 1350 | copy_size += copy; | ||
| 1352 | } | 1351 | } |
| 1353 | } | 1352 | } |
| 1354 | 1353 | ||
| @@ -1363,7 +1362,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
| 1363 | memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size); | 1362 | memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size); |
| 1364 | iwl_pcie_txq_build_tfd(trans, txq, | 1363 | iwl_pcie_txq_build_tfd(trans, txq, |
| 1365 | iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr), | 1364 | iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr), |
| 1366 | scratch_size, 1); | 1365 | scratch_size, true); |
| 1367 | 1366 | ||
| 1368 | /* map first command fragment, if any remains */ | 1367 | /* map first command fragment, if any remains */ |
| 1369 | if (copy_size > scratch_size) { | 1368 | if (copy_size > scratch_size) { |
| @@ -1379,7 +1378,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
| 1379 | } | 1378 | } |
| 1380 | 1379 | ||
| 1381 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, | 1380 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, |
| 1382 | copy_size - scratch_size, 0); | 1381 | copy_size - scratch_size, false); |
| 1383 | } | 1382 | } |
| 1384 | 1383 | ||
| 1385 | /* map the remaining (adjusted) nocopy/dup fragments */ | 1384 | /* map the remaining (adjusted) nocopy/dup fragments */ |
| @@ -1402,7 +1401,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
| 1402 | goto out; | 1401 | goto out; |
| 1403 | } | 1402 | } |
| 1404 | 1403 | ||
| 1405 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0); | 1404 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], false); |
| 1406 | } | 1405 | } |
| 1407 | 1406 | ||
| 1408 | out_meta->flags = cmd->flags; | 1407 | out_meta->flags = cmd->flags; |
| @@ -1445,7 +1444,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
| 1445 | } | 1444 | } |
| 1446 | 1445 | ||
| 1447 | /* Increment and update queue's write index */ | 1446 | /* Increment and update queue's write index */ |
| 1448 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 1447 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr); |
| 1449 | iwl_pcie_txq_inc_wr_ptr(trans, txq); | 1448 | iwl_pcie_txq_inc_wr_ptr(trans, txq); |
| 1450 | 1449 | ||
| 1451 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); | 1450 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); |
| @@ -1601,7 +1600,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
| 1601 | get_cmd_string(trans_pcie, cmd->id)); | 1600 | get_cmd_string(trans_pcie, cmd->id)); |
| 1602 | ret = -ETIMEDOUT; | 1601 | ret = -ETIMEDOUT; |
| 1603 | 1602 | ||
| 1604 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1); | 1603 | iwl_force_nmi(trans); |
| 1605 | iwl_trans_fw_error(trans); | 1604 | iwl_trans_fw_error(trans); |
| 1606 | 1605 | ||
| 1607 | goto cancel; | 1606 | goto cancel; |
| @@ -1740,7 +1739,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
| 1740 | memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr, | 1739 | memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr, |
| 1741 | IWL_HCMD_SCRATCHBUF_SIZE); | 1740 | IWL_HCMD_SCRATCHBUF_SIZE); |
| 1742 | iwl_pcie_txq_build_tfd(trans, txq, tb0_phys, | 1741 | iwl_pcie_txq_build_tfd(trans, txq, tb0_phys, |
| 1743 | IWL_HCMD_SCRATCHBUF_SIZE, 1); | 1742 | IWL_HCMD_SCRATCHBUF_SIZE, true); |
| 1744 | 1743 | ||
| 1745 | /* there must be data left over for TB1 or this code must be changed */ | 1744 | /* there must be data left over for TB1 or this code must be changed */ |
| 1746 | BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE); | 1745 | BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE); |
| @@ -1750,7 +1749,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
| 1750 | tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE); | 1749 | tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE); |
| 1751 | if (unlikely(dma_mapping_error(trans->dev, tb1_phys))) | 1750 | if (unlikely(dma_mapping_error(trans->dev, tb1_phys))) |
| 1752 | goto out_err; | 1751 | goto out_err; |
| 1753 | iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, 0); | 1752 | iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, false); |
| 1754 | 1753 | ||
| 1755 | /* | 1754 | /* |
| 1756 | * Set up TFD's third entry to point directly to remainder | 1755 | * Set up TFD's third entry to point directly to remainder |
| @@ -1766,7 +1765,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
| 1766 | &txq->tfds[q->write_ptr]); | 1765 | &txq->tfds[q->write_ptr]); |
| 1767 | goto out_err; | 1766 | goto out_err; |
| 1768 | } | 1767 | } |
| 1769 | iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, 0); | 1768 | iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, false); |
| 1770 | } | 1769 | } |
| 1771 | 1770 | ||
| 1772 | /* Set up entry for this TFD in Tx byte-count array */ | 1771 | /* Set up entry for this TFD in Tx byte-count array */ |
| @@ -1788,7 +1787,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
| 1788 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); | 1787 | mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout); |
| 1789 | 1788 | ||
| 1790 | /* Tell device the write index *just past* this latest filled TFD */ | 1789 | /* Tell device the write index *just past* this latest filled TFD */ |
| 1791 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 1790 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr); |
| 1792 | if (!wait_write_ptr) | 1791 | if (!wait_write_ptr) |
| 1793 | iwl_pcie_txq_inc_wr_ptr(trans, txq); | 1792 | iwl_pcie_txq_inc_wr_ptr(trans, txq); |
| 1794 | 1793 | ||
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 54e344aed6e0..47a998d8f99e 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
| @@ -1006,9 +1006,8 @@ struct cmd_key_material { | |||
| 1006 | } __packed; | 1006 | } __packed; |
| 1007 | 1007 | ||
| 1008 | static int lbs_set_key_material(struct lbs_private *priv, | 1008 | static int lbs_set_key_material(struct lbs_private *priv, |
| 1009 | int key_type, | 1009 | int key_type, int key_info, |
| 1010 | int key_info, | 1010 | const u8 *key, u16 key_len) |
| 1011 | u8 *key, u16 key_len) | ||
| 1012 | { | 1011 | { |
| 1013 | struct cmd_key_material cmd; | 1012 | struct cmd_key_material cmd; |
| 1014 | int ret; | 1013 | int ret; |
| @@ -1610,7 +1609,7 @@ static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev, | |||
| 1610 | */ | 1609 | */ |
| 1611 | 1610 | ||
| 1612 | static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, | 1611 | static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, |
| 1613 | u8 *mac, struct station_info *sinfo) | 1612 | const u8 *mac, struct station_info *sinfo) |
| 1614 | { | 1613 | { |
| 1615 | struct lbs_private *priv = wiphy_priv(wiphy); | 1614 | struct lbs_private *priv = wiphy_priv(wiphy); |
| 1616 | s8 signal, noise; | 1615 | s8 signal, noise; |
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index ab966f08024a..407784aca627 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
| @@ -90,7 +90,8 @@ do { if ((lbs_debug & (grp)) == (grp)) \ | |||
| 90 | #define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args) | 90 | #define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args) |
| 91 | 91 | ||
| 92 | #ifdef DEBUG | 92 | #ifdef DEBUG |
| 93 | static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len) | 93 | static inline void lbs_deb_hex(unsigned int grp, const char *prompt, |
| 94 | const u8 *buf, int len) | ||
| 94 | { | 95 | { |
| 95 | int i = 0; | 96 | int i = 0; |
| 96 | 97 | ||
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index c7366b07b568..e446fed7b345 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c | |||
| @@ -71,8 +71,10 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
| 71 | 71 | ||
| 72 | skb->ip_summed = CHECKSUM_NONE; | 72 | skb->ip_summed = CHECKSUM_NONE; |
| 73 | 73 | ||
| 74 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) | 74 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) { |
| 75 | return process_rxed_802_11_packet(priv, skb); | 75 | ret = process_rxed_802_11_packet(priv, skb); |
| 76 | goto done; | ||
| 77 | } | ||
| 76 | 78 | ||
| 77 | p_rx_pd = (struct rxpd *) skb->data; | 79 | p_rx_pd = (struct rxpd *) skb->data; |
| 78 | p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd + | 80 | p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd + |
| @@ -86,7 +88,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
| 86 | if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { | 88 | if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { |
| 87 | lbs_deb_rx("rx err: frame received with bad length\n"); | 89 | lbs_deb_rx("rx err: frame received with bad length\n"); |
| 88 | dev->stats.rx_length_errors++; | 90 | dev->stats.rx_length_errors++; |
| 89 | ret = 0; | 91 | ret = -EINVAL; |
| 90 | dev_kfree_skb(skb); | 92 | dev_kfree_skb(skb); |
| 91 | goto done; | 93 | goto done; |
| 92 | } | 94 | } |
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 2bd07d681c5e..e1c2f67ae85e 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
| @@ -749,3 +749,45 @@ void mwifiex_set_ba_params(struct mwifiex_private *priv) | |||
| 749 | 749 | ||
| 750 | return; | 750 | return; |
| 751 | } | 751 | } |
| 752 | |||
| 753 | u8 mwifiex_get_sec_chan_offset(int chan) | ||
| 754 | { | ||
| 755 | u8 sec_offset; | ||
| 756 | |||
| 757 | switch (chan) { | ||
| 758 | case 36: | ||
| 759 | case 44: | ||
| 760 | case 52: | ||
| 761 | case 60: | ||
| 762 | case 100: | ||
| 763 | case 108: | ||
| 764 | case 116: | ||
| 765 | case 124: | ||
| 766 | case 132: | ||
| 767 | case 140: | ||
| 768 | case 149: | ||
| 769 | case 157: | ||
| 770 | sec_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
| 771 | break; | ||
| 772 | case 40: | ||
| 773 | case 48: | ||
| 774 | case 56: | ||
| 775 | case 64: | ||
| 776 | case 104: | ||
| 777 | case 112: | ||
| 778 | case 120: | ||
| 779 | case 128: | ||
| 780 | case 136: | ||
| 781 | case 144: | ||
| 782 | case 153: | ||
| 783 | case 161: | ||
| 784 | sec_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
| 785 | break; | ||
| 786 | case 165: | ||
| 787 | default: | ||
| 788 | sec_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
| 789 | break; | ||
| 790 | } | ||
| 791 | |||
| 792 | return sec_offset; | ||
| 793 | } | ||
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 40b007a00f4b..0b73fa08f5d4 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h | |||
| @@ -63,6 +63,7 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, | |||
| 63 | int cmd_action, | 63 | int cmd_action, |
| 64 | struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl); | 64 | struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl); |
| 65 | void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra); | 65 | void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra); |
| 66 | u8 mwifiex_get_sec_chan_offset(int chan); | ||
| 66 | 67 | ||
| 67 | static inline u8 | 68 | static inline u8 |
| 68 | mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv, | 69 | mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv, |
| @@ -199,7 +200,7 @@ static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv, | |||
| 199 | } | 200 | } |
| 200 | 201 | ||
| 201 | static inline u8 | 202 | static inline u8 |
| 202 | mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, u8 *ra) | 203 | mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, const u8 *ra) |
| 203 | { | 204 | { |
| 204 | struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra); | 205 | struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra); |
| 205 | if (node) | 206 | if (node) |
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 860dfe71cf96..5b32106182f8 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c | |||
| @@ -100,6 +100,7 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, | |||
| 100 | struct sk_buff *skb) | 100 | struct sk_buff *skb) |
| 101 | { | 101 | { |
| 102 | struct txpd *local_tx_pd; | 102 | struct txpd *local_tx_pd; |
| 103 | struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); | ||
| 103 | 104 | ||
| 104 | skb_push(skb, sizeof(*local_tx_pd)); | 105 | skb_push(skb, sizeof(*local_tx_pd)); |
| 105 | 106 | ||
| @@ -118,6 +119,9 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, | |||
| 118 | local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len - | 119 | local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len - |
| 119 | sizeof(*local_tx_pd)); | 120 | sizeof(*local_tx_pd)); |
| 120 | 121 | ||
| 122 | if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) | ||
| 123 | local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET; | ||
| 124 | |||
| 121 | if (local_tx_pd->tx_control == 0) | 125 | if (local_tx_pd->tx_control == 0) |
| 122 | /* TxCtrl set by user or default */ | 126 | /* TxCtrl set by user or default */ |
| 123 | local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); | 127 | local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); |
| @@ -183,6 +187,9 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
| 183 | 187 | ||
| 184 | tx_info_aggr->bss_type = tx_info_src->bss_type; | 188 | tx_info_aggr->bss_type = tx_info_src->bss_type; |
| 185 | tx_info_aggr->bss_num = tx_info_src->bss_num; | 189 | tx_info_aggr->bss_num = tx_info_src->bss_num; |
| 190 | |||
| 191 | if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) | ||
| 192 | tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; | ||
| 186 | skb_aggr->priority = skb_src->priority; | 193 | skb_aggr->priority = skb_src->priority; |
| 187 | 194 | ||
| 188 | do_gettimeofday(&tv); | 195 | do_gettimeofday(&tv); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 21ee27ab7b74..e95dec91a561 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
| @@ -994,7 +994,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
| 994 | */ | 994 | */ |
| 995 | static int | 995 | static int |
| 996 | mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 996 | mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, |
| 997 | u8 *mac, struct station_info *sinfo) | 997 | const u8 *mac, struct station_info *sinfo) |
| 998 | { | 998 | { |
| 999 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 999 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
| 1000 | 1000 | ||
| @@ -1270,7 +1270,7 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy, | |||
| 1270 | */ | 1270 | */ |
| 1271 | static int | 1271 | static int |
| 1272 | mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, | 1272 | mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, |
| 1273 | u8 *mac) | 1273 | const u8 *mac) |
| 1274 | { | 1274 | { |
| 1275 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 1275 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
| 1276 | struct mwifiex_sta_node *sta_node; | 1276 | struct mwifiex_sta_node *sta_node; |
| @@ -2629,7 +2629,7 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy, | |||
| 2629 | */ | 2629 | */ |
| 2630 | static int | 2630 | static int |
| 2631 | mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | 2631 | mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, |
| 2632 | u8 *peer, u8 action_code, u8 dialog_token, | 2632 | const u8 *peer, u8 action_code, u8 dialog_token, |
| 2633 | u16 status_code, u32 peer_capability, | 2633 | u16 status_code, u32 peer_capability, |
| 2634 | const u8 *extra_ies, size_t extra_ies_len) | 2634 | const u8 *extra_ies, size_t extra_ies_len) |
| 2635 | { | 2635 | { |
| @@ -2701,7 +2701,7 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
| 2701 | 2701 | ||
| 2702 | static int | 2702 | static int |
| 2703 | mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | 2703 | mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, |
| 2704 | u8 *peer, enum nl80211_tdls_operation action) | 2704 | const u8 *peer, enum nl80211_tdls_operation action) |
| 2705 | { | 2705 | { |
| 2706 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 2706 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
| 2707 | 2707 | ||
| @@ -2748,9 +2748,8 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
| 2748 | } | 2748 | } |
| 2749 | 2749 | ||
| 2750 | static int | 2750 | static int |
| 2751 | mwifiex_cfg80211_add_station(struct wiphy *wiphy, | 2751 | mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev, |
| 2752 | struct net_device *dev, | 2752 | const u8 *mac, struct station_parameters *params) |
| 2753 | u8 *mac, struct station_parameters *params) | ||
| 2754 | { | 2753 | { |
| 2755 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 2754 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
| 2756 | 2755 | ||
| @@ -2765,9 +2764,9 @@ mwifiex_cfg80211_add_station(struct wiphy *wiphy, | |||
| 2765 | } | 2764 | } |
| 2766 | 2765 | ||
| 2767 | static int | 2766 | static int |
| 2768 | mwifiex_cfg80211_change_station(struct wiphy *wiphy, | 2767 | mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev, |
| 2769 | struct net_device *dev, | 2768 | const u8 *mac, |
| 2770 | u8 *mac, struct station_parameters *params) | 2769 | struct station_parameters *params) |
| 2771 | { | 2770 | { |
| 2772 | int ret; | 2771 | int ret; |
| 2773 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 2772 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index b485dc1ae5eb..42eaeda1dc82 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
| @@ -169,6 +169,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
| 169 | #define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146) | 169 | #define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146) |
| 170 | #define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154) | 170 | #define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154) |
| 171 | #define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156) | 171 | #define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156) |
| 172 | #define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194) | ||
| 172 | #define TLV_TYPE_FW_API_REV (PROPRIETARY_TLV_BASE_ID + 199) | 173 | #define TLV_TYPE_FW_API_REV (PROPRIETARY_TLV_BASE_ID + 199) |
| 173 | 174 | ||
| 174 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 | 175 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 |
| @@ -229,6 +230,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
| 229 | #define ISENABLED_40MHZ_INTOLERANT(Dot11nDevCap) (Dot11nDevCap & BIT(8)) | 230 | #define ISENABLED_40MHZ_INTOLERANT(Dot11nDevCap) (Dot11nDevCap & BIT(8)) |
| 230 | #define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22)) | 231 | #define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22)) |
| 231 | #define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & BIT(30)) | 232 | #define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & BIT(30)) |
| 233 | #define ISALLOWED_CHANWIDTH40(ht_param) (ht_param & BIT(2)) | ||
| 232 | 234 | ||
| 233 | /* httxcfg bitmap | 235 | /* httxcfg bitmap |
| 234 | * 0 reserved | 236 | * 0 reserved |
| @@ -487,6 +489,7 @@ enum P2P_MODES { | |||
| 487 | #define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c | 489 | #define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c |
| 488 | #define EVENT_HOSTWAKE_STAIE 0x0000004d | 490 | #define EVENT_HOSTWAKE_STAIE 0x0000004d |
| 489 | #define EVENT_CHANNEL_SWITCH_ANN 0x00000050 | 491 | #define EVENT_CHANNEL_SWITCH_ANN 0x00000050 |
| 492 | #define EVENT_TDLS_GENERIC_EVENT 0x00000052 | ||
| 490 | #define EVENT_EXT_SCAN_REPORT 0x00000058 | 493 | #define EVENT_EXT_SCAN_REPORT 0x00000058 |
| 491 | #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f | 494 | #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f |
| 492 | 495 | ||
| @@ -519,6 +522,7 @@ enum P2P_MODES { | |||
| 519 | #define ACT_TDLS_DELETE 0x00 | 522 | #define ACT_TDLS_DELETE 0x00 |
| 520 | #define ACT_TDLS_CREATE 0x01 | 523 | #define ACT_TDLS_CREATE 0x01 |
| 521 | #define ACT_TDLS_CONFIG 0x02 | 524 | #define ACT_TDLS_CONFIG 0x02 |
| 525 | #define TDLS_EVENT_LINK_TEAR_DOWN 3 | ||
| 522 | 526 | ||
| 523 | #define MWIFIEX_FW_V15 15 | 527 | #define MWIFIEX_FW_V15 15 |
| 524 | 528 | ||
| @@ -535,6 +539,7 @@ struct mwifiex_ie_types_data { | |||
| 535 | #define MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET 0x01 | 539 | #define MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET 0x01 |
| 536 | #define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08 | 540 | #define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08 |
| 537 | #define MWIFIEX_TXPD_FLAGS_TDLS_PACKET 0x10 | 541 | #define MWIFIEX_TXPD_FLAGS_TDLS_PACKET 0x10 |
| 542 | #define MWIFIEX_RXPD_FLAGS_TDLS_PACKET 0x01 | ||
| 538 | 543 | ||
| 539 | struct txpd { | 544 | struct txpd { |
| 540 | u8 bss_type; | 545 | u8 bss_type; |
| @@ -577,7 +582,7 @@ struct rxpd { | |||
| 577 | * [Bit 7] Reserved | 582 | * [Bit 7] Reserved |
| 578 | */ | 583 | */ |
| 579 | u8 ht_info; | 584 | u8 ht_info; |
| 580 | u8 reserved; | 585 | u8 flags; |
| 581 | } __packed; | 586 | } __packed; |
| 582 | 587 | ||
| 583 | struct uap_txpd { | 588 | struct uap_txpd { |
| @@ -708,6 +713,13 @@ struct mwifiex_ie_types_vendor_param_set { | |||
| 708 | u8 ie[MWIFIEX_MAX_VSIE_LEN]; | 713 | u8 ie[MWIFIEX_MAX_VSIE_LEN]; |
| 709 | }; | 714 | }; |
| 710 | 715 | ||
| 716 | #define MWIFIEX_TDLS_IDLE_TIMEOUT 60 | ||
| 717 | |||
| 718 | struct mwifiex_ie_types_tdls_idle_timeout { | ||
| 719 | struct mwifiex_ie_types_header header; | ||
| 720 | __le16 value; | ||
| 721 | } __packed; | ||
| 722 | |||
| 711 | struct mwifiex_ie_types_rsn_param_set { | 723 | struct mwifiex_ie_types_rsn_param_set { |
| 712 | struct mwifiex_ie_types_header header; | 724 | struct mwifiex_ie_types_header header; |
| 713 | u8 rsn_ie[1]; | 725 | u8 rsn_ie[1]; |
| @@ -1745,6 +1757,15 @@ struct host_cmd_ds_802_11_subsc_evt { | |||
| 1745 | __le16 events; | 1757 | __le16 events; |
| 1746 | } __packed; | 1758 | } __packed; |
| 1747 | 1759 | ||
| 1760 | struct mwifiex_tdls_generic_event { | ||
| 1761 | __le16 type; | ||
| 1762 | u8 peer_mac[ETH_ALEN]; | ||
| 1763 | union { | ||
| 1764 | __le16 reason_code; | ||
| 1765 | __le16 reserved; | ||
| 1766 | } u; | ||
| 1767 | } __packed; | ||
| 1768 | |||
| 1748 | struct mwifiex_ie { | 1769 | struct mwifiex_ie { |
| 1749 | __le16 ie_index; | 1770 | __le16 ie_index; |
| 1750 | __le16 mgmt_subtype_mask; | 1771 | __le16 mgmt_subtype_mask; |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 34181192a666..3f25feb1508e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
| @@ -910,8 +910,6 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, | |||
| 910 | struct sk_buff *skb); | 910 | struct sk_buff *skb); |
| 911 | int mwifiex_process_sta_event(struct mwifiex_private *); | 911 | int mwifiex_process_sta_event(struct mwifiex_private *); |
| 912 | int mwifiex_process_uap_event(struct mwifiex_private *); | 912 | int mwifiex_process_uap_event(struct mwifiex_private *); |
| 913 | struct mwifiex_sta_node * | ||
| 914 | mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac); | ||
| 915 | void mwifiex_delete_all_station_list(struct mwifiex_private *priv); | 913 | void mwifiex_delete_all_station_list(struct mwifiex_private *priv); |
| 916 | void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); | 914 | void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); |
| 917 | void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb); | 915 | void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb); |
| @@ -1220,26 +1218,26 @@ void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv); | |||
| 1220 | extern const struct ethtool_ops mwifiex_ethtool_ops; | 1218 | extern const struct ethtool_ops mwifiex_ethtool_ops; |
| 1221 | 1219 | ||
| 1222 | void mwifiex_del_all_sta_list(struct mwifiex_private *priv); | 1220 | void mwifiex_del_all_sta_list(struct mwifiex_private *priv); |
| 1223 | void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac); | 1221 | void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac); |
| 1224 | void | 1222 | void |
| 1225 | mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, | 1223 | mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, |
| 1226 | int ies_len, struct mwifiex_sta_node *node); | 1224 | int ies_len, struct mwifiex_sta_node *node); |
| 1227 | struct mwifiex_sta_node * | 1225 | struct mwifiex_sta_node * |
| 1228 | mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac); | 1226 | mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac); |
| 1229 | struct mwifiex_sta_node * | 1227 | struct mwifiex_sta_node * |
| 1230 | mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac); | 1228 | mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac); |
| 1231 | int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, u8 *peer, | 1229 | int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer, |
| 1232 | u8 action_code, u8 dialog_token, | 1230 | u8 action_code, u8 dialog_token, |
| 1233 | u16 status_code, const u8 *extra_ies, | 1231 | u16 status_code, const u8 *extra_ies, |
| 1234 | size_t extra_ies_len); | 1232 | size_t extra_ies_len); |
| 1235 | int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, | 1233 | int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer, |
| 1236 | u8 *peer, u8 action_code, u8 dialog_token, | 1234 | u8 action_code, u8 dialog_token, |
| 1237 | u16 status_code, const u8 *extra_ies, | 1235 | u16 status_code, const u8 *extra_ies, |
| 1238 | size_t extra_ies_len); | 1236 | size_t extra_ies_len); |
| 1239 | void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, | 1237 | void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, |
| 1240 | u8 *buf, int len); | 1238 | u8 *buf, int len); |
| 1241 | int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action); | 1239 | int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action); |
| 1242 | int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac); | 1240 | int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac); |
| 1243 | void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv); | 1241 | void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv); |
| 1244 | bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv); | 1242 | bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv); |
| 1245 | u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band, | 1243 | u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band, |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index c2cfeec466d8..574d4b597468 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
| @@ -1071,6 +1071,7 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) | |||
| 1071 | * is mapped to PCI device memory. Tx ring pointers are advanced accordingly. | 1071 | * is mapped to PCI device memory. Tx ring pointers are advanced accordingly. |
| 1072 | * Download ready interrupt to FW is deffered if Tx ring is not full and | 1072 | * Download ready interrupt to FW is deffered if Tx ring is not full and |
| 1073 | * additional payload can be accomodated. | 1073 | * additional payload can be accomodated. |
| 1074 | * Caller must ensure tx_param parameter to this function is not NULL. | ||
| 1074 | */ | 1075 | */ |
| 1075 | static int | 1076 | static int |
| 1076 | mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, | 1077 | mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, |
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index a1773d3cb49f..4ce3d7b33991 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
| @@ -1678,8 +1678,12 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, | |||
| 1678 | if (ret) { | 1678 | if (ret) { |
| 1679 | if (type == MWIFIEX_TYPE_CMD) | 1679 | if (type == MWIFIEX_TYPE_CMD) |
| 1680 | adapter->cmd_sent = false; | 1680 | adapter->cmd_sent = false; |
| 1681 | if (type == MWIFIEX_TYPE_DATA) | 1681 | if (type == MWIFIEX_TYPE_DATA) { |
| 1682 | adapter->data_sent = false; | 1682 | adapter->data_sent = false; |
| 1683 | /* restore curr_wr_port in error cases */ | ||
| 1684 | card->curr_wr_port = port; | ||
| 1685 | card->mp_wr_bitmap |= (u32)(1 << card->curr_wr_port); | ||
| 1686 | } | ||
| 1683 | } else { | 1687 | } else { |
| 1684 | if (type == MWIFIEX_TYPE_DATA) { | 1688 | if (type == MWIFIEX_TYPE_DATA) { |
| 1685 | if (!(card->mp_wr_bitmap & (1 << card->curr_wr_port))) | 1689 | if (!(card->mp_wr_bitmap & (1 << card->curr_wr_port))) |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index e3cac1495cc7..88202ce0c139 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
| @@ -1546,6 +1546,7 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv, | |||
| 1546 | struct mwifiex_ie_types_extcap *extcap; | 1546 | struct mwifiex_ie_types_extcap *extcap; |
| 1547 | struct mwifiex_ie_types_vhtcap *vht_capab; | 1547 | struct mwifiex_ie_types_vhtcap *vht_capab; |
| 1548 | struct mwifiex_ie_types_aid *aid; | 1548 | struct mwifiex_ie_types_aid *aid; |
| 1549 | struct mwifiex_ie_types_tdls_idle_timeout *timeout; | ||
| 1549 | u8 *pos, qos_info; | 1550 | u8 *pos, qos_info; |
| 1550 | u16 config_len = 0; | 1551 | u16 config_len = 0; |
| 1551 | struct station_parameters *params = priv->sta_params; | 1552 | struct station_parameters *params = priv->sta_params; |
| @@ -1643,6 +1644,12 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv, | |||
| 1643 | config_len += sizeof(struct mwifiex_ie_types_aid); | 1644 | config_len += sizeof(struct mwifiex_ie_types_aid); |
| 1644 | } | 1645 | } |
| 1645 | 1646 | ||
| 1647 | timeout = (void *)(pos + config_len); | ||
| 1648 | timeout->header.type = cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT); | ||
| 1649 | timeout->header.len = cpu_to_le16(sizeof(timeout->value)); | ||
| 1650 | timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT); | ||
| 1651 | config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout); | ||
| 1652 | |||
| 1646 | break; | 1653 | break; |
| 1647 | default: | 1654 | default: |
| 1648 | dev_err(priv->adapter->dev, "Unknown TDLS operation\n"); | 1655 | dev_err(priv->adapter->dev, "Unknown TDLS operation\n"); |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index bfebb0144df5..577f2979ed8f 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
| @@ -865,14 +865,20 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv, | |||
| 865 | 865 | ||
| 866 | switch (action) { | 866 | switch (action) { |
| 867 | case ACT_TDLS_DELETE: | 867 | case ACT_TDLS_DELETE: |
| 868 | if (reason) | 868 | if (reason) { |
| 869 | dev_err(priv->adapter->dev, | 869 | if (!node || reason == TDLS_ERR_LINK_NONEXISTENT) |
| 870 | "TDLS link delete for %pM failed: reason %d\n", | 870 | dev_dbg(priv->adapter->dev, |
| 871 | cmd_tdls_oper->peer_mac, reason); | 871 | "TDLS link delete for %pM failed: reason %d\n", |
| 872 | else | 872 | cmd_tdls_oper->peer_mac, reason); |
| 873 | else | ||
| 874 | dev_err(priv->adapter->dev, | ||
| 875 | "TDLS link delete for %pM failed: reason %d\n", | ||
| 876 | cmd_tdls_oper->peer_mac, reason); | ||
| 877 | } else { | ||
| 873 | dev_dbg(priv->adapter->dev, | 878 | dev_dbg(priv->adapter->dev, |
| 874 | "TDLS link config for %pM successful\n", | 879 | "TDLS link delete for %pM successful\n", |
| 875 | cmd_tdls_oper->peer_mac); | 880 | cmd_tdls_oper->peer_mac); |
| 881 | } | ||
| 876 | break; | 882 | break; |
| 877 | case ACT_TDLS_CREATE: | 883 | case ACT_TDLS_CREATE: |
| 878 | if (reason) { | 884 | if (reason) { |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 368450cc56c7..f6395ef11a72 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
| @@ -134,6 +134,46 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code) | |||
| 134 | netif_carrier_off(priv->netdev); | 134 | netif_carrier_off(priv->netdev); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static int mwifiex_parse_tdls_event(struct mwifiex_private *priv, | ||
| 138 | struct sk_buff *event_skb) | ||
| 139 | { | ||
| 140 | int ret = 0; | ||
| 141 | struct mwifiex_adapter *adapter = priv->adapter; | ||
| 142 | struct mwifiex_sta_node *sta_ptr; | ||
| 143 | struct mwifiex_tdls_generic_event *tdls_evt = | ||
| 144 | (void *)event_skb->data + sizeof(adapter->event_cause); | ||
| 145 | |||
| 146 | /* reserved 2 bytes are not mandatory in tdls event */ | ||
| 147 | if (event_skb->len < (sizeof(struct mwifiex_tdls_generic_event) - | ||
| 148 | sizeof(u16) - sizeof(adapter->event_cause))) { | ||
| 149 | dev_err(adapter->dev, "Invalid event length!\n"); | ||
| 150 | return -1; | ||
| 151 | } | ||
| 152 | |||
| 153 | sta_ptr = mwifiex_get_sta_entry(priv, tdls_evt->peer_mac); | ||
| 154 | if (!sta_ptr) { | ||
| 155 | dev_err(adapter->dev, "cannot get sta entry!\n"); | ||
| 156 | return -1; | ||
| 157 | } | ||
| 158 | |||
| 159 | switch (le16_to_cpu(tdls_evt->type)) { | ||
| 160 | case TDLS_EVENT_LINK_TEAR_DOWN: | ||
| 161 | cfg80211_tdls_oper_request(priv->netdev, | ||
| 162 | tdls_evt->peer_mac, | ||
| 163 | NL80211_TDLS_TEARDOWN, | ||
| 164 | le16_to_cpu(tdls_evt->u.reason_code), | ||
| 165 | GFP_KERNEL); | ||
| 166 | ret = mwifiex_tdls_oper(priv, tdls_evt->peer_mac, | ||
| 167 | MWIFIEX_TDLS_DISABLE_LINK); | ||
| 168 | queue_work(adapter->workqueue, &adapter->main_work); | ||
| 169 | break; | ||
| 170 | default: | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | |||
| 174 | return ret; | ||
| 175 | } | ||
| 176 | |||
| 137 | /* | 177 | /* |
| 138 | * This function handles events generated by firmware. | 178 | * This function handles events generated by firmware. |
| 139 | * | 179 | * |
| @@ -459,6 +499,10 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
| 459 | false); | 499 | false); |
| 460 | break; | 500 | break; |
| 461 | 501 | ||
| 502 | case EVENT_TDLS_GENERIC_EVENT: | ||
| 503 | ret = mwifiex_parse_tdls_event(priv, adapter->event_skb); | ||
| 504 | break; | ||
| 505 | |||
| 462 | default: | 506 | default: |
| 463 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", | 507 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", |
| 464 | eventcause); | 508 | eventcause); |
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index ed26387eccf5..8b639d7fe6df 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c | |||
| @@ -183,6 +183,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, | |||
| 183 | struct rx_packet_hdr *rx_pkt_hdr; | 183 | struct rx_packet_hdr *rx_pkt_hdr; |
| 184 | u8 ta[ETH_ALEN]; | 184 | u8 ta[ETH_ALEN]; |
| 185 | u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num; | 185 | u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num; |
| 186 | struct mwifiex_sta_node *sta_ptr; | ||
| 186 | 187 | ||
| 187 | local_rx_pd = (struct rxpd *) (skb->data); | 188 | local_rx_pd = (struct rxpd *) (skb->data); |
| 188 | rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type); | 189 | rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type); |
| @@ -213,14 +214,25 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, | |||
| 213 | * If the packet is not an unicast packet then send the packet | 214 | * If the packet is not an unicast packet then send the packet |
| 214 | * directly to os. Don't pass thru rx reordering | 215 | * directly to os. Don't pass thru rx reordering |
| 215 | */ | 216 | */ |
| 216 | if (!IS_11N_ENABLED(priv) || | 217 | if ((!IS_11N_ENABLED(priv) && |
| 218 | !(ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && | ||
| 219 | !(local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET))) || | ||
| 217 | !ether_addr_equal_unaligned(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest)) { | 220 | !ether_addr_equal_unaligned(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest)) { |
| 218 | mwifiex_process_rx_packet(priv, skb); | 221 | mwifiex_process_rx_packet(priv, skb); |
| 219 | return ret; | 222 | return ret; |
| 220 | } | 223 | } |
| 221 | 224 | ||
| 222 | if (mwifiex_queuing_ra_based(priv)) { | 225 | if (mwifiex_queuing_ra_based(priv) || |
| 226 | (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && | ||
| 227 | local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET)) { | ||
| 223 | memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); | 228 | memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); |
| 229 | if (local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET && | ||
| 230 | local_rx_pd->priority < MAX_NUM_TID) { | ||
| 231 | sta_ptr = mwifiex_get_sta_entry(priv, ta); | ||
| 232 | if (sta_ptr) | ||
| 233 | sta_ptr->rx_seq[local_rx_pd->priority] = | ||
| 234 | le16_to_cpu(local_rx_pd->seq_num); | ||
| 235 | } | ||
| 224 | } else { | 236 | } else { |
| 225 | if (rx_pkt_type != PKT_TYPE_BAR) | 237 | if (rx_pkt_type != PKT_TYPE_BAR) |
| 226 | priv->rx_seq[local_rx_pd->priority] = seq_num; | 238 | priv->rx_seq[local_rx_pd->priority] = seq_num; |
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 1236a5de7bca..5fce7e78a36e 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c | |||
| @@ -128,6 +128,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) | |||
| 128 | { | 128 | { |
| 129 | struct mwifiex_adapter *adapter = priv->adapter; | 129 | struct mwifiex_adapter *adapter = priv->adapter; |
| 130 | struct txpd *local_tx_pd; | 130 | struct txpd *local_tx_pd; |
| 131 | struct mwifiex_tx_param tx_param; | ||
| 131 | /* sizeof(struct txpd) + Interface specific header */ | 132 | /* sizeof(struct txpd) + Interface specific header */ |
| 132 | #define NULL_PACKET_HDR 64 | 133 | #define NULL_PACKET_HDR 64 |
| 133 | u32 data_len = NULL_PACKET_HDR; | 134 | u32 data_len = NULL_PACKET_HDR; |
| @@ -168,8 +169,9 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) | |||
| 168 | skb, NULL); | 169 | skb, NULL); |
| 169 | } else { | 170 | } else { |
| 170 | skb_push(skb, INTF_HEADER_LEN); | 171 | skb_push(skb, INTF_HEADER_LEN); |
| 172 | tx_param.next_pkt_len = 0; | ||
| 171 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, | 173 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, |
| 172 | skb, NULL); | 174 | skb, &tx_param); |
| 173 | } | 175 | } |
| 174 | switch (ret) { | 176 | switch (ret) { |
| 175 | case -EBUSY: | 177 | case -EBUSY: |
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c index 97662a1ba58c..e73034fbbde9 100644 --- a/drivers/net/wireless/mwifiex/tdls.c +++ b/drivers/net/wireless/mwifiex/tdls.c | |||
| @@ -25,8 +25,8 @@ | |||
| 25 | #define TDLS_RESP_FIX_LEN 8 | 25 | #define TDLS_RESP_FIX_LEN 8 |
| 26 | #define TDLS_CONFIRM_FIX_LEN 6 | 26 | #define TDLS_CONFIRM_FIX_LEN 6 |
| 27 | 27 | ||
| 28 | static void | 28 | static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv, |
| 29 | mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status) | 29 | const u8 *mac, u8 status) |
| 30 | { | 30 | { |
| 31 | struct mwifiex_ra_list_tbl *ra_list; | 31 | struct mwifiex_ra_list_tbl *ra_list; |
| 32 | struct list_head *tid_list; | 32 | struct list_head *tid_list; |
| @@ -84,7 +84,8 @@ mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status) | |||
| 84 | return; | 84 | return; |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, u8 *mac) | 87 | static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, |
| 88 | const u8 *mac) | ||
| 88 | { | 89 | { |
| 89 | struct mwifiex_ra_list_tbl *ra_list; | 90 | struct mwifiex_ra_list_tbl *ra_list; |
| 90 | struct list_head *ra_list_head; | 91 | struct list_head *ra_list_head; |
| @@ -185,8 +186,50 @@ static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv, | |||
| 185 | return 0; | 186 | return 0; |
| 186 | } | 187 | } |
| 187 | 188 | ||
| 189 | static int | ||
| 190 | mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac, | ||
| 191 | u8 vht_enabled, struct sk_buff *skb) | ||
| 192 | { | ||
| 193 | struct ieee80211_ht_operation *ht_oper; | ||
| 194 | struct mwifiex_sta_node *sta_ptr; | ||
| 195 | struct mwifiex_bssdescriptor *bss_desc = | ||
| 196 | &priv->curr_bss_params.bss_descriptor; | ||
| 197 | u8 *pos; | ||
| 198 | |||
| 199 | sta_ptr = mwifiex_get_sta_entry(priv, mac); | ||
| 200 | if (unlikely(!sta_ptr)) { | ||
| 201 | dev_warn(priv->adapter->dev, | ||
| 202 | "TDLS peer station not found in list\n"); | ||
| 203 | return -1; | ||
| 204 | } | ||
| 205 | |||
| 206 | pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2); | ||
| 207 | *pos++ = WLAN_EID_HT_OPERATION; | ||
| 208 | *pos++ = sizeof(struct ieee80211_ht_operation); | ||
| 209 | ht_oper = (void *)pos; | ||
| 210 | |||
| 211 | ht_oper->primary_chan = bss_desc->channel; | ||
| 212 | |||
| 213 | /* follow AP's channel bandwidth */ | ||
| 214 | if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) && | ||
| 215 | bss_desc->bcn_ht_cap && | ||
| 216 | ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_oper->ht_param)) | ||
| 217 | ht_oper->ht_param = bss_desc->bcn_ht_oper->ht_param; | ||
| 218 | |||
| 219 | if (vht_enabled) { | ||
| 220 | ht_oper->ht_param = | ||
| 221 | mwifiex_get_sec_chan_offset(bss_desc->channel); | ||
| 222 | ht_oper->ht_param |= BIT(2); | ||
| 223 | } | ||
| 224 | |||
| 225 | memcpy(&sta_ptr->tdls_cap.ht_oper, ht_oper, | ||
| 226 | sizeof(struct ieee80211_ht_operation)); | ||
| 227 | |||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 188 | static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv, | 231 | static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv, |
| 189 | u8 *mac, struct sk_buff *skb) | 232 | const u8 *mac, struct sk_buff *skb) |
| 190 | { | 233 | { |
| 191 | struct mwifiex_bssdescriptor *bss_desc; | 234 | struct mwifiex_bssdescriptor *bss_desc; |
| 192 | struct ieee80211_vht_operation *vht_oper; | 235 | struct ieee80211_vht_operation *vht_oper; |
| @@ -325,8 +368,9 @@ static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb) | |||
| 325 | } | 368 | } |
| 326 | 369 | ||
| 327 | static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, | 370 | static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, |
| 328 | u8 *peer, u8 action_code, u8 dialog_token, | 371 | const u8 *peer, u8 action_code, |
| 329 | u16 status_code, struct sk_buff *skb) | 372 | u8 dialog_token, |
| 373 | u16 status_code, struct sk_buff *skb) | ||
| 330 | { | 374 | { |
| 331 | struct ieee80211_tdls_data *tf; | 375 | struct ieee80211_tdls_data *tf; |
| 332 | int ret; | 376 | int ret; |
| @@ -428,6 +472,17 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, | |||
| 428 | dev_kfree_skb_any(skb); | 472 | dev_kfree_skb_any(skb); |
| 429 | return ret; | 473 | return ret; |
| 430 | } | 474 | } |
| 475 | ret = mwifiex_tdls_add_ht_oper(priv, peer, 1, skb); | ||
| 476 | if (ret) { | ||
| 477 | dev_kfree_skb_any(skb); | ||
| 478 | return ret; | ||
| 479 | } | ||
| 480 | } else { | ||
| 481 | ret = mwifiex_tdls_add_ht_oper(priv, peer, 0, skb); | ||
| 482 | if (ret) { | ||
| 483 | dev_kfree_skb_any(skb); | ||
| 484 | return ret; | ||
| 485 | } | ||
| 431 | } | 486 | } |
| 432 | break; | 487 | break; |
| 433 | 488 | ||
| @@ -453,7 +508,8 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, | |||
| 453 | } | 508 | } |
| 454 | 509 | ||
| 455 | static void | 510 | static void |
| 456 | mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid) | 511 | mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr, |
| 512 | const u8 *peer, const u8 *bssid) | ||
| 457 | { | 513 | { |
| 458 | struct ieee80211_tdls_lnkie *lnkid; | 514 | struct ieee80211_tdls_lnkie *lnkid; |
| 459 | 515 | ||
| @@ -467,8 +523,8 @@ mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid) | |||
| 467 | memcpy(lnkid->resp_sta, peer, ETH_ALEN); | 523 | memcpy(lnkid->resp_sta, peer, ETH_ALEN); |
| 468 | } | 524 | } |
| 469 | 525 | ||
| 470 | int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, | 526 | int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer, |
| 471 | u8 *peer, u8 action_code, u8 dialog_token, | 527 | u8 action_code, u8 dialog_token, |
| 472 | u16 status_code, const u8 *extra_ies, | 528 | u16 status_code, const u8 *extra_ies, |
| 473 | size_t extra_ies_len) | 529 | size_t extra_ies_len) |
| 474 | { | 530 | { |
| @@ -560,7 +616,8 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, | |||
| 560 | } | 616 | } |
| 561 | 617 | ||
| 562 | static int | 618 | static int |
| 563 | mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer, | 619 | mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, |
| 620 | const u8 *peer, | ||
| 564 | u8 action_code, u8 dialog_token, | 621 | u8 action_code, u8 dialog_token, |
| 565 | u16 status_code, struct sk_buff *skb) | 622 | u16 status_code, struct sk_buff *skb) |
| 566 | { | 623 | { |
| @@ -638,10 +695,10 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer, | |||
| 638 | return 0; | 695 | return 0; |
| 639 | } | 696 | } |
| 640 | 697 | ||
| 641 | int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, | 698 | int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer, |
| 642 | u8 *peer, u8 action_code, u8 dialog_token, | 699 | u8 action_code, u8 dialog_token, |
| 643 | u16 status_code, const u8 *extra_ies, | 700 | u16 status_code, const u8 *extra_ies, |
| 644 | size_t extra_ies_len) | 701 | size_t extra_ies_len) |
| 645 | { | 702 | { |
| 646 | struct sk_buff *skb; | 703 | struct sk_buff *skb; |
| 647 | struct mwifiex_txinfo *tx_info; | 704 | struct mwifiex_txinfo *tx_info; |
| @@ -848,7 +905,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, | |||
| 848 | } | 905 | } |
| 849 | 906 | ||
| 850 | static int | 907 | static int |
| 851 | mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer) | 908 | mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer) |
| 852 | { | 909 | { |
| 853 | struct mwifiex_sta_node *sta_ptr; | 910 | struct mwifiex_sta_node *sta_ptr; |
| 854 | struct mwifiex_ds_tdls_oper tdls_oper; | 911 | struct mwifiex_ds_tdls_oper tdls_oper; |
| @@ -869,7 +926,7 @@ mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer) | |||
| 869 | } | 926 | } |
| 870 | 927 | ||
| 871 | static int | 928 | static int |
| 872 | mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer) | 929 | mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer) |
| 873 | { | 930 | { |
| 874 | struct mwifiex_sta_node *sta_ptr; | 931 | struct mwifiex_sta_node *sta_ptr; |
| 875 | struct mwifiex_ds_tdls_oper tdls_oper; | 932 | struct mwifiex_ds_tdls_oper tdls_oper; |
| @@ -896,7 +953,7 @@ mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer) | |||
| 896 | } | 953 | } |
| 897 | 954 | ||
| 898 | static int | 955 | static int |
| 899 | mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer) | 956 | mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer) |
| 900 | { | 957 | { |
| 901 | struct mwifiex_sta_node *sta_ptr; | 958 | struct mwifiex_sta_node *sta_ptr; |
| 902 | struct mwifiex_ds_tdls_oper tdls_oper; | 959 | struct mwifiex_ds_tdls_oper tdls_oper; |
| @@ -925,7 +982,7 @@ mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer) | |||
| 925 | } | 982 | } |
| 926 | 983 | ||
| 927 | static int | 984 | static int |
| 928 | mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer) | 985 | mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer) |
| 929 | { | 986 | { |
| 930 | struct mwifiex_sta_node *sta_ptr; | 987 | struct mwifiex_sta_node *sta_ptr; |
| 931 | struct ieee80211_mcs_info mcs; | 988 | struct ieee80211_mcs_info mcs; |
| @@ -982,7 +1039,7 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer) | |||
| 982 | return 0; | 1039 | return 0; |
| 983 | } | 1040 | } |
| 984 | 1041 | ||
| 985 | int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action) | 1042 | int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action) |
| 986 | { | 1043 | { |
| 987 | switch (action) { | 1044 | switch (action) { |
| 988 | case MWIFIEX_TDLS_ENABLE_LINK: | 1045 | case MWIFIEX_TDLS_ENABLE_LINK: |
| @@ -997,7 +1054,7 @@ int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action) | |||
| 997 | return 0; | 1054 | return 0; |
| 998 | } | 1055 | } |
| 999 | 1056 | ||
| 1000 | int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac) | 1057 | int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac) |
| 1001 | { | 1058 | { |
| 1002 | struct mwifiex_sta_node *sta_ptr; | 1059 | struct mwifiex_sta_node *sta_ptr; |
| 1003 | 1060 | ||
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index c3824e37f3f2..6da5abf52e61 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
| @@ -259,7 +259,7 @@ int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, | |||
| 259 | * NULL is returned if station entry is not found in associated STA list. | 259 | * NULL is returned if station entry is not found in associated STA list. |
| 260 | */ | 260 | */ |
| 261 | struct mwifiex_sta_node * | 261 | struct mwifiex_sta_node * |
| 262 | mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac) | 262 | mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac) |
| 263 | { | 263 | { |
| 264 | struct mwifiex_sta_node *node; | 264 | struct mwifiex_sta_node *node; |
| 265 | 265 | ||
| @@ -280,7 +280,7 @@ mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac) | |||
| 280 | * If received mac address is NULL, NULL is returned. | 280 | * If received mac address is NULL, NULL is returned. |
| 281 | */ | 281 | */ |
| 282 | struct mwifiex_sta_node * | 282 | struct mwifiex_sta_node * |
| 283 | mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac) | 283 | mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac) |
| 284 | { | 284 | { |
| 285 | struct mwifiex_sta_node *node; | 285 | struct mwifiex_sta_node *node; |
| 286 | unsigned long flags; | 286 | unsigned long flags; |
| @@ -332,7 +332,7 @@ mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, | |||
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | /* This function will delete a station entry from station list */ | 334 | /* This function will delete a station entry from station list */ |
| 335 | void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac) | 335 | void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac) |
| 336 | { | 336 | { |
| 337 | struct mwifiex_sta_node *node; | 337 | struct mwifiex_sta_node *node; |
| 338 | unsigned long flags; | 338 | unsigned long flags; |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 94b6c74ba727..6d9738a5dc31 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
| @@ -92,7 +92,7 @@ mwifiex_wmm_ac_debug_print(const struct ieee_types_wmm_ac_parameters *ac_param) | |||
| 92 | * The function also initializes the list with the provided RA. | 92 | * The function also initializes the list with the provided RA. |
| 93 | */ | 93 | */ |
| 94 | static struct mwifiex_ra_list_tbl * | 94 | static struct mwifiex_ra_list_tbl * |
| 95 | mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra) | 95 | mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra) |
| 96 | { | 96 | { |
| 97 | struct mwifiex_ra_list_tbl *ra_list; | 97 | struct mwifiex_ra_list_tbl *ra_list; |
| 98 | 98 | ||
| @@ -139,8 +139,7 @@ static u8 mwifiex_get_random_ba_threshold(void) | |||
| 139 | * This function allocates and adds a RA list for all TIDs | 139 | * This function allocates and adds a RA list for all TIDs |
| 140 | * with the given RA. | 140 | * with the given RA. |
| 141 | */ | 141 | */ |
| 142 | void | 142 | void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra) |
| 143 | mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) | ||
| 144 | { | 143 | { |
| 145 | int i; | 144 | int i; |
| 146 | struct mwifiex_ra_list_tbl *ra_list; | 145 | struct mwifiex_ra_list_tbl *ra_list; |
| @@ -566,7 +565,7 @@ mwifiex_clean_txrx(struct mwifiex_private *priv) | |||
| 566 | */ | 565 | */ |
| 567 | static struct mwifiex_ra_list_tbl * | 566 | static struct mwifiex_ra_list_tbl * |
| 568 | mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, | 567 | mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, |
| 569 | u8 *ra_addr) | 568 | const u8 *ra_addr) |
| 570 | { | 569 | { |
| 571 | struct mwifiex_ra_list_tbl *ra_list; | 570 | struct mwifiex_ra_list_tbl *ra_list; |
| 572 | 571 | ||
| @@ -587,7 +586,8 @@ mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, | |||
| 587 | * retrieved. | 586 | * retrieved. |
| 588 | */ | 587 | */ |
| 589 | struct mwifiex_ra_list_tbl * | 588 | struct mwifiex_ra_list_tbl * |
| 590 | mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) | 589 | mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, |
| 590 | const u8 *ra_addr) | ||
| 591 | { | 591 | { |
| 592 | struct mwifiex_ra_list_tbl *ra_list; | 592 | struct mwifiex_ra_list_tbl *ra_list; |
| 593 | 593 | ||
| @@ -648,7 +648,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, | |||
| 648 | if (ntohs(eth_hdr->h_proto) == ETH_P_TDLS) | 648 | if (ntohs(eth_hdr->h_proto) == ETH_P_TDLS) |
| 649 | dev_dbg(adapter->dev, | 649 | dev_dbg(adapter->dev, |
| 650 | "TDLS setup packet for %pM. Don't block\n", ra); | 650 | "TDLS setup packet for %pM. Don't block\n", ra); |
| 651 | else | 651 | else if (memcmp(priv->cfg_bssid, ra, ETH_ALEN)) |
| 652 | tdls_status = mwifiex_get_tdls_link_status(priv, ra); | 652 | tdls_status = mwifiex_get_tdls_link_status(priv, ra); |
| 653 | } | 653 | } |
| 654 | 654 | ||
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h index 83e42083ebff..eca56e371a57 100644 --- a/drivers/net/wireless/mwifiex/wmm.h +++ b/drivers/net/wireless/mwifiex/wmm.h | |||
| @@ -99,7 +99,7 @@ mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead) | |||
| 99 | 99 | ||
| 100 | void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, | 100 | void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, |
| 101 | struct sk_buff *skb); | 101 | struct sk_buff *skb); |
| 102 | void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra); | 102 | void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra); |
| 103 | void mwifiex_rotate_priolists(struct mwifiex_private *priv, | 103 | void mwifiex_rotate_priolists(struct mwifiex_private *priv, |
| 104 | struct mwifiex_ra_list_tbl *ra, int tid); | 104 | struct mwifiex_ra_list_tbl *ra, int tid); |
| 105 | 105 | ||
| @@ -123,7 +123,8 @@ void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); | |||
| 123 | int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, | 123 | int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, |
| 124 | const struct host_cmd_ds_command *resp); | 124 | const struct host_cmd_ds_command *resp); |
| 125 | struct mwifiex_ra_list_tbl * | 125 | struct mwifiex_ra_list_tbl * |
| 126 | mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr); | 126 | mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, |
| 127 | const u8 *ra_addr); | ||
| 127 | u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid); | 128 | u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid); |
| 128 | 129 | ||
| 129 | #endif /* !_MWIFIEX_WMM_H_ */ | 130 | #endif /* !_MWIFIEX_WMM_H_ */ |
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 49300d04efdf..e27e32851f1e 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c | |||
| @@ -988,8 +988,8 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv) | |||
| 988 | * tsc must be NULL or up to 8 bytes | 988 | * tsc must be NULL or up to 8 bytes |
| 989 | */ | 989 | */ |
| 990 | int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, | 990 | int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, |
| 991 | int set_tx, u8 *key, u8 *rsc, size_t rsc_len, | 991 | int set_tx, const u8 *key, const u8 *rsc, |
| 992 | u8 *tsc, size_t tsc_len) | 992 | size_t rsc_len, const u8 *tsc, size_t tsc_len) |
| 993 | { | 993 | { |
| 994 | struct { | 994 | struct { |
| 995 | __le16 idx; | 995 | __le16 idx; |
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h index 8f6831f4e328..466d1ede76f1 100644 --- a/drivers/net/wireless/orinoco/hw.h +++ b/drivers/net/wireless/orinoco/hw.h | |||
| @@ -38,8 +38,8 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv); | |||
| 38 | int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv); | 38 | int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv); |
| 39 | int __orinoco_hw_setup_enc(struct orinoco_private *priv); | 39 | int __orinoco_hw_setup_enc(struct orinoco_private *priv); |
| 40 | int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, | 40 | int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, |
| 41 | int set_tx, u8 *key, u8 *rsc, size_t rsc_len, | 41 | int set_tx, const u8 *key, const u8 *rsc, |
| 42 | u8 *tsc, size_t tsc_len); | 42 | size_t rsc_len, const u8 *tsc, size_t tsc_len); |
| 43 | int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx); | 43 | int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx); |
| 44 | int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, | 44 | int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, |
| 45 | struct net_device *dev, | 45 | struct net_device *dev, |
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index f9805c9353d2..1cbb7835806f 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c | |||
| @@ -1687,7 +1687,7 @@ static int ezusb_probe(struct usb_interface *interface, | |||
| 1687 | firmware.code = fw_entry->data; | 1687 | firmware.code = fw_entry->data; |
| 1688 | } | 1688 | } |
| 1689 | if (firmware.size && firmware.code) { | 1689 | if (firmware.size && firmware.code) { |
| 1690 | if (ezusb_firmware_download(upriv, &firmware)) | 1690 | if (ezusb_firmware_download(upriv, &firmware) < 0) |
| 1691 | goto error; | 1691 | goto error; |
| 1692 | } else { | 1692 | } else { |
| 1693 | err("No firmware to download"); | 1693 | err("No firmware to download"); |
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index b7a867b50b94..6abdaf0aa052 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c | |||
| @@ -52,9 +52,9 @@ static int orinoco_set_key(struct orinoco_private *priv, int index, | |||
| 52 | priv->keys[index].seq_len = seq_len; | 52 | priv->keys[index].seq_len = seq_len; |
| 53 | 53 | ||
| 54 | if (key_len) | 54 | if (key_len) |
| 55 | memcpy(priv->keys[index].key, key, key_len); | 55 | memcpy((void *)priv->keys[index].key, key, key_len); |
| 56 | if (seq_len) | 56 | if (seq_len) |
| 57 | memcpy(priv->keys[index].seq, seq, seq_len); | 57 | memcpy((void *)priv->keys[index].seq, seq, seq_len); |
| 58 | 58 | ||
| 59 | switch (alg) { | 59 | switch (alg) { |
| 60 | case ORINOCO_ALG_TKIP: | 60 | case ORINOCO_ALG_TKIP: |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 39d22a154341..d2a9a08210be 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
| @@ -517,7 +517,7 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | |||
| 517 | u8 key_index, bool unicast, bool multicast); | 517 | u8 key_index, bool unicast, bool multicast); |
| 518 | 518 | ||
| 519 | static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, | 519 | static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, |
| 520 | u8 *mac, struct station_info *sinfo); | 520 | const u8 *mac, struct station_info *sinfo); |
| 521 | 521 | ||
| 522 | static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, | 522 | static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, |
| 523 | int idx, u8 *mac, struct station_info *sinfo); | 523 | int idx, u8 *mac, struct station_info *sinfo); |
| @@ -2490,7 +2490,7 @@ static void rndis_fill_station_info(struct usbnet *usbdev, | |||
| 2490 | } | 2490 | } |
| 2491 | 2491 | ||
| 2492 | static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, | 2492 | static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, |
| 2493 | u8 *mac, struct station_info *sinfo) | 2493 | const u8 *mac, struct station_info *sinfo) |
| 2494 | { | 2494 | { |
| 2495 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | 2495 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); |
| 2496 | struct usbnet *usbdev = priv->usbdev; | 2496 | struct usbnet *usbdev = priv->usbdev; |
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 84164747ace0..54aaeb09debf 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c | |||
| @@ -656,6 +656,7 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw, | |||
| 656 | case IEEE80211_AMPDU_TX_START: | 656 | case IEEE80211_AMPDU_TX_START: |
| 657 | common->vif_info[ii].seq_start = seq_no; | 657 | common->vif_info[ii].seq_start = seq_no; |
| 658 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 658 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
| 659 | status = 0; | ||
| 659 | break; | 660 | break; |
| 660 | 661 | ||
| 661 | case IEEE80211_AMPDU_TX_STOP_CONT: | 662 | case IEEE80211_AMPDU_TX_STOP_CONT: |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 10572452cc21..86c43d112a4b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
| @@ -68,6 +68,12 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, | |||
| 68 | } | 68 | } |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | /* If the port is powered down, we get a -EPROTO error, and this | ||
| 72 | * leads to a endless loop. So just say that the device is gone. | ||
| 73 | */ | ||
| 74 | if (status == -EPROTO) | ||
| 75 | clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); | ||
| 76 | |||
| 71 | rt2x00_err(rt2x00dev, | 77 | rt2x00_err(rt2x00dev, |
| 72 | "Vendor Request 0x%02x failed for offset 0x%04x with error %d\n", | 78 | "Vendor Request 0x%02x failed for offset 0x%04x with error %d\n", |
| 73 | request, offset, status); | 79 | request, offset, status); |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index 50d69b13f984..2c1c02bafa10 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c | |||
| @@ -284,6 +284,8 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) | |||
| 284 | rx_status.band = dev->conf.chandef.chan->band; | 284 | rx_status.band = dev->conf.chandef.chan->band; |
| 285 | rx_status.mactime = tsft; | 285 | rx_status.mactime = tsft; |
| 286 | rx_status.flag |= RX_FLAG_MACTIME_START; | 286 | rx_status.flag |= RX_FLAG_MACTIME_START; |
| 287 | if (flags & RTL818X_RX_DESC_FLAG_SPLCP) | ||
| 288 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
| 287 | if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) | 289 | if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) |
| 288 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; | 290 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; |
| 289 | 291 | ||
| @@ -461,18 +463,23 @@ static void rtl8180_tx(struct ieee80211_hw *dev, | |||
| 461 | RTL818X_TX_DESC_FLAG_NO_ENC; | 463 | RTL818X_TX_DESC_FLAG_NO_ENC; |
| 462 | 464 | ||
| 463 | rc_flags = info->control.rates[0].flags; | 465 | rc_flags = info->control.rates[0].flags; |
| 466 | |||
| 467 | /* HW will perform RTS-CTS when only RTS flags is set. | ||
| 468 | * HW will perform CTS-to-self when both RTS and CTS flags are set. | ||
| 469 | * RTS rate and RTS duration will be used also for CTS-to-self. | ||
| 470 | */ | ||
| 464 | if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { | 471 | if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { |
| 465 | tx_flags |= RTL818X_TX_DESC_FLAG_RTS; | 472 | tx_flags |= RTL818X_TX_DESC_FLAG_RTS; |
| 466 | tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; | 473 | tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; |
| 474 | rts_duration = ieee80211_rts_duration(dev, priv->vif, | ||
| 475 | skb->len, info); | ||
| 467 | } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | 476 | } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
| 468 | tx_flags |= RTL818X_TX_DESC_FLAG_CTS; | 477 | tx_flags |= RTL818X_TX_DESC_FLAG_RTS | RTL818X_TX_DESC_FLAG_CTS; |
| 469 | tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; | 478 | tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; |
| 479 | rts_duration = ieee80211_ctstoself_duration(dev, priv->vif, | ||
| 480 | skb->len, info); | ||
| 470 | } | 481 | } |
| 471 | 482 | ||
| 472 | if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) | ||
| 473 | rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len, | ||
| 474 | info); | ||
| 475 | |||
| 476 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) { | 483 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) { |
| 477 | unsigned int remainder; | 484 | unsigned int remainder; |
| 478 | 485 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 0ca17cda48fa..629ad8cfa17b 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c | |||
| @@ -253,14 +253,21 @@ static void rtl8187_tx(struct ieee80211_hw *dev, | |||
| 253 | flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24; | 253 | flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24; |
| 254 | if (ieee80211_has_morefrags(tx_hdr->frame_control)) | 254 | if (ieee80211_has_morefrags(tx_hdr->frame_control)) |
| 255 | flags |= RTL818X_TX_DESC_FLAG_MOREFRAG; | 255 | flags |= RTL818X_TX_DESC_FLAG_MOREFRAG; |
| 256 | |||
| 257 | /* HW will perform RTS-CTS when only RTS flags is set. | ||
| 258 | * HW will perform CTS-to-self when both RTS and CTS flags are set. | ||
| 259 | * RTS rate and RTS duration will be used also for CTS-to-self. | ||
| 260 | */ | ||
| 256 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | 261 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { |
| 257 | flags |= RTL818X_TX_DESC_FLAG_RTS; | 262 | flags |= RTL818X_TX_DESC_FLAG_RTS; |
| 258 | flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; | 263 | flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; |
| 259 | rts_dur = ieee80211_rts_duration(dev, priv->vif, | 264 | rts_dur = ieee80211_rts_duration(dev, priv->vif, |
| 260 | skb->len, info); | 265 | skb->len, info); |
| 261 | } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | 266 | } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
| 262 | flags |= RTL818X_TX_DESC_FLAG_CTS; | 267 | flags |= RTL818X_TX_DESC_FLAG_RTS | RTL818X_TX_DESC_FLAG_CTS; |
| 263 | flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; | 268 | flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; |
| 269 | rts_dur = ieee80211_ctstoself_duration(dev, priv->vif, | ||
| 270 | skb->len, info); | ||
| 264 | } | 271 | } |
| 265 | 272 | ||
| 266 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 273 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
| @@ -381,6 +388,8 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
| 381 | rx_status.freq = dev->conf.chandef.chan->center_freq; | 388 | rx_status.freq = dev->conf.chandef.chan->center_freq; |
| 382 | rx_status.band = dev->conf.chandef.chan->band; | 389 | rx_status.band = dev->conf.chandef.chan->band; |
| 383 | rx_status.flag |= RX_FLAG_MACTIME_START; | 390 | rx_status.flag |= RX_FLAG_MACTIME_START; |
| 391 | if (flags & RTL818X_RX_DESC_FLAG_SPLCP) | ||
| 392 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
| 384 | if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) | 393 | if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) |
| 385 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; | 394 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; |
| 386 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | 395 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c index 94cd9df98381..b14cf5a10f44 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c | |||
| @@ -2515,23 +2515,3 @@ void rtl88ee_suspend(struct ieee80211_hw *hw) | |||
| 2515 | void rtl88ee_resume(struct ieee80211_hw *hw) | 2515 | void rtl88ee_resume(struct ieee80211_hw *hw) |
| 2516 | { | 2516 | { |
| 2517 | } | 2517 | } |
| 2518 | |||
| 2519 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
| 2520 | void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw, | ||
| 2521 | bool allow_all_da, bool write_into_reg) | ||
| 2522 | { | ||
| 2523 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 2524 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
| 2525 | |||
| 2526 | if (allow_all_da) /* Set BIT0 */ | ||
| 2527 | rtlpci->receive_config |= RCR_AAP; | ||
| 2528 | else /* Clear BIT0 */ | ||
| 2529 | rtlpci->receive_config &= ~RCR_AAP; | ||
| 2530 | |||
| 2531 | if (write_into_reg) | ||
| 2532 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
| 2533 | |||
| 2534 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
| 2535 | "receive_config = 0x%08X, write_into_reg =%d\n", | ||
| 2536 | rtlpci->receive_config, write_into_reg); | ||
| 2537 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h index b4460a41bd01..1850fde881b5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h | |||
| @@ -61,8 +61,6 @@ void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw); | |||
| 61 | void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw); | 61 | void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw); |
| 62 | void rtl88ee_suspend(struct ieee80211_hw *hw); | 62 | void rtl88ee_suspend(struct ieee80211_hw *hw); |
| 63 | void rtl88ee_resume(struct ieee80211_hw *hw); | 63 | void rtl88ee_resume(struct ieee80211_hw *hw); |
| 64 | void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw, | ||
| 65 | bool allow_all_da, bool write_into_reg); | ||
| 66 | void rtl88ee_fw_clk_off_timer_callback(unsigned long data); | 64 | void rtl88ee_fw_clk_off_timer_callback(unsigned long data); |
| 67 | 65 | ||
| 68 | #endif | 66 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c index 347af1e4f438..842d69349a37 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c | |||
| @@ -93,6 +93,7 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw) | |||
| 93 | u8 tid; | 93 | u8 tid; |
| 94 | 94 | ||
| 95 | rtl8188ee_bt_reg_init(hw); | 95 | rtl8188ee_bt_reg_init(hw); |
| 96 | rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; | ||
| 96 | 97 | ||
| 97 | rtlpriv->dm.dm_initialgain_enable = 1; | 98 | rtlpriv->dm.dm_initialgain_enable = 1; |
| 98 | rtlpriv->dm.dm_flag = 0; | 99 | rtlpriv->dm.dm_flag = 0; |
| @@ -254,7 +255,6 @@ static struct rtl_hal_ops rtl8188ee_hal_ops = { | |||
| 254 | .enable_hw_sec = rtl88ee_enable_hw_security_config, | 255 | .enable_hw_sec = rtl88ee_enable_hw_security_config, |
| 255 | .set_key = rtl88ee_set_key, | 256 | .set_key = rtl88ee_set_key, |
| 256 | .init_sw_leds = rtl88ee_init_sw_leds, | 257 | .init_sw_leds = rtl88ee_init_sw_leds, |
| 257 | .allow_all_destaddr = rtl88ee_allow_all_destaddr, | ||
| 258 | .get_bbreg = rtl88e_phy_query_bb_reg, | 258 | .get_bbreg = rtl88e_phy_query_bb_reg, |
| 259 | .set_bbreg = rtl88e_phy_set_bb_reg, | 259 | .set_bbreg = rtl88e_phy_set_bb_reg, |
| 260 | .get_rfreg = rtl88e_phy_query_rf_reg, | 260 | .get_rfreg = rtl88e_phy_query_rf_reg, |
| @@ -266,6 +266,7 @@ static struct rtl_mod_params rtl88ee_mod_params = { | |||
| 266 | .inactiveps = true, | 266 | .inactiveps = true, |
| 267 | .swctrl_lps = false, | 267 | .swctrl_lps = false, |
| 268 | .fwctrl_lps = true, | 268 | .fwctrl_lps = true, |
| 269 | .msi_support = false, | ||
| 269 | .debug = DBG_EMERG, | 270 | .debug = DBG_EMERG, |
| 270 | }; | 271 | }; |
| 271 | 272 | ||
| @@ -382,10 +383,12 @@ module_param_named(debug, rtl88ee_mod_params.debug, int, 0444); | |||
| 382 | module_param_named(ips, rtl88ee_mod_params.inactiveps, bool, 0444); | 383 | module_param_named(ips, rtl88ee_mod_params.inactiveps, bool, 0444); |
| 383 | module_param_named(swlps, rtl88ee_mod_params.swctrl_lps, bool, 0444); | 384 | module_param_named(swlps, rtl88ee_mod_params.swctrl_lps, bool, 0444); |
| 384 | module_param_named(fwlps, rtl88ee_mod_params.fwctrl_lps, bool, 0444); | 385 | module_param_named(fwlps, rtl88ee_mod_params.fwctrl_lps, bool, 0444); |
| 386 | module_param_named(msi, rtl88ee_mod_params.msi_support, bool, 0444); | ||
| 385 | MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); | 387 | MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); |
| 386 | MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); | 388 | MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); |
| 387 | MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); | 389 | MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); |
| 388 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); | 390 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); |
| 391 | MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n"); | ||
| 389 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); | 392 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); |
| 390 | 393 | ||
| 391 | static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); | 394 | static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 55adf043aef7..cdecb0fd4d8e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | |||
| @@ -2423,24 +2423,3 @@ void rtl92ce_suspend(struct ieee80211_hw *hw) | |||
| 2423 | void rtl92ce_resume(struct ieee80211_hw *hw) | 2423 | void rtl92ce_resume(struct ieee80211_hw *hw) |
| 2424 | { | 2424 | { |
| 2425 | } | 2425 | } |
| 2426 | |||
| 2427 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
| 2428 | void rtl92ce_allow_all_destaddr(struct ieee80211_hw *hw, | ||
| 2429 | bool allow_all_da, bool write_into_reg) | ||
| 2430 | { | ||
| 2431 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 2432 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
| 2433 | |||
| 2434 | if (allow_all_da) {/* Set BIT0 */ | ||
| 2435 | rtlpci->receive_config |= RCR_AAP; | ||
| 2436 | } else {/* Clear BIT0 */ | ||
| 2437 | rtlpci->receive_config &= ~RCR_AAP; | ||
| 2438 | } | ||
| 2439 | |||
| 2440 | if (write_into_reg) | ||
| 2441 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
| 2442 | |||
| 2443 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
| 2444 | "receive_config=0x%08X, write_into_reg=%d\n", | ||
| 2445 | rtlpci->receive_config, write_into_reg); | ||
| 2446 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h index 2d063b0c7760..5533070f266c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h | |||
| @@ -76,7 +76,5 @@ void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw); | |||
| 76 | void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); | 76 | void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); |
| 77 | void rtl92ce_suspend(struct ieee80211_hw *hw); | 77 | void rtl92ce_suspend(struct ieee80211_hw *hw); |
| 78 | void rtl92ce_resume(struct ieee80211_hw *hw); | 78 | void rtl92ce_resume(struct ieee80211_hw *hw); |
| 79 | void rtl92ce_allow_all_destaddr(struct ieee80211_hw *hw, | ||
| 80 | bool allow_all_da, bool write_into_reg); | ||
| 81 | 79 | ||
| 82 | #endif | 80 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index b790320d2030..12f21f4073e8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | |||
| @@ -229,7 +229,6 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { | |||
| 229 | .enable_hw_sec = rtl92ce_enable_hw_security_config, | 229 | .enable_hw_sec = rtl92ce_enable_hw_security_config, |
| 230 | .set_key = rtl92ce_set_key, | 230 | .set_key = rtl92ce_set_key, |
| 231 | .init_sw_leds = rtl92ce_init_sw_leds, | 231 | .init_sw_leds = rtl92ce_init_sw_leds, |
| 232 | .allow_all_destaddr = rtl92ce_allow_all_destaddr, | ||
| 233 | .get_bbreg = rtl92c_phy_query_bb_reg, | 232 | .get_bbreg = rtl92c_phy_query_bb_reg, |
| 234 | .set_bbreg = rtl92c_phy_set_bb_reg, | 233 | .set_bbreg = rtl92c_phy_set_bb_reg, |
| 235 | .set_rfreg = rtl92ce_phy_set_rf_reg, | 234 | .set_rfreg = rtl92ce_phy_set_rf_reg, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 07cb06da6729..a903c2671b4d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
| @@ -511,7 +511,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw) | |||
| 511 | pr_info("MAC auto ON okay!\n"); | 511 | pr_info("MAC auto ON okay!\n"); |
| 512 | break; | 512 | break; |
| 513 | } | 513 | } |
| 514 | if (pollingCount++ > 100) { | 514 | if (pollingCount++ > 1000) { |
| 515 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, | 515 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, |
| 516 | "Failed to polling REG_APS_FSMCO[APFM_ONMAC] done!\n"); | 516 | "Failed to polling REG_APS_FSMCO[APFM_ONMAC] done!\n"); |
| 517 | return -ENODEV; | 517 | return -ENODEV; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c index 9098558d916d..1c7101bcd790 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c | |||
| @@ -2544,23 +2544,3 @@ void rtl92se_resume(struct ieee80211_hw *hw) | |||
| 2544 | pci_write_config_dword(rtlpci->pdev, 0x40, | 2544 | pci_write_config_dword(rtlpci->pdev, 0x40, |
| 2545 | val & 0xffff00ff); | 2545 | val & 0xffff00ff); |
| 2546 | } | 2546 | } |
| 2547 | |||
| 2548 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
| 2549 | void rtl92se_allow_all_destaddr(struct ieee80211_hw *hw, | ||
| 2550 | bool allow_all_da, bool write_into_reg) | ||
| 2551 | { | ||
| 2552 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 2553 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
| 2554 | |||
| 2555 | if (allow_all_da) /* Set BIT0 */ | ||
| 2556 | rtlpci->receive_config |= RCR_AAP; | ||
| 2557 | else /* Clear BIT0 */ | ||
| 2558 | rtlpci->receive_config &= ~RCR_AAP; | ||
| 2559 | |||
| 2560 | if (write_into_reg) | ||
| 2561 | rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); | ||
| 2562 | |||
| 2563 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
| 2564 | "receive_config=0x%08X, write_into_reg=%d\n", | ||
| 2565 | rtlpci->receive_config, write_into_reg); | ||
| 2566 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h index da48aa8cbe6f..4cacee10f31e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h | |||
| @@ -74,7 +74,5 @@ void rtl92se_set_key(struct ieee80211_hw *hw, | |||
| 74 | u8 enc_algo, bool is_wepkey, bool clear_all); | 74 | u8 enc_algo, bool is_wepkey, bool clear_all); |
| 75 | void rtl92se_suspend(struct ieee80211_hw *hw); | 75 | void rtl92se_suspend(struct ieee80211_hw *hw); |
| 76 | void rtl92se_resume(struct ieee80211_hw *hw); | 76 | void rtl92se_resume(struct ieee80211_hw *hw); |
| 77 | void rtl92se_allow_all_destaddr(struct ieee80211_hw *hw, | ||
| 78 | bool allow_all_da, bool write_into_reg); | ||
| 79 | 77 | ||
| 80 | #endif | 78 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 2e8e6f8d2d51..1bff2a0f7600 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c | |||
| @@ -290,7 +290,6 @@ static struct rtl_hal_ops rtl8192se_hal_ops = { | |||
| 290 | .enable_hw_sec = rtl92se_enable_hw_security_config, | 290 | .enable_hw_sec = rtl92se_enable_hw_security_config, |
| 291 | .set_key = rtl92se_set_key, | 291 | .set_key = rtl92se_set_key, |
| 292 | .init_sw_leds = rtl92se_init_sw_leds, | 292 | .init_sw_leds = rtl92se_init_sw_leds, |
| 293 | .allow_all_destaddr = rtl92se_allow_all_destaddr, | ||
| 294 | .get_bbreg = rtl92s_phy_query_bb_reg, | 293 | .get_bbreg = rtl92s_phy_query_bb_reg, |
| 295 | .set_bbreg = rtl92s_phy_set_bb_reg, | 294 | .set_bbreg = rtl92s_phy_set_bb_reg, |
| 296 | .get_rfreg = rtl92s_phy_query_rf_reg, | 295 | .get_rfreg = rtl92s_phy_query_rf_reg, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c index 65c9e80e1f78..87f69166a7ed 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c | |||
| @@ -2383,24 +2383,3 @@ void rtl8723ae_suspend(struct ieee80211_hw *hw) | |||
| 2383 | void rtl8723ae_resume(struct ieee80211_hw *hw) | 2383 | void rtl8723ae_resume(struct ieee80211_hw *hw) |
| 2384 | { | 2384 | { |
| 2385 | } | 2385 | } |
| 2386 | |||
| 2387 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
| 2388 | void rtl8723ae_allow_all_destaddr(struct ieee80211_hw *hw, | ||
| 2389 | bool allow_all_da, bool write_into_reg) | ||
| 2390 | { | ||
| 2391 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 2392 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
| 2393 | |||
| 2394 | if (allow_all_da) /* Set BIT0 */ | ||
| 2395 | rtlpci->receive_config |= RCR_AAP; | ||
| 2396 | else /* Clear BIT0 */ | ||
| 2397 | rtlpci->receive_config &= ~RCR_AAP; | ||
| 2398 | |||
| 2399 | if (write_into_reg) | ||
| 2400 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
| 2401 | |||
| 2402 | |||
| 2403 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
| 2404 | "receive_config=0x%08X, write_into_reg=%d\n", | ||
| 2405 | rtlpci->receive_config, write_into_reg); | ||
| 2406 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h index 6fa24f79b1d7..d3bc39fb27a5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h | |||
| @@ -67,7 +67,5 @@ void rtl8723ae_bt_reg_init(struct ieee80211_hw *hw); | |||
| 67 | void rtl8723ae_bt_hw_init(struct ieee80211_hw *hw); | 67 | void rtl8723ae_bt_hw_init(struct ieee80211_hw *hw); |
| 68 | void rtl8723ae_suspend(struct ieee80211_hw *hw); | 68 | void rtl8723ae_suspend(struct ieee80211_hw *hw); |
| 69 | void rtl8723ae_resume(struct ieee80211_hw *hw); | 69 | void rtl8723ae_resume(struct ieee80211_hw *hw); |
| 70 | void rtl8723ae_allow_all_destaddr(struct ieee80211_hw *hw, | ||
| 71 | bool allow_all_da, bool write_into_reg); | ||
| 72 | 70 | ||
| 73 | #endif | 71 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c index 1087a3bd07fa..73cba1eec8cf 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c | |||
| @@ -238,7 +238,6 @@ static struct rtl_hal_ops rtl8723ae_hal_ops = { | |||
| 238 | .enable_hw_sec = rtl8723ae_enable_hw_security_config, | 238 | .enable_hw_sec = rtl8723ae_enable_hw_security_config, |
| 239 | .set_key = rtl8723ae_set_key, | 239 | .set_key = rtl8723ae_set_key, |
| 240 | .init_sw_leds = rtl8723ae_init_sw_leds, | 240 | .init_sw_leds = rtl8723ae_init_sw_leds, |
| 241 | .allow_all_destaddr = rtl8723ae_allow_all_destaddr, | ||
| 242 | .get_bbreg = rtl8723_phy_query_bb_reg, | 241 | .get_bbreg = rtl8723_phy_query_bb_reg, |
| 243 | .set_bbreg = rtl8723_phy_set_bb_reg, | 242 | .set_bbreg = rtl8723_phy_set_bb_reg, |
| 244 | .get_rfreg = rtl8723ae_phy_query_rf_reg, | 243 | .get_rfreg = rtl8723ae_phy_query_rf_reg, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/rtlwifi/rtl8723be/hw.c index 0fdf0909321f..3d555495b453 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723be/hw.c | |||
| @@ -2501,23 +2501,3 @@ void rtl8723be_suspend(struct ieee80211_hw *hw) | |||
| 2501 | void rtl8723be_resume(struct ieee80211_hw *hw) | 2501 | void rtl8723be_resume(struct ieee80211_hw *hw) |
| 2502 | { | 2502 | { |
| 2503 | } | 2503 | } |
| 2504 | |||
| 2505 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
| 2506 | void rtl8723be_allow_all_destaddr(struct ieee80211_hw *hw, bool allow_all_da, | ||
| 2507 | bool write_into_reg) | ||
| 2508 | { | ||
| 2509 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 2510 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
| 2511 | |||
| 2512 | if (allow_all_da) /* Set BIT0 */ | ||
| 2513 | rtlpci->receive_config |= RCR_AAP; | ||
| 2514 | else /* Clear BIT0 */ | ||
| 2515 | rtlpci->receive_config &= ~RCR_AAP; | ||
| 2516 | |||
| 2517 | if (write_into_reg) | ||
| 2518 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
| 2519 | |||
| 2520 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
| 2521 | "receive_config = 0x%08X, write_into_reg =%d\n", | ||
| 2522 | rtlpci->receive_config, write_into_reg); | ||
| 2523 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.h b/drivers/net/wireless/rtlwifi/rtl8723be/hw.h index b7449a9b57e4..64c7551af6b7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8723be/hw.h | |||
| @@ -59,6 +59,4 @@ void rtl8723be_bt_reg_init(struct ieee80211_hw *hw); | |||
| 59 | void rtl8723be_bt_hw_init(struct ieee80211_hw *hw); | 59 | void rtl8723be_bt_hw_init(struct ieee80211_hw *hw); |
| 60 | void rtl8723be_suspend(struct ieee80211_hw *hw); | 60 | void rtl8723be_suspend(struct ieee80211_hw *hw); |
| 61 | void rtl8723be_resume(struct ieee80211_hw *hw); | 61 | void rtl8723be_resume(struct ieee80211_hw *hw); |
| 62 | void rtl8723be_allow_all_destaddr(struct ieee80211_hw *hw, bool allow_all_da, | ||
| 63 | bool write_into_reg); | ||
| 64 | #endif | 62 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/rtlwifi/rtl8723be/sw.c index a07213645da0..ff12bf41644b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723be/sw.c | |||
| @@ -92,7 +92,7 @@ int rtl8723be_init_sw_vars(struct ieee80211_hw *hw) | |||
| 92 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 92 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 93 | 93 | ||
| 94 | rtl8723be_bt_reg_init(hw); | 94 | rtl8723be_bt_reg_init(hw); |
| 95 | rtlpci->msi_support = false; | 95 | rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; |
| 96 | rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); | 96 | rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); |
| 97 | 97 | ||
| 98 | rtlpriv->dm.dm_initialgain_enable = 1; | 98 | rtlpriv->dm.dm_initialgain_enable = 1; |
| @@ -253,6 +253,7 @@ static struct rtl_mod_params rtl8723be_mod_params = { | |||
| 253 | .inactiveps = true, | 253 | .inactiveps = true, |
| 254 | .swctrl_lps = false, | 254 | .swctrl_lps = false, |
| 255 | .fwctrl_lps = true, | 255 | .fwctrl_lps = true, |
| 256 | .msi_support = false, | ||
| 256 | .debug = DBG_EMERG, | 257 | .debug = DBG_EMERG, |
| 257 | }; | 258 | }; |
| 258 | 259 | ||
| @@ -365,9 +366,11 @@ module_param_named(debug, rtl8723be_mod_params.debug, int, 0444); | |||
| 365 | module_param_named(ips, rtl8723be_mod_params.inactiveps, bool, 0444); | 366 | module_param_named(ips, rtl8723be_mod_params.inactiveps, bool, 0444); |
| 366 | module_param_named(swlps, rtl8723be_mod_params.swctrl_lps, bool, 0444); | 367 | module_param_named(swlps, rtl8723be_mod_params.swctrl_lps, bool, 0444); |
| 367 | module_param_named(fwlps, rtl8723be_mod_params.fwctrl_lps, bool, 0444); | 368 | module_param_named(fwlps, rtl8723be_mod_params.fwctrl_lps, bool, 0444); |
| 369 | module_param_named(msi, rtl8723be_mod_params.msi_support, bool, 0444); | ||
| 368 | MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); | 370 | MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); |
| 369 | MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); | 371 | MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); |
| 370 | MODULE_PARM_DESC(fwlps, "using linked fw control power save (default 1 is open)\n"); | 372 | MODULE_PARM_DESC(fwlps, "using linked fw control power save (default 1 is open)\n"); |
| 373 | MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n"); | ||
| 371 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); | 374 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); |
| 372 | 375 | ||
| 373 | static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); | 376 | static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 6965afdf572a..407a7936d364 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
| @@ -1960,8 +1960,6 @@ struct rtl_hal_ops { | |||
| 1960 | u32 regaddr, u32 bitmask); | 1960 | u32 regaddr, u32 bitmask); |
| 1961 | void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, | 1961 | void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, |
| 1962 | u32 regaddr, u32 bitmask, u32 data); | 1962 | u32 regaddr, u32 bitmask, u32 data); |
| 1963 | void (*allow_all_destaddr)(struct ieee80211_hw *hw, | ||
| 1964 | bool allow_all_da, bool write_into_reg); | ||
| 1965 | void (*linked_set_reg) (struct ieee80211_hw *hw); | 1963 | void (*linked_set_reg) (struct ieee80211_hw *hw); |
| 1966 | void (*chk_switch_dmdp) (struct ieee80211_hw *hw); | 1964 | void (*chk_switch_dmdp) (struct ieee80211_hw *hw); |
| 1967 | void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); | 1965 | void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); |
| @@ -2030,6 +2028,10 @@ struct rtl_mod_params { | |||
| 2030 | 2028 | ||
| 2031 | /* default: 1 = using linked fw power save */ | 2029 | /* default: 1 = using linked fw power save */ |
| 2032 | bool fwctrl_lps; | 2030 | bool fwctrl_lps; |
| 2031 | |||
| 2032 | /* default: 0 = not using MSI interrupts mode */ | ||
| 2033 | /* submodules should set their own defalut value */ | ||
| 2034 | bool msi_support; | ||
| 2033 | }; | 2035 | }; |
| 2034 | 2036 | ||
| 2035 | struct rtl_hal_usbint_cfg { | 2037 | struct rtl_hal_usbint_cfg { |
diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c index 5a4ec56c83d0..5695628757ee 100644 --- a/drivers/net/wireless/ti/wl1251/acx.c +++ b/drivers/net/wireless/ti/wl1251/acx.c | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | 2 | ||
| 3 | #include <linux/module.h> | 3 | #include <linux/module.h> |
| 4 | #include <linux/slab.h> | 4 | #include <linux/slab.h> |
| 5 | #include <linux/crc7.h> | ||
| 6 | 5 | ||
| 7 | #include "wl1251.h" | 6 | #include "wl1251.h" |
| 8 | #include "reg.h" | 7 | #include "reg.h" |
diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c index bf1fa18b9786..ede31f048ef9 100644 --- a/drivers/net/wireless/ti/wl1251/cmd.c +++ b/drivers/net/wireless/ti/wl1251/cmd.c | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | 2 | ||
| 3 | #include <linux/module.h> | 3 | #include <linux/module.h> |
| 4 | #include <linux/slab.h> | 4 | #include <linux/slab.h> |
| 5 | #include <linux/crc7.h> | ||
| 6 | #include <linux/etherdevice.h> | 5 | #include <linux/etherdevice.h> |
| 7 | 6 | ||
| 8 | #include "wl1251.h" | 7 | #include "wl1251.h" |
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c index db0105313745..c98630394a1a 100644 --- a/drivers/net/wireless/ti/wl1251/event.c +++ b/drivers/net/wireless/ti/wl1251/event.c | |||
| @@ -124,11 +124,12 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) | |||
| 124 | return ret; | 124 | return ret; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | if (wl->vif && vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) { | 127 | if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) { |
| 128 | wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); | 128 | wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); |
| 129 | 129 | ||
| 130 | /* indicate to the stack, that beacons have been lost */ | 130 | /* indicate to the stack, that beacons have been lost */ |
| 131 | ieee80211_beacon_loss(wl->vif); | 131 | if (wl->vif && wl->vif->type == NL80211_IFTYPE_STATION) |
| 132 | ieee80211_beacon_loss(wl->vif); | ||
| 132 | } | 133 | } |
| 133 | 134 | ||
| 134 | if (vector & REGAINED_BSS_EVENT_ID) { | 135 | if (vector & REGAINED_BSS_EVENT_ID) { |
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 757e25784a8a..4e782f18ae34 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
| @@ -550,6 +550,34 @@ static void wl1251_op_remove_interface(struct ieee80211_hw *hw, | |||
| 550 | mutex_unlock(&wl->mutex); | 550 | mutex_unlock(&wl->mutex); |
| 551 | } | 551 | } |
| 552 | 552 | ||
| 553 | static int wl1251_build_null_data(struct wl1251 *wl) | ||
| 554 | { | ||
| 555 | struct sk_buff *skb = NULL; | ||
| 556 | int size; | ||
| 557 | void *ptr; | ||
| 558 | int ret = -ENOMEM; | ||
| 559 | |||
| 560 | if (wl->bss_type == BSS_TYPE_IBSS) { | ||
| 561 | size = sizeof(struct wl12xx_null_data_template); | ||
| 562 | ptr = NULL; | ||
| 563 | } else { | ||
| 564 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); | ||
| 565 | if (!skb) | ||
| 566 | goto out; | ||
| 567 | size = skb->len; | ||
| 568 | ptr = skb->data; | ||
| 569 | } | ||
| 570 | |||
| 571 | ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, ptr, size); | ||
| 572 | |||
| 573 | out: | ||
| 574 | dev_kfree_skb(skb); | ||
| 575 | if (ret) | ||
| 576 | wl1251_warning("cmd buld null data failed: %d", ret); | ||
| 577 | |||
| 578 | return ret; | ||
| 579 | } | ||
| 580 | |||
| 553 | static int wl1251_build_qos_null_data(struct wl1251 *wl) | 581 | static int wl1251_build_qos_null_data(struct wl1251 *wl) |
| 554 | { | 582 | { |
| 555 | struct ieee80211_qos_hdr template; | 583 | struct ieee80211_qos_hdr template; |
| @@ -687,16 +715,6 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | |||
| 687 | wl->power_level = conf->power_level; | 715 | wl->power_level = conf->power_level; |
| 688 | } | 716 | } |
| 689 | 717 | ||
| 690 | /* | ||
| 691 | * Tell stack that connection is lost because hw encryption isn't | ||
| 692 | * supported in monitor mode. | ||
| 693 | * This requires temporary enabling of the hw connection monitor flag | ||
| 694 | */ | ||
| 695 | if ((changed & IEEE80211_CONF_CHANGE_MONITOR) && wl->vif) { | ||
| 696 | wl->hw->flags |= IEEE80211_HW_CONNECTION_MONITOR; | ||
| 697 | ieee80211_connection_loss(wl->vif); | ||
| 698 | } | ||
| 699 | |||
| 700 | out_sleep: | 718 | out_sleep: |
| 701 | wl1251_ps_elp_sleep(wl); | 719 | wl1251_ps_elp_sleep(wl); |
| 702 | 720 | ||
| @@ -1103,24 +1121,19 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1103 | wl->rssi_thold = bss_conf->cqm_rssi_thold; | 1121 | wl->rssi_thold = bss_conf->cqm_rssi_thold; |
| 1104 | } | 1122 | } |
| 1105 | 1123 | ||
| 1106 | if (changed & BSS_CHANGED_BSSID) { | 1124 | if ((changed & BSS_CHANGED_BSSID) && |
| 1125 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | ||
| 1107 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | 1126 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); |
| 1108 | 1127 | ||
| 1109 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); | 1128 | if (!is_zero_ether_addr(wl->bssid)) { |
| 1110 | if (!skb) | 1129 | ret = wl1251_build_null_data(wl); |
| 1111 | goto out_sleep; | 1130 | if (ret < 0) |
| 1112 | 1131 | goto out_sleep; | |
| 1113 | ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, | ||
| 1114 | skb->data, skb->len); | ||
| 1115 | dev_kfree_skb(skb); | ||
| 1116 | if (ret < 0) | ||
| 1117 | goto out_sleep; | ||
| 1118 | 1132 | ||
| 1119 | ret = wl1251_build_qos_null_data(wl); | 1133 | ret = wl1251_build_qos_null_data(wl); |
| 1120 | if (ret < 0) | 1134 | if (ret < 0) |
| 1121 | goto out; | 1135 | goto out_sleep; |
| 1122 | 1136 | ||
| 1123 | if (wl->bss_type != BSS_TYPE_IBSS) { | ||
| 1124 | ret = wl1251_join(wl, wl->bss_type, wl->channel, | 1137 | ret = wl1251_join(wl, wl->bss_type, wl->channel, |
| 1125 | wl->beacon_int, wl->dtim_period); | 1138 | wl->beacon_int, wl->dtim_period); |
| 1126 | if (ret < 0) | 1139 | if (ret < 0) |
| @@ -1129,9 +1142,6 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1129 | } | 1142 | } |
| 1130 | 1143 | ||
| 1131 | if (changed & BSS_CHANGED_ASSOC) { | 1144 | if (changed & BSS_CHANGED_ASSOC) { |
| 1132 | /* Disable temporary enabled hw connection monitor flag */ | ||
| 1133 | wl->hw->flags &= ~IEEE80211_HW_CONNECTION_MONITOR; | ||
| 1134 | |||
| 1135 | if (bss_conf->assoc) { | 1145 | if (bss_conf->assoc) { |
| 1136 | wl->beacon_int = bss_conf->beacon_int; | 1146 | wl->beacon_int = bss_conf->beacon_int; |
| 1137 | 1147 | ||
| @@ -1216,8 +1226,8 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1216 | if (ret < 0) | 1226 | if (ret < 0) |
| 1217 | goto out_sleep; | 1227 | goto out_sleep; |
| 1218 | 1228 | ||
| 1219 | ret = wl1251_join(wl, wl->bss_type, wl->beacon_int, | 1229 | ret = wl1251_join(wl, wl->bss_type, wl->channel, |
| 1220 | wl->channel, wl->dtim_period); | 1230 | wl->beacon_int, wl->dtim_period); |
| 1221 | 1231 | ||
| 1222 | if (ret < 0) | 1232 | if (ret < 0) |
| 1223 | goto out_sleep; | 1233 | goto out_sleep; |
diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c index b06d36d99362..a0aa8fa72392 100644 --- a/drivers/net/wireless/ti/wl1251/spi.c +++ b/drivers/net/wireless/ti/wl1251/spi.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/swab.h> | ||
| 26 | #include <linux/crc7.h> | 27 | #include <linux/crc7.h> |
| 27 | #include <linux/spi/spi.h> | 28 | #include <linux/spi/spi.h> |
| 28 | #include <linux/wl12xx.h> | 29 | #include <linux/wl12xx.h> |
| @@ -83,47 +84,44 @@ static void wl1251_spi_reset(struct wl1251 *wl) | |||
| 83 | 84 | ||
| 84 | static void wl1251_spi_wake(struct wl1251 *wl) | 85 | static void wl1251_spi_wake(struct wl1251 *wl) |
| 85 | { | 86 | { |
| 86 | u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; | ||
| 87 | struct spi_transfer t; | 87 | struct spi_transfer t; |
| 88 | struct spi_message m; | 88 | struct spi_message m; |
| 89 | u8 *cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); | ||
| 89 | 90 | ||
| 90 | cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); | ||
| 91 | if (!cmd) { | 91 | if (!cmd) { |
| 92 | wl1251_error("could not allocate cmd for spi init"); | 92 | wl1251_error("could not allocate cmd for spi init"); |
| 93 | return; | 93 | return; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | memset(crc, 0, sizeof(crc)); | ||
| 97 | memset(&t, 0, sizeof(t)); | 96 | memset(&t, 0, sizeof(t)); |
| 98 | spi_message_init(&m); | 97 | spi_message_init(&m); |
| 99 | 98 | ||
| 100 | /* Set WSPI_INIT_COMMAND | 99 | /* Set WSPI_INIT_COMMAND |
| 101 | * the data is being send from the MSB to LSB | 100 | * the data is being send from the MSB to LSB |
| 102 | */ | 101 | */ |
| 103 | cmd[2] = 0xff; | 102 | cmd[0] = 0xff; |
| 104 | cmd[3] = 0xff; | 103 | cmd[1] = 0xff; |
| 105 | cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; | 104 | cmd[2] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; |
| 106 | cmd[0] = 0; | 105 | cmd[3] = 0; |
| 107 | cmd[7] = 0; | 106 | cmd[4] = 0; |
| 108 | cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3; | 107 | cmd[5] = HW_ACCESS_WSPI_INIT_CMD_MASK << 3; |
| 109 | cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; | 108 | cmd[5] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; |
| 109 | |||
| 110 | cmd[6] = WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS | ||
| 111 | | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; | ||
| 110 | 112 | ||
| 111 | if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) | 113 | if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) |
| 112 | cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; | 114 | cmd[6] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; |
| 113 | else | 115 | else |
| 114 | cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY; | 116 | cmd[6] |= WSPI_INIT_CMD_EN_FIXEDBUSY; |
| 115 | |||
| 116 | cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS | ||
| 117 | | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; | ||
| 118 | |||
| 119 | crc[0] = cmd[1]; | ||
| 120 | crc[1] = cmd[0]; | ||
| 121 | crc[2] = cmd[7]; | ||
| 122 | crc[3] = cmd[6]; | ||
| 123 | crc[4] = cmd[5]; | ||
| 124 | 117 | ||
| 125 | cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1; | 118 | cmd[7] = crc7_be(0, cmd+2, WSPI_INIT_CMD_CRC_LEN) | WSPI_INIT_CMD_END; |
| 126 | cmd[4] |= WSPI_INIT_CMD_END; | 119 | /* |
| 120 | * The above is the logical order; it must actually be stored | ||
| 121 | * in the buffer byte-swapped. | ||
| 122 | */ | ||
| 123 | __swab32s((u32 *)cmd); | ||
| 124 | __swab32s((u32 *)cmd+1); | ||
| 127 | 125 | ||
| 128 | t.tx_buf = cmd; | 126 | t.tx_buf = cmd; |
| 129 | t.len = WSPI_INIT_CMD_LEN; | 127 | t.len = WSPI_INIT_CMD_LEN; |
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h index f7381dd69009..0f2cfb0d2a9e 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.h +++ b/drivers/net/wireless/ti/wlcore/debugfs.h | |||
| @@ -57,7 +57,7 @@ static const struct file_operations name## _ops = { \ | |||
| 57 | wl, &name## _ops); \ | 57 | wl, &name## _ops); \ |
| 58 | if (!entry || IS_ERR(entry)) \ | 58 | if (!entry || IS_ERR(entry)) \ |
| 59 | goto err; \ | 59 | goto err; \ |
| 60 | } while (0); | 60 | } while (0) |
| 61 | 61 | ||
| 62 | 62 | ||
| 63 | #define DEBUGFS_ADD_PREFIX(prefix, name, parent) \ | 63 | #define DEBUGFS_ADD_PREFIX(prefix, name, parent) \ |
| @@ -66,7 +66,7 @@ static const struct file_operations name## _ops = { \ | |||
| 66 | wl, &prefix## _## name## _ops); \ | 66 | wl, &prefix## _## name## _ops); \ |
| 67 | if (!entry || IS_ERR(entry)) \ | 67 | if (!entry || IS_ERR(entry)) \ |
| 68 | goto err; \ | 68 | goto err; \ |
| 69 | } while (0); | 69 | } while (0) |
| 70 | 70 | ||
| 71 | #define DEBUGFS_FWSTATS_FILE(sub, name, fmt, struct_type) \ | 71 | #define DEBUGFS_FWSTATS_FILE(sub, name, fmt, struct_type) \ |
| 72 | static ssize_t sub## _ ##name## _read(struct file *file, \ | 72 | static ssize_t sub## _ ##name## _read(struct file *file, \ |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 077eb5b9cd74..02c91d6db753 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
| @@ -1416,7 +1416,7 @@ void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter) | |||
| 1416 | 1416 | ||
| 1417 | int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, | 1417 | int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, |
| 1418 | u16 offset, u8 flags, | 1418 | u16 offset, u8 flags, |
| 1419 | u8 *pattern, u8 len) | 1419 | const u8 *pattern, u8 len) |
| 1420 | { | 1420 | { |
| 1421 | struct wl12xx_rx_filter_field *field; | 1421 | struct wl12xx_rx_filter_field *field; |
| 1422 | 1422 | ||
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 5f3a389dd74c..392c882b28f0 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c | |||
| @@ -24,11 +24,12 @@ | |||
| 24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
| 25 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/slab.h> | ||
| 28 | #include <linux/swab.h> | ||
| 27 | #include <linux/crc7.h> | 29 | #include <linux/crc7.h> |
| 28 | #include <linux/spi/spi.h> | 30 | #include <linux/spi/spi.h> |
| 29 | #include <linux/wl12xx.h> | 31 | #include <linux/wl12xx.h> |
| 30 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
| 31 | #include <linux/slab.h> | ||
| 32 | 33 | ||
| 33 | #include "wlcore.h" | 34 | #include "wlcore.h" |
| 34 | #include "wl12xx_80211.h" | 35 | #include "wl12xx_80211.h" |
| @@ -110,18 +111,16 @@ static void wl12xx_spi_reset(struct device *child) | |||
| 110 | static void wl12xx_spi_init(struct device *child) | 111 | static void wl12xx_spi_init(struct device *child) |
| 111 | { | 112 | { |
| 112 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); | 113 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); |
| 113 | u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; | ||
| 114 | struct spi_transfer t; | 114 | struct spi_transfer t; |
| 115 | struct spi_message m; | 115 | struct spi_message m; |
| 116 | u8 *cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); | ||
| 116 | 117 | ||
| 117 | cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); | ||
| 118 | if (!cmd) { | 118 | if (!cmd) { |
| 119 | dev_err(child->parent, | 119 | dev_err(child->parent, |
| 120 | "could not allocate cmd for spi init\n"); | 120 | "could not allocate cmd for spi init\n"); |
| 121 | return; | 121 | return; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | memset(crc, 0, sizeof(crc)); | ||
| 125 | memset(&t, 0, sizeof(t)); | 124 | memset(&t, 0, sizeof(t)); |
| 126 | spi_message_init(&m); | 125 | spi_message_init(&m); |
| 127 | 126 | ||
| @@ -129,30 +128,29 @@ static void wl12xx_spi_init(struct device *child) | |||
| 129 | * Set WSPI_INIT_COMMAND | 128 | * Set WSPI_INIT_COMMAND |
| 130 | * the data is being send from the MSB to LSB | 129 | * the data is being send from the MSB to LSB |
| 131 | */ | 130 | */ |
| 132 | cmd[2] = 0xff; | 131 | cmd[0] = 0xff; |
| 133 | cmd[3] = 0xff; | 132 | cmd[1] = 0xff; |
| 134 | cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; | 133 | cmd[2] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; |
| 135 | cmd[0] = 0; | 134 | cmd[3] = 0; |
| 136 | cmd[7] = 0; | 135 | cmd[4] = 0; |
| 137 | cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3; | 136 | cmd[5] = HW_ACCESS_WSPI_INIT_CMD_MASK << 3; |
| 138 | cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; | 137 | cmd[5] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; |
| 138 | |||
| 139 | cmd[6] = WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS | ||
| 140 | | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; | ||
| 139 | 141 | ||
| 140 | if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) | 142 | if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) |
| 141 | cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; | 143 | cmd[6] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; |
| 142 | else | 144 | else |
| 143 | cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY; | 145 | cmd[6] |= WSPI_INIT_CMD_EN_FIXEDBUSY; |
| 144 | 146 | ||
| 145 | cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS | 147 | cmd[7] = crc7_be(0, cmd+2, WSPI_INIT_CMD_CRC_LEN) | WSPI_INIT_CMD_END; |
| 146 | | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; | 148 | /* |
| 147 | 149 | * The above is the logical order; it must actually be stored | |
| 148 | crc[0] = cmd[1]; | 150 | * in the buffer byte-swapped. |
| 149 | crc[1] = cmd[0]; | 151 | */ |
| 150 | crc[2] = cmd[7]; | 152 | __swab32s((u32 *)cmd); |
| 151 | crc[3] = cmd[6]; | 153 | __swab32s((u32 *)cmd+1); |
| 152 | crc[4] = cmd[5]; | ||
| 153 | |||
| 154 | cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1; | ||
| 155 | cmd[4] |= WSPI_INIT_CMD_END; | ||
| 156 | 154 | ||
| 157 | t.tx_buf = cmd; | 155 | t.tx_buf = cmd; |
| 158 | t.len = WSPI_INIT_CMD_LEN; | 156 | t.len = WSPI_INIT_CMD_LEN; |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 756e890bc5ee..c2c34a84ff3d 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
| @@ -512,8 +512,8 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif); | |||
| 512 | void wl12xx_queue_recovery_work(struct wl1271 *wl); | 512 | void wl12xx_queue_recovery_work(struct wl1271 *wl); |
| 513 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); | 513 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); |
| 514 | int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, | 514 | int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, |
| 515 | u16 offset, u8 flags, | 515 | u16 offset, u8 flags, |
| 516 | u8 *pattern, u8 len); | 516 | const u8 *pattern, u8 len); |
| 517 | void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter); | 517 | void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter); |
| 518 | struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void); | 518 | struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void); |
| 519 | int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter); | 519 | int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter); |
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index 65d4ca19d132..26c66a126551 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig | |||
| @@ -71,5 +71,6 @@ config NFC_PORT100 | |||
| 71 | source "drivers/nfc/pn544/Kconfig" | 71 | source "drivers/nfc/pn544/Kconfig" |
| 72 | source "drivers/nfc/microread/Kconfig" | 72 | source "drivers/nfc/microread/Kconfig" |
| 73 | source "drivers/nfc/nfcmrvl/Kconfig" | 73 | source "drivers/nfc/nfcmrvl/Kconfig" |
| 74 | source "drivers/nfc/st21nfca/Kconfig" | ||
| 74 | 75 | ||
| 75 | endmenu | 76 | endmenu |
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index ae42a3fa60c9..23225b0287fd 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile | |||
| @@ -11,5 +11,6 @@ obj-$(CONFIG_NFC_SIM) += nfcsim.o | |||
| 11 | obj-$(CONFIG_NFC_PORT100) += port100.o | 11 | obj-$(CONFIG_NFC_PORT100) += port100.o |
| 12 | obj-$(CONFIG_NFC_MRVL) += nfcmrvl/ | 12 | obj-$(CONFIG_NFC_MRVL) += nfcmrvl/ |
| 13 | obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o | 13 | obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o |
| 14 | obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/ | ||
| 14 | 15 | ||
| 15 | ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG | 16 | ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG |
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index f2acd85be86e..440291ab7263 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
| 24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
| 25 | #include <linux/of_gpio.h> | ||
| 26 | #include <linux/of_irq.h> | ||
| 25 | #include <linux/miscdevice.h> | 27 | #include <linux/miscdevice.h> |
| 26 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
| 27 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
| @@ -857,6 +859,92 @@ exit_state_wait_secure_write_answer: | |||
| 857 | } | 859 | } |
| 858 | } | 860 | } |
| 859 | 861 | ||
| 862 | #ifdef CONFIG_OF | ||
| 863 | |||
| 864 | static int pn544_hci_i2c_of_request_resources(struct i2c_client *client) | ||
| 865 | { | ||
| 866 | struct pn544_i2c_phy *phy = i2c_get_clientdata(client); | ||
| 867 | struct device_node *pp; | ||
| 868 | int ret; | ||
| 869 | |||
| 870 | pp = client->dev.of_node; | ||
| 871 | if (!pp) { | ||
| 872 | ret = -ENODEV; | ||
| 873 | goto err_dt; | ||
| 874 | } | ||
| 875 | |||
| 876 | /* Obtention of EN GPIO from device tree */ | ||
| 877 | ret = of_get_named_gpio(pp, "enable-gpios", 0); | ||
| 878 | if (ret < 0) { | ||
| 879 | if (ret != -EPROBE_DEFER) | ||
| 880 | nfc_err(&client->dev, | ||
| 881 | "Failed to get EN gpio, error: %d\n", ret); | ||
| 882 | goto err_dt; | ||
| 883 | } | ||
| 884 | phy->gpio_en = ret; | ||
| 885 | |||
| 886 | /* Configuration of EN GPIO */ | ||
| 887 | ret = gpio_request(phy->gpio_en, "pn544_en"); | ||
| 888 | if (ret) { | ||
| 889 | nfc_err(&client->dev, "Fail EN pin\n"); | ||
| 890 | goto err_dt; | ||
| 891 | } | ||
| 892 | ret = gpio_direction_output(phy->gpio_en, 0); | ||
| 893 | if (ret) { | ||
| 894 | nfc_err(&client->dev, "Fail EN pin direction\n"); | ||
| 895 | goto err_gpio_en; | ||
| 896 | } | ||
| 897 | |||
| 898 | /* Obtention of FW GPIO from device tree */ | ||
| 899 | ret = of_get_named_gpio(pp, "firmware-gpios", 0); | ||
| 900 | if (ret < 0) { | ||
| 901 | if (ret != -EPROBE_DEFER) | ||
| 902 | nfc_err(&client->dev, | ||
| 903 | "Failed to get FW gpio, error: %d\n", ret); | ||
| 904 | goto err_gpio_en; | ||
| 905 | } | ||
| 906 | phy->gpio_fw = ret; | ||
| 907 | |||
| 908 | /* Configuration of FW GPIO */ | ||
| 909 | ret = gpio_request(phy->gpio_fw, "pn544_fw"); | ||
| 910 | if (ret) { | ||
| 911 | nfc_err(&client->dev, "Fail FW pin\n"); | ||
| 912 | goto err_gpio_en; | ||
| 913 | } | ||
| 914 | ret = gpio_direction_output(phy->gpio_fw, 0); | ||
| 915 | if (ret) { | ||
| 916 | nfc_err(&client->dev, "Fail FW pin direction\n"); | ||
| 917 | goto err_gpio_fw; | ||
| 918 | } | ||
| 919 | |||
| 920 | /* IRQ */ | ||
| 921 | ret = irq_of_parse_and_map(pp, 0); | ||
| 922 | if (ret < 0) { | ||
| 923 | nfc_err(&client->dev, | ||
| 924 | "Unable to get irq, error: %d\n", ret); | ||
| 925 | goto err_gpio_fw; | ||
| 926 | } | ||
| 927 | client->irq = ret; | ||
| 928 | |||
| 929 | return 0; | ||
| 930 | |||
| 931 | err_gpio_fw: | ||
| 932 | gpio_free(phy->gpio_fw); | ||
| 933 | err_gpio_en: | ||
| 934 | gpio_free(phy->gpio_en); | ||
| 935 | err_dt: | ||
| 936 | return ret; | ||
| 937 | } | ||
| 938 | |||
| 939 | #else | ||
| 940 | |||
| 941 | static int pn544_hci_i2c_of_request_resources(struct i2c_client *client) | ||
| 942 | { | ||
| 943 | return -ENODEV; | ||
| 944 | } | ||
| 945 | |||
| 946 | #endif | ||
| 947 | |||
| 860 | static int pn544_hci_i2c_probe(struct i2c_client *client, | 948 | static int pn544_hci_i2c_probe(struct i2c_client *client, |
| 861 | const struct i2c_device_id *id) | 949 | const struct i2c_device_id *id) |
| 862 | { | 950 | { |
| @@ -887,25 +975,36 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, | |||
| 887 | i2c_set_clientdata(client, phy); | 975 | i2c_set_clientdata(client, phy); |
| 888 | 976 | ||
| 889 | pdata = client->dev.platform_data; | 977 | pdata = client->dev.platform_data; |
| 890 | if (pdata == NULL) { | ||
| 891 | nfc_err(&client->dev, "No platform data\n"); | ||
| 892 | return -EINVAL; | ||
| 893 | } | ||
| 894 | 978 | ||
| 895 | if (pdata->request_resources == NULL) { | 979 | /* No platform data, using device tree. */ |
| 896 | nfc_err(&client->dev, "request_resources() missing\n"); | 980 | if (!pdata && client->dev.of_node) { |
| 897 | return -EINVAL; | 981 | r = pn544_hci_i2c_of_request_resources(client); |
| 898 | } | 982 | if (r) { |
| 983 | nfc_err(&client->dev, "No DT data\n"); | ||
| 984 | return r; | ||
| 985 | } | ||
| 986 | /* Using platform data. */ | ||
| 987 | } else if (pdata) { | ||
| 899 | 988 | ||
| 900 | r = pdata->request_resources(client); | 989 | if (pdata->request_resources == NULL) { |
| 901 | if (r) { | 990 | nfc_err(&client->dev, "request_resources() missing\n"); |
| 902 | nfc_err(&client->dev, "Cannot get platform resources\n"); | 991 | return -EINVAL; |
| 903 | return r; | 992 | } |
| 904 | } | ||
| 905 | 993 | ||
| 906 | phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); | 994 | r = pdata->request_resources(client); |
| 907 | phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); | 995 | if (r) { |
| 908 | phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); | 996 | nfc_err(&client->dev, |
| 997 | "Cannot get platform resources\n"); | ||
| 998 | return r; | ||
| 999 | } | ||
| 1000 | |||
| 1001 | phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); | ||
| 1002 | phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); | ||
| 1003 | phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); | ||
| 1004 | } else { | ||
| 1005 | nfc_err(&client->dev, "No platform data\n"); | ||
| 1006 | return -EINVAL; | ||
| 1007 | } | ||
| 909 | 1008 | ||
| 910 | pn544_hci_i2c_platform_init(phy); | 1009 | pn544_hci_i2c_platform_init(phy); |
| 911 | 1010 | ||
| @@ -930,8 +1029,12 @@ err_hci: | |||
| 930 | free_irq(client->irq, phy); | 1029 | free_irq(client->irq, phy); |
| 931 | 1030 | ||
| 932 | err_rti: | 1031 | err_rti: |
| 933 | if (pdata->free_resources != NULL) | 1032 | if (!pdata) { |
| 1033 | gpio_free(phy->gpio_en); | ||
| 1034 | gpio_free(phy->gpio_fw); | ||
| 1035 | } else if (pdata->free_resources) { | ||
| 934 | pdata->free_resources(); | 1036 | pdata->free_resources(); |
| 1037 | } | ||
| 935 | 1038 | ||
| 936 | return r; | 1039 | return r; |
| 937 | } | 1040 | } |
| @@ -953,15 +1056,30 @@ static int pn544_hci_i2c_remove(struct i2c_client *client) | |||
| 953 | pn544_hci_i2c_disable(phy); | 1056 | pn544_hci_i2c_disable(phy); |
| 954 | 1057 | ||
| 955 | free_irq(client->irq, phy); | 1058 | free_irq(client->irq, phy); |
| 956 | if (pdata->free_resources) | 1059 | |
| 1060 | /* No platform data, GPIOs have been requested by this driver */ | ||
| 1061 | if (!pdata) { | ||
| 1062 | gpio_free(phy->gpio_en); | ||
| 1063 | gpio_free(phy->gpio_fw); | ||
| 1064 | /* Using platform data */ | ||
| 1065 | } else if (pdata->free_resources) { | ||
| 957 | pdata->free_resources(); | 1066 | pdata->free_resources(); |
| 1067 | } | ||
| 958 | 1068 | ||
| 959 | return 0; | 1069 | return 0; |
| 960 | } | 1070 | } |
| 961 | 1071 | ||
| 1072 | static const struct of_device_id of_pn544_i2c_match[] = { | ||
| 1073 | { .compatible = "nxp,pn544-i2c", }, | ||
| 1074 | {}, | ||
| 1075 | }; | ||
| 1076 | MODULE_DEVICE_TABLE(of, of_pn544_i2c_match); | ||
| 1077 | |||
| 962 | static struct i2c_driver pn544_hci_i2c_driver = { | 1078 | static struct i2c_driver pn544_hci_i2c_driver = { |
| 963 | .driver = { | 1079 | .driver = { |
| 964 | .name = PN544_HCI_I2C_DRIVER_NAME, | 1080 | .name = PN544_HCI_I2C_DRIVER_NAME, |
| 1081 | .owner = THIS_MODULE, | ||
| 1082 | .of_match_table = of_match_ptr(of_pn544_i2c_match), | ||
| 965 | }, | 1083 | }, |
| 966 | .probe = pn544_hci_i2c_probe, | 1084 | .probe = pn544_hci_i2c_probe, |
| 967 | .id_table = pn544_hci_i2c_id_table, | 1085 | .id_table = pn544_hci_i2c_id_table, |
diff --git a/drivers/nfc/st21nfca/Kconfig b/drivers/nfc/st21nfca/Kconfig new file mode 100644 index 000000000000..ee459f066ade --- /dev/null +++ b/drivers/nfc/st21nfca/Kconfig | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | config NFC_ST21NFCA | ||
| 2 | tristate "STMicroelectronics ST21NFCA NFC driver" | ||
| 3 | depends on NFC_HCI | ||
| 4 | select CRC_CCITT | ||
| 5 | default n | ||
| 6 | ---help--- | ||
| 7 | STMicroelectronics ST21NFCA core driver. It implements the chipset | ||
| 8 | HCI logic and hooks into the NFC kernel APIs. Physical layers will | ||
| 9 | register against it. | ||
| 10 | |||
| 11 | To compile this driver as a module, choose m here. The module will | ||
| 12 | be called st21nfca. | ||
| 13 | Say N if unsure. | ||
| 14 | |||
| 15 | config NFC_ST21NFCA_I2C | ||
| 16 | tristate "NFC ST21NFCA i2c support" | ||
| 17 | depends on NFC_ST21NFCA && I2C && NFC_SHDLC | ||
| 18 | ---help--- | ||
| 19 | This module adds support for the STMicroelectronics st21nfca i2c interface. | ||
| 20 | Select this if your platform is using the i2c bus. | ||
| 21 | |||
| 22 | If you choose to build a module, it'll be called st21nfca_i2c. | ||
| 23 | Say N if unsure. | ||
diff --git a/drivers/nfc/st21nfca/Makefile b/drivers/nfc/st21nfca/Makefile new file mode 100644 index 000000000000..038ed093a119 --- /dev/null +++ b/drivers/nfc/st21nfca/Makefile | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | # | ||
| 2 | # Makefile for ST21NFCA HCI based NFC driver | ||
| 3 | # | ||
| 4 | |||
| 5 | st21nfca_i2c-objs = i2c.o | ||
| 6 | |||
| 7 | obj-$(CONFIG_NFC_ST21NFCA) += st21nfca.o | ||
| 8 | obj-$(CONFIG_NFC_ST21NFCA_I2C) += st21nfca_i2c.o | ||
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c new file mode 100644 index 000000000000..3f954ed86d98 --- /dev/null +++ b/drivers/nfc/st21nfca/i2c.c | |||
| @@ -0,0 +1,724 @@ | |||
| 1 | /* | ||
| 2 | * I2C Link Layer for ST21NFCA HCI based Driver | ||
| 3 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 19 | |||
| 20 | #include <linux/crc-ccitt.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/i2c.h> | ||
| 23 | #include <linux/gpio.h> | ||
| 24 | #include <linux/of_irq.h> | ||
| 25 | #include <linux/of_gpio.h> | ||
| 26 | #include <linux/miscdevice.h> | ||
| 27 | #include <linux/interrupt.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | #include <linux/nfc.h> | ||
| 30 | #include <linux/firmware.h> | ||
| 31 | #include <linux/unaligned/access_ok.h> | ||
| 32 | #include <linux/platform_data/st21nfca.h> | ||
| 33 | |||
| 34 | #include <net/nfc/hci.h> | ||
| 35 | #include <net/nfc/llc.h> | ||
| 36 | #include <net/nfc/nfc.h> | ||
| 37 | |||
| 38 | #include "st21nfca.h" | ||
| 39 | |||
| 40 | /* | ||
| 41 | * Every frame starts with ST21NFCA_SOF_EOF and ends with ST21NFCA_SOF_EOF. | ||
| 42 | * Because ST21NFCA_SOF_EOF is a possible data value, there is a mecanism | ||
| 43 | * called byte stuffing has been introduced. | ||
| 44 | * | ||
| 45 | * if byte == ST21NFCA_SOF_EOF or ST21NFCA_ESCAPE_BYTE_STUFFING | ||
| 46 | * - insert ST21NFCA_ESCAPE_BYTE_STUFFING (escape byte) | ||
| 47 | * - xor byte with ST21NFCA_BYTE_STUFFING_MASK | ||
| 48 | */ | ||
| 49 | #define ST21NFCA_SOF_EOF 0x7e | ||
| 50 | #define ST21NFCA_BYTE_STUFFING_MASK 0x20 | ||
| 51 | #define ST21NFCA_ESCAPE_BYTE_STUFFING 0x7d | ||
| 52 | |||
| 53 | /* SOF + 00 */ | ||
| 54 | #define ST21NFCA_FRAME_HEADROOM 2 | ||
| 55 | |||
| 56 | /* 2 bytes crc + EOF */ | ||
| 57 | #define ST21NFCA_FRAME_TAILROOM 3 | ||
| 58 | #define IS_START_OF_FRAME(buf) (buf[0] == ST21NFCA_SOF_EOF && \ | ||
| 59 | buf[1] == 0) | ||
| 60 | |||
| 61 | #define ST21NFCA_HCI_I2C_DRIVER_NAME "st21nfca_hci_i2c" | ||
| 62 | |||
| 63 | static struct i2c_device_id st21nfca_hci_i2c_id_table[] = { | ||
| 64 | {ST21NFCA_HCI_DRIVER_NAME, 0}, | ||
| 65 | {} | ||
| 66 | }; | ||
| 67 | |||
| 68 | MODULE_DEVICE_TABLE(i2c, st21nfca_hci_i2c_id_table); | ||
| 69 | |||
| 70 | struct st21nfca_i2c_phy { | ||
| 71 | struct i2c_client *i2c_dev; | ||
| 72 | struct nfc_hci_dev *hdev; | ||
| 73 | |||
| 74 | unsigned int gpio_ena; | ||
| 75 | unsigned int gpio_irq; | ||
| 76 | unsigned int irq_polarity; | ||
| 77 | |||
| 78 | struct sk_buff *pending_skb; | ||
| 79 | int current_read_len; | ||
| 80 | /* | ||
| 81 | * crc might have fail because i2c macro | ||
| 82 | * is disable due to other interface activity | ||
| 83 | */ | ||
| 84 | int crc_trials; | ||
| 85 | |||
| 86 | int powered; | ||
| 87 | int run_mode; | ||
| 88 | |||
| 89 | /* | ||
| 90 | * < 0 if hardware error occured (e.g. i2c err) | ||
| 91 | * and prevents normal operation. | ||
| 92 | */ | ||
| 93 | int hard_fault; | ||
| 94 | struct mutex phy_lock; | ||
| 95 | }; | ||
| 96 | static u8 len_seq[] = { 13, 24, 15, 29 }; | ||
| 97 | static u16 wait_tab[] = { 2, 3, 5, 15, 20, 40}; | ||
| 98 | |||
| 99 | #define I2C_DUMP_SKB(info, skb) \ | ||
| 100 | do { \ | ||
| 101 | pr_debug("%s:\n", info); \ | ||
| 102 | print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET, \ | ||
| 103 | 16, 1, (skb)->data, (skb)->len, 0); \ | ||
| 104 | } while (0) | ||
| 105 | |||
| 106 | /* | ||
| 107 | * In order to get the CLF in a known state we generate an internal reboot | ||
| 108 | * using a proprietary command. | ||
| 109 | * Once the reboot is completed, we expect to receive a ST21NFCA_SOF_EOF | ||
| 110 | * fill buffer. | ||
| 111 | */ | ||
| 112 | static int st21nfca_hci_platform_init(struct st21nfca_i2c_phy *phy) | ||
| 113 | { | ||
| 114 | u16 wait_reboot[] = { 50, 300, 1000 }; | ||
| 115 | char reboot_cmd[] = { 0x7E, 0x66, 0x48, 0xF6, 0x7E }; | ||
| 116 | u8 tmp[ST21NFCA_HCI_LLC_MAX_SIZE]; | ||
| 117 | int i, r = -1; | ||
| 118 | |||
| 119 | for (i = 0; i < ARRAY_SIZE(wait_reboot) && r < 0; i++) { | ||
| 120 | r = i2c_master_send(phy->i2c_dev, reboot_cmd, | ||
| 121 | sizeof(reboot_cmd)); | ||
| 122 | if (r < 0) | ||
| 123 | msleep(wait_reboot[i]); | ||
| 124 | } | ||
| 125 | if (r < 0) | ||
| 126 | return r; | ||
| 127 | |||
| 128 | /* CLF is spending about 20ms to do an internal reboot */ | ||
| 129 | msleep(20); | ||
| 130 | r = -1; | ||
| 131 | for (i = 0; i < ARRAY_SIZE(wait_reboot) && r < 0; i++) { | ||
| 132 | r = i2c_master_recv(phy->i2c_dev, tmp, | ||
| 133 | ST21NFCA_HCI_LLC_MAX_SIZE); | ||
| 134 | if (r < 0) | ||
| 135 | msleep(wait_reboot[i]); | ||
| 136 | } | ||
| 137 | if (r < 0) | ||
| 138 | return r; | ||
| 139 | |||
| 140 | for (i = 0; i < ST21NFCA_HCI_LLC_MAX_SIZE && | ||
| 141 | tmp[i] == ST21NFCA_SOF_EOF; i++) | ||
| 142 | ; | ||
| 143 | |||
| 144 | if (r != ST21NFCA_HCI_LLC_MAX_SIZE) | ||
| 145 | return -ENODEV; | ||
| 146 | |||
| 147 | usleep_range(1000, 1500); | ||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | |||
| 151 | static int st21nfca_hci_i2c_enable(void *phy_id) | ||
| 152 | { | ||
| 153 | struct st21nfca_i2c_phy *phy = phy_id; | ||
| 154 | |||
| 155 | gpio_set_value(phy->gpio_ena, 1); | ||
| 156 | phy->powered = 1; | ||
| 157 | phy->run_mode = ST21NFCA_HCI_MODE; | ||
| 158 | |||
| 159 | usleep_range(10000, 15000); | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static void st21nfca_hci_i2c_disable(void *phy_id) | ||
| 165 | { | ||
| 166 | struct st21nfca_i2c_phy *phy = phy_id; | ||
| 167 | |||
| 168 | pr_info("\n"); | ||
| 169 | gpio_set_value(phy->gpio_ena, 0); | ||
| 170 | |||
| 171 | phy->powered = 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | static void st21nfca_hci_add_len_crc(struct sk_buff *skb) | ||
| 175 | { | ||
| 176 | u16 crc; | ||
| 177 | u8 tmp; | ||
| 178 | |||
| 179 | *skb_push(skb, 1) = 0; | ||
| 180 | |||
| 181 | crc = crc_ccitt(0xffff, skb->data, skb->len); | ||
| 182 | crc = ~crc; | ||
| 183 | |||
| 184 | tmp = crc & 0x00ff; | ||
| 185 | *skb_put(skb, 1) = tmp; | ||
| 186 | |||
| 187 | tmp = (crc >> 8) & 0x00ff; | ||
| 188 | *skb_put(skb, 1) = tmp; | ||
| 189 | } | ||
| 190 | |||
| 191 | static void st21nfca_hci_remove_len_crc(struct sk_buff *skb) | ||
| 192 | { | ||
| 193 | skb_pull(skb, ST21NFCA_FRAME_HEADROOM); | ||
| 194 | skb_trim(skb, skb->len - ST21NFCA_FRAME_TAILROOM); | ||
| 195 | } | ||
| 196 | |||
| 197 | /* | ||
| 198 | * Writing a frame must not return the number of written bytes. | ||
| 199 | * It must return either zero for success, or <0 for error. | ||
| 200 | * In addition, it must not alter the skb | ||
| 201 | */ | ||
| 202 | static int st21nfca_hci_i2c_write(void *phy_id, struct sk_buff *skb) | ||
| 203 | { | ||
| 204 | int r = -1, i, j; | ||
| 205 | struct st21nfca_i2c_phy *phy = phy_id; | ||
| 206 | struct i2c_client *client = phy->i2c_dev; | ||
| 207 | u8 tmp[ST21NFCA_HCI_LLC_MAX_SIZE * 2]; | ||
| 208 | |||
| 209 | I2C_DUMP_SKB("st21nfca_hci_i2c_write", skb); | ||
| 210 | |||
| 211 | |||
| 212 | if (phy->hard_fault != 0) | ||
| 213 | return phy->hard_fault; | ||
| 214 | |||
| 215 | /* | ||
| 216 | * Compute CRC before byte stuffing computation on frame | ||
| 217 | * Note st21nfca_hci_add_len_crc is doing a byte stuffing | ||
| 218 | * on its own value | ||
| 219 | */ | ||
| 220 | st21nfca_hci_add_len_crc(skb); | ||
| 221 | |||
| 222 | /* add ST21NFCA_SOF_EOF on tail */ | ||
| 223 | *skb_put(skb, 1) = ST21NFCA_SOF_EOF; | ||
| 224 | /* add ST21NFCA_SOF_EOF on head */ | ||
| 225 | *skb_push(skb, 1) = ST21NFCA_SOF_EOF; | ||
| 226 | |||
| 227 | /* | ||
| 228 | * Compute byte stuffing | ||
| 229 | * if byte == ST21NFCA_SOF_EOF or ST21NFCA_ESCAPE_BYTE_STUFFING | ||
| 230 | * insert ST21NFCA_ESCAPE_BYTE_STUFFING (escape byte) | ||
| 231 | * xor byte with ST21NFCA_BYTE_STUFFING_MASK | ||
| 232 | */ | ||
| 233 | tmp[0] = skb->data[0]; | ||
| 234 | for (i = 1, j = 1; i < skb->len - 1; i++, j++) { | ||
| 235 | if (skb->data[i] == ST21NFCA_SOF_EOF | ||
| 236 | || skb->data[i] == ST21NFCA_ESCAPE_BYTE_STUFFING) { | ||
| 237 | tmp[j] = ST21NFCA_ESCAPE_BYTE_STUFFING; | ||
| 238 | j++; | ||
| 239 | tmp[j] = skb->data[i] ^ ST21NFCA_BYTE_STUFFING_MASK; | ||
| 240 | } else { | ||
| 241 | tmp[j] = skb->data[i]; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | tmp[j] = skb->data[i]; | ||
| 245 | j++; | ||
| 246 | |||
| 247 | /* | ||
| 248 | * Manage sleep mode | ||
| 249 | * Try 3 times to send data with delay between each | ||
| 250 | */ | ||
| 251 | mutex_lock(&phy->phy_lock); | ||
| 252 | for (i = 0; i < ARRAY_SIZE(wait_tab) && r < 0; i++) { | ||
| 253 | r = i2c_master_send(client, tmp, j); | ||
| 254 | if (r < 0) | ||
| 255 | msleep(wait_tab[i]); | ||
| 256 | } | ||
| 257 | mutex_unlock(&phy->phy_lock); | ||
| 258 | |||
| 259 | if (r >= 0) { | ||
| 260 | if (r != j) | ||
| 261 | r = -EREMOTEIO; | ||
| 262 | else | ||
| 263 | r = 0; | ||
| 264 | } | ||
| 265 | |||
| 266 | st21nfca_hci_remove_len_crc(skb); | ||
| 267 | |||
| 268 | return r; | ||
| 269 | } | ||
| 270 | |||
| 271 | static int get_frame_size(u8 *buf, int buflen) | ||
| 272 | { | ||
| 273 | int len = 0; | ||
| 274 | if (buf[len + 1] == ST21NFCA_SOF_EOF) | ||
| 275 | return 0; | ||
| 276 | |||
| 277 | for (len = 1; len < buflen && buf[len] != ST21NFCA_SOF_EOF; len++) | ||
| 278 | ; | ||
| 279 | |||
| 280 | return len; | ||
| 281 | } | ||
| 282 | |||
| 283 | static int check_crc(u8 *buf, int buflen) | ||
| 284 | { | ||
| 285 | u16 crc; | ||
| 286 | |||
| 287 | crc = crc_ccitt(0xffff, buf, buflen - 2); | ||
| 288 | crc = ~crc; | ||
| 289 | |||
| 290 | if (buf[buflen - 2] != (crc & 0xff) || buf[buflen - 1] != (crc >> 8)) { | ||
| 291 | pr_err(ST21NFCA_HCI_DRIVER_NAME | ||
| 292 | ": CRC error 0x%x != 0x%x 0x%x\n", crc, buf[buflen - 1], | ||
| 293 | buf[buflen - 2]); | ||
| 294 | |||
| 295 | pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__); | ||
| 296 | print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, | ||
| 297 | 16, 2, buf, buflen, false); | ||
| 298 | return -EPERM; | ||
| 299 | } | ||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | /* | ||
| 304 | * Prepare received data for upper layer. | ||
| 305 | * Received data include byte stuffing, crc and sof/eof | ||
| 306 | * which is not usable by hci part. | ||
| 307 | * returns: | ||
| 308 | * frame size without sof/eof, header and byte stuffing | ||
| 309 | * -EBADMSG : frame was incorrect and discarded | ||
| 310 | */ | ||
| 311 | static int st21nfca_hci_i2c_repack(struct sk_buff *skb) | ||
| 312 | { | ||
| 313 | int i, j, r, size; | ||
| 314 | if (skb->len < 1 || (skb->len > 1 && skb->data[1] != 0)) | ||
| 315 | return -EBADMSG; | ||
| 316 | |||
| 317 | size = get_frame_size(skb->data, skb->len); | ||
| 318 | if (size > 0) { | ||
| 319 | skb_trim(skb, size); | ||
| 320 | /* remove ST21NFCA byte stuffing for upper layer */ | ||
| 321 | for (i = 1, j = 0; i < skb->len; i++) { | ||
| 322 | if (skb->data[i + j] == | ||
| 323 | (u8) ST21NFCA_ESCAPE_BYTE_STUFFING) { | ||
| 324 | skb->data[i] = skb->data[i + j + 1] | ||
| 325 | | ST21NFCA_BYTE_STUFFING_MASK; | ||
| 326 | i++; | ||
| 327 | j++; | ||
| 328 | } | ||
| 329 | skb->data[i] = skb->data[i + j]; | ||
| 330 | } | ||
| 331 | /* remove byte stuffing useless byte */ | ||
| 332 | skb_trim(skb, i - j); | ||
| 333 | /* remove ST21NFCA_SOF_EOF from head */ | ||
| 334 | skb_pull(skb, 1); | ||
| 335 | |||
| 336 | r = check_crc(skb->data, skb->len); | ||
| 337 | if (r != 0) { | ||
| 338 | i = 0; | ||
| 339 | return -EBADMSG; | ||
| 340 | } | ||
| 341 | |||
| 342 | /* remove headbyte */ | ||
| 343 | skb_pull(skb, 1); | ||
| 344 | /* remove crc. Byte Stuffing is already removed here */ | ||
| 345 | skb_trim(skb, skb->len - 2); | ||
| 346 | return skb->len; | ||
| 347 | } | ||
| 348 | return 0; | ||
| 349 | } | ||
| 350 | |||
| 351 | /* | ||
| 352 | * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees | ||
| 353 | * that i2c bus will be flushed and that next read will start on a new frame. | ||
| 354 | * returned skb contains only LLC header and payload. | ||
| 355 | * returns: | ||
| 356 | * frame size : if received frame is complete (find ST21NFCA_SOF_EOF at | ||
| 357 | * end of read) | ||
| 358 | * -EAGAIN : if received frame is incomplete (not find ST21NFCA_SOF_EOF | ||
| 359 | * at end of read) | ||
| 360 | * -EREMOTEIO : i2c read error (fatal) | ||
| 361 | * -EBADMSG : frame was incorrect and discarded | ||
| 362 | * (value returned from st21nfca_hci_i2c_repack) | ||
| 363 | * -EIO : if no ST21NFCA_SOF_EOF is found after reaching | ||
| 364 | * the read length end sequence | ||
| 365 | */ | ||
| 366 | static int st21nfca_hci_i2c_read(struct st21nfca_i2c_phy *phy, | ||
| 367 | struct sk_buff *skb) | ||
| 368 | { | ||
| 369 | int r, i; | ||
| 370 | u8 len; | ||
| 371 | u8 buf[ST21NFCA_HCI_LLC_MAX_PAYLOAD]; | ||
| 372 | struct i2c_client *client = phy->i2c_dev; | ||
| 373 | |||
| 374 | if (phy->current_read_len < ARRAY_SIZE(len_seq)) { | ||
| 375 | len = len_seq[phy->current_read_len]; | ||
| 376 | |||
| 377 | /* | ||
| 378 | * Add retry mecanism | ||
| 379 | * Operation on I2C interface may fail in case of operation on | ||
| 380 | * RF or SWP interface | ||
| 381 | */ | ||
| 382 | r = 0; | ||
| 383 | mutex_lock(&phy->phy_lock); | ||
| 384 | for (i = 0; i < ARRAY_SIZE(wait_tab) && r <= 0; i++) { | ||
| 385 | r = i2c_master_recv(client, buf, len); | ||
| 386 | if (r < 0) | ||
| 387 | msleep(wait_tab[i]); | ||
| 388 | } | ||
| 389 | mutex_unlock(&phy->phy_lock); | ||
| 390 | |||
| 391 | if (r != len) { | ||
| 392 | phy->current_read_len = 0; | ||
| 393 | return -EREMOTEIO; | ||
| 394 | } | ||
| 395 | |||
| 396 | /* | ||
| 397 | * The first read sequence does not start with SOF. | ||
| 398 | * Data is corrupeted so we drop it. | ||
| 399 | */ | ||
| 400 | if (!phy->current_read_len && buf[0] != ST21NFCA_SOF_EOF) { | ||
| 401 | skb_trim(skb, 0); | ||
| 402 | phy->current_read_len = 0; | ||
| 403 | return -EIO; | ||
| 404 | } else if (phy->current_read_len && | ||
| 405 | IS_START_OF_FRAME(buf)) { | ||
| 406 | /* | ||
| 407 | * Previous frame transmission was interrupted and | ||
| 408 | * the frame got repeated. | ||
| 409 | * Received frame start with ST21NFCA_SOF_EOF + 00. | ||
| 410 | */ | ||
| 411 | skb_trim(skb, 0); | ||
| 412 | phy->current_read_len = 0; | ||
| 413 | } | ||
| 414 | |||
| 415 | memcpy(skb_put(skb, len), buf, len); | ||
| 416 | |||
| 417 | if (skb->data[skb->len - 1] == ST21NFCA_SOF_EOF) { | ||
| 418 | phy->current_read_len = 0; | ||
| 419 | return st21nfca_hci_i2c_repack(skb); | ||
| 420 | } | ||
| 421 | phy->current_read_len++; | ||
| 422 | return -EAGAIN; | ||
| 423 | } | ||
| 424 | return -EIO; | ||
| 425 | } | ||
| 426 | |||
| 427 | /* | ||
| 428 | * Reads an shdlc frame from the chip. This is not as straightforward as it | ||
| 429 | * seems. The frame format is data-crc, and corruption can occur anywhere | ||
| 430 | * while transiting on i2c bus, such that we could read an invalid data. | ||
| 431 | * The tricky case is when we read a corrupted data or crc. We must detect | ||
| 432 | * this here in order to determine that data can be transmitted to the hci | ||
| 433 | * core. This is the reason why we check the crc here. | ||
| 434 | * The CLF will repeat a frame until we send a RR on that frame. | ||
| 435 | * | ||
| 436 | * On ST21NFCA, IRQ goes in idle when read starts. As no size information are | ||
| 437 | * available in the incoming data, other IRQ might come. Every IRQ will trigger | ||
| 438 | * a read sequence with different length and will fill the current frame. | ||
| 439 | * The reception is complete once we reach a ST21NFCA_SOF_EOF. | ||
| 440 | */ | ||
| 441 | static irqreturn_t st21nfca_hci_irq_thread_fn(int irq, void *phy_id) | ||
| 442 | { | ||
| 443 | struct st21nfca_i2c_phy *phy = phy_id; | ||
| 444 | struct i2c_client *client; | ||
| 445 | |||
| 446 | int r; | ||
| 447 | |||
| 448 | if (!phy || irq != phy->i2c_dev->irq) { | ||
| 449 | WARN_ON_ONCE(1); | ||
| 450 | return IRQ_NONE; | ||
| 451 | } | ||
| 452 | |||
| 453 | client = phy->i2c_dev; | ||
| 454 | dev_dbg(&client->dev, "IRQ\n"); | ||
| 455 | |||
| 456 | if (phy->hard_fault != 0) | ||
| 457 | return IRQ_HANDLED; | ||
| 458 | |||
| 459 | r = st21nfca_hci_i2c_read(phy, phy->pending_skb); | ||
| 460 | if (r == -EREMOTEIO) { | ||
| 461 | phy->hard_fault = r; | ||
| 462 | |||
| 463 | nfc_hci_recv_frame(phy->hdev, NULL); | ||
| 464 | |||
| 465 | return IRQ_HANDLED; | ||
| 466 | } else if (r == -EAGAIN || r == -EIO) { | ||
| 467 | return IRQ_HANDLED; | ||
| 468 | } else if (r == -EBADMSG && phy->crc_trials < ARRAY_SIZE(wait_tab)) { | ||
| 469 | /* | ||
| 470 | * With ST21NFCA, only one interface (I2C, RF or SWP) | ||
| 471 | * may be active at a time. | ||
| 472 | * Having incorrect crc is usually due to i2c macrocell | ||
| 473 | * deactivation in the middle of a transmission. | ||
| 474 | * It may generate corrupted data on i2c. | ||
| 475 | * We give sometime to get i2c back. | ||
| 476 | * The complete frame will be repeated. | ||
| 477 | */ | ||
| 478 | msleep(wait_tab[phy->crc_trials]); | ||
| 479 | phy->crc_trials++; | ||
| 480 | phy->current_read_len = 0; | ||
| 481 | kfree_skb(phy->pending_skb); | ||
| 482 | } else if (r > 0) { | ||
| 483 | /* | ||
| 484 | * We succeeded to read data from the CLF and | ||
| 485 | * data is valid. | ||
| 486 | * Reset counter. | ||
| 487 | */ | ||
| 488 | nfc_hci_recv_frame(phy->hdev, phy->pending_skb); | ||
| 489 | phy->crc_trials = 0; | ||
| 490 | } | ||
| 491 | |||
| 492 | phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL); | ||
| 493 | if (phy->pending_skb == NULL) { | ||
| 494 | phy->hard_fault = -ENOMEM; | ||
| 495 | nfc_hci_recv_frame(phy->hdev, NULL); | ||
| 496 | } | ||
| 497 | |||
| 498 | return IRQ_HANDLED; | ||
| 499 | } | ||
| 500 | |||
| 501 | static struct nfc_phy_ops i2c_phy_ops = { | ||
| 502 | .write = st21nfca_hci_i2c_write, | ||
| 503 | .enable = st21nfca_hci_i2c_enable, | ||
| 504 | .disable = st21nfca_hci_i2c_disable, | ||
| 505 | }; | ||
| 506 | |||
| 507 | #ifdef CONFIG_OF | ||
| 508 | static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client) | ||
| 509 | { | ||
| 510 | struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client); | ||
| 511 | struct device_node *pp; | ||
| 512 | int gpio; | ||
| 513 | int r; | ||
| 514 | |||
| 515 | pp = client->dev.of_node; | ||
| 516 | if (!pp) | ||
| 517 | return -ENODEV; | ||
| 518 | |||
| 519 | /* Get GPIO from device tree */ | ||
| 520 | gpio = of_get_named_gpio(pp, "enable-gpios", 0); | ||
| 521 | if (gpio < 0) { | ||
| 522 | nfc_err(&client->dev, "Failed to retrieve enable-gpios from device tree\n"); | ||
| 523 | return gpio; | ||
| 524 | } | ||
| 525 | |||
| 526 | /* GPIO request and configuration */ | ||
| 527 | r = devm_gpio_request(&client->dev, gpio, "clf_enable"); | ||
| 528 | if (r) { | ||
| 529 | nfc_err(&client->dev, "Failed to request enable pin\n"); | ||
| 530 | return -ENODEV; | ||
| 531 | } | ||
| 532 | |||
| 533 | r = gpio_direction_output(gpio, 1); | ||
| 534 | if (r) { | ||
| 535 | nfc_err(&client->dev, "Failed to set enable pin direction as output\n"); | ||
| 536 | return -ENODEV; | ||
| 537 | } | ||
| 538 | phy->gpio_ena = gpio; | ||
| 539 | |||
| 540 | /* IRQ */ | ||
| 541 | r = irq_of_parse_and_map(pp, 0); | ||
| 542 | if (r < 0) { | ||
| 543 | nfc_err(&client->dev, | ||
| 544 | "Unable to get irq, error: %d\n", r); | ||
| 545 | return r; | ||
| 546 | } | ||
| 547 | |||
| 548 | phy->irq_polarity = irq_get_trigger_type(r); | ||
| 549 | client->irq = r; | ||
| 550 | |||
| 551 | return 0; | ||
| 552 | } | ||
| 553 | #else | ||
| 554 | static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client) | ||
| 555 | { | ||
| 556 | return -ENODEV; | ||
| 557 | } | ||
| 558 | #endif | ||
| 559 | |||
| 560 | static int st21nfca_hci_i2c_request_resources(struct i2c_client *client) | ||
| 561 | { | ||
| 562 | struct st21nfca_nfc_platform_data *pdata; | ||
| 563 | struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client); | ||
| 564 | int r; | ||
| 565 | int irq; | ||
| 566 | |||
| 567 | pdata = client->dev.platform_data; | ||
| 568 | if (pdata == NULL) { | ||
| 569 | nfc_err(&client->dev, "No platform data\n"); | ||
| 570 | return -EINVAL; | ||
| 571 | } | ||
| 572 | |||
| 573 | /* store for later use */ | ||
| 574 | phy->gpio_irq = pdata->gpio_irq; | ||
| 575 | phy->gpio_ena = pdata->gpio_ena; | ||
| 576 | phy->irq_polarity = pdata->irq_polarity; | ||
| 577 | |||
| 578 | r = devm_gpio_request(&client->dev, phy->gpio_irq, "wake_up"); | ||
| 579 | if (r) { | ||
| 580 | pr_err("%s : gpio_request failed\n", __FILE__); | ||
| 581 | return -ENODEV; | ||
| 582 | } | ||
| 583 | |||
| 584 | r = gpio_direction_input(phy->gpio_irq); | ||
| 585 | if (r) { | ||
| 586 | pr_err("%s : gpio_direction_input failed\n", __FILE__); | ||
| 587 | return -ENODEV; | ||
| 588 | } | ||
| 589 | |||
| 590 | if (phy->gpio_ena > 0) { | ||
| 591 | r = devm_gpio_request(&client->dev, | ||
| 592 | phy->gpio_ena, "clf_enable"); | ||
| 593 | if (r) { | ||
| 594 | pr_err("%s : ena gpio_request failed\n", __FILE__); | ||
| 595 | return -ENODEV; | ||
| 596 | } | ||
| 597 | r = gpio_direction_output(phy->gpio_ena, 1); | ||
| 598 | |||
| 599 | if (r) { | ||
| 600 | pr_err("%s : ena gpio_direction_output failed\n", | ||
| 601 | __FILE__); | ||
| 602 | return -ENODEV; | ||
| 603 | } | ||
| 604 | } | ||
| 605 | |||
| 606 | /* IRQ */ | ||
| 607 | irq = gpio_to_irq(phy->gpio_irq); | ||
| 608 | if (irq < 0) { | ||
| 609 | nfc_err(&client->dev, | ||
| 610 | "Unable to get irq number for GPIO %d error %d\n", | ||
| 611 | phy->gpio_irq, r); | ||
| 612 | return -ENODEV; | ||
| 613 | } | ||
| 614 | client->irq = irq; | ||
| 615 | |||
| 616 | return 0; | ||
| 617 | } | ||
| 618 | |||
| 619 | static int st21nfca_hci_i2c_probe(struct i2c_client *client, | ||
| 620 | const struct i2c_device_id *id) | ||
| 621 | { | ||
| 622 | struct st21nfca_i2c_phy *phy; | ||
| 623 | struct st21nfca_nfc_platform_data *pdata; | ||
| 624 | int r; | ||
| 625 | |||
| 626 | dev_dbg(&client->dev, "%s\n", __func__); | ||
| 627 | dev_dbg(&client->dev, "IRQ: %d\n", client->irq); | ||
| 628 | |||
| 629 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
| 630 | nfc_err(&client->dev, "Need I2C_FUNC_I2C\n"); | ||
| 631 | return -ENODEV; | ||
| 632 | } | ||
| 633 | |||
| 634 | phy = devm_kzalloc(&client->dev, sizeof(struct st21nfca_i2c_phy), | ||
| 635 | GFP_KERNEL); | ||
| 636 | if (!phy) { | ||
| 637 | nfc_err(&client->dev, | ||
| 638 | "Cannot allocate memory for st21nfca i2c phy.\n"); | ||
| 639 | return -ENOMEM; | ||
| 640 | } | ||
| 641 | |||
| 642 | phy->i2c_dev = client; | ||
| 643 | phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL); | ||
| 644 | if (phy->pending_skb == NULL) | ||
| 645 | return -ENOMEM; | ||
| 646 | |||
| 647 | phy->current_read_len = 0; | ||
| 648 | phy->crc_trials = 0; | ||
| 649 | mutex_init(&phy->phy_lock); | ||
| 650 | i2c_set_clientdata(client, phy); | ||
| 651 | |||
| 652 | pdata = client->dev.platform_data; | ||
| 653 | if (!pdata && client->dev.of_node) { | ||
| 654 | r = st21nfca_hci_i2c_of_request_resources(client); | ||
| 655 | if (r) { | ||
| 656 | nfc_err(&client->dev, "No platform data\n"); | ||
| 657 | return r; | ||
| 658 | } | ||
| 659 | } else if (pdata) { | ||
| 660 | r = st21nfca_hci_i2c_request_resources(client); | ||
| 661 | if (r) { | ||
| 662 | nfc_err(&client->dev, "Cannot get platform resources\n"); | ||
| 663 | return r; | ||
| 664 | } | ||
| 665 | } else { | ||
| 666 | nfc_err(&client->dev, "st21nfca platform resources not available\n"); | ||
| 667 | return -ENODEV; | ||
| 668 | } | ||
| 669 | |||
| 670 | r = st21nfca_hci_platform_init(phy); | ||
| 671 | if (r < 0) { | ||
| 672 | nfc_err(&client->dev, "Unable to reboot st21nfca\n"); | ||
| 673 | return -ENODEV; | ||
| 674 | } | ||
| 675 | |||
| 676 | r = devm_request_threaded_irq(&client->dev, client->irq, NULL, | ||
| 677 | st21nfca_hci_irq_thread_fn, | ||
| 678 | phy->irq_polarity | IRQF_ONESHOT, | ||
| 679 | ST21NFCA_HCI_DRIVER_NAME, phy); | ||
| 680 | if (r < 0) { | ||
| 681 | nfc_err(&client->dev, "Unable to register IRQ handler\n"); | ||
| 682 | return r; | ||
| 683 | } | ||
| 684 | |||
| 685 | return st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, | ||
| 686 | ST21NFCA_FRAME_HEADROOM, ST21NFCA_FRAME_TAILROOM, | ||
| 687 | ST21NFCA_HCI_LLC_MAX_PAYLOAD, &phy->hdev); | ||
| 688 | } | ||
| 689 | |||
| 690 | static int st21nfca_hci_i2c_remove(struct i2c_client *client) | ||
| 691 | { | ||
| 692 | struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client); | ||
| 693 | |||
| 694 | dev_dbg(&client->dev, "%s\n", __func__); | ||
| 695 | |||
| 696 | st21nfca_hci_remove(phy->hdev); | ||
| 697 | |||
| 698 | if (phy->powered) | ||
| 699 | st21nfca_hci_i2c_disable(phy); | ||
| 700 | |||
| 701 | return 0; | ||
| 702 | } | ||
| 703 | |||
| 704 | static const struct of_device_id of_st21nfca_i2c_match[] = { | ||
| 705 | { .compatible = "st,st21nfca_i2c", }, | ||
| 706 | {} | ||
| 707 | }; | ||
| 708 | |||
| 709 | static struct i2c_driver st21nfca_hci_i2c_driver = { | ||
| 710 | .driver = { | ||
| 711 | .owner = THIS_MODULE, | ||
| 712 | .name = ST21NFCA_HCI_I2C_DRIVER_NAME, | ||
| 713 | .owner = THIS_MODULE, | ||
| 714 | .of_match_table = of_match_ptr(of_st21nfca_i2c_match), | ||
| 715 | }, | ||
| 716 | .probe = st21nfca_hci_i2c_probe, | ||
| 717 | .id_table = st21nfca_hci_i2c_id_table, | ||
| 718 | .remove = st21nfca_hci_i2c_remove, | ||
| 719 | }; | ||
| 720 | |||
| 721 | module_i2c_driver(st21nfca_hci_i2c_driver); | ||
| 722 | |||
| 723 | MODULE_LICENSE("GPL"); | ||
| 724 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c new file mode 100644 index 000000000000..51e0f00b3a4f --- /dev/null +++ b/drivers/nfc/st21nfca/st21nfca.c | |||
| @@ -0,0 +1,698 @@ | |||
| 1 | /* | ||
| 2 | * HCI based Driver for STMicroelectronics NFC Chip | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms and conditions of the GNU General Public License, | ||
| 8 | * version 2, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/nfc.h> | ||
| 21 | #include <net/nfc/hci.h> | ||
| 22 | #include <net/nfc/llc.h> | ||
| 23 | |||
| 24 | #include "st21nfca.h" | ||
| 25 | |||
| 26 | #define DRIVER_DESC "HCI NFC driver for ST21NFCA" | ||
| 27 | |||
| 28 | #define FULL_VERSION_LEN 3 | ||
| 29 | |||
| 30 | /* Proprietary gates, events, commands and registers */ | ||
| 31 | |||
| 32 | /* Commands that apply to all RF readers */ | ||
| 33 | #define ST21NFCA_RF_READER_CMD_PRESENCE_CHECK 0x30 | ||
| 34 | |||
| 35 | #define ST21NFCA_RF_READER_ISO15693_GATE 0x12 | ||
| 36 | #define ST21NFCA_RF_READER_ISO15693_INVENTORY 0x01 | ||
| 37 | |||
| 38 | /* | ||
| 39 | * Reader gate for communication with contact-less cards using Type A | ||
| 40 | * protocol ISO14443-3 but not compliant with ISO14443-4 | ||
| 41 | */ | ||
| 42 | #define ST21NFCA_RF_READER_14443_3_A_GATE 0x15 | ||
| 43 | #define ST21NFCA_RF_READER_14443_3_A_UID 0x02 | ||
| 44 | #define ST21NFCA_RF_READER_14443_3_A_ATQA 0x03 | ||
| 45 | #define ST21NFCA_RF_READER_14443_3_A_SAK 0x04 | ||
| 46 | |||
| 47 | #define ST21NFCA_DEVICE_MGNT_GATE 0x01 | ||
| 48 | #define ST21NFCA_DEVICE_MGNT_PIPE 0x02 | ||
| 49 | |||
| 50 | #define ST21NFCA_DM_GETINFO 0x13 | ||
| 51 | #define ST21NFCA_DM_GETINFO_PIPE_LIST 0x02 | ||
| 52 | #define ST21NFCA_DM_GETINFO_PIPE_INFO 0x01 | ||
| 53 | #define ST21NFCA_DM_PIPE_CREATED 0x02 | ||
| 54 | #define ST21NFCA_DM_PIPE_OPEN 0x04 | ||
| 55 | #define ST21NFCA_DM_RF_ACTIVE 0x80 | ||
| 56 | |||
| 57 | #define ST21NFCA_DM_IS_PIPE_OPEN(p) \ | ||
| 58 | ((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN)) | ||
| 59 | |||
| 60 | #define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/ | ||
| 61 | |||
| 62 | static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES); | ||
| 63 | |||
| 64 | static struct nfc_hci_gate st21nfca_gates[] = { | ||
| 65 | {NFC_HCI_ADMIN_GATE, NFC_HCI_ADMIN_PIPE}, | ||
| 66 | {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE}, | ||
| 67 | {NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE}, | ||
| 68 | {NFC_HCI_LINK_MGMT_GATE, NFC_HCI_LINK_MGMT_PIPE}, | ||
| 69 | {NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE}, | ||
| 70 | {NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE}, | ||
| 71 | {ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE}, | ||
| 72 | {ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, | ||
| 73 | {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE}, | ||
| 74 | {ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct st21nfca_pipe_info { | ||
| 78 | u8 pipe_state; | ||
| 79 | u8 src_host_id; | ||
| 80 | u8 src_gate_id; | ||
| 81 | u8 dst_host_id; | ||
| 82 | u8 dst_gate_id; | ||
| 83 | } __packed; | ||
| 84 | |||
| 85 | /* Largest headroom needed for outgoing custom commands */ | ||
| 86 | #define ST21NFCA_CMDS_HEADROOM 7 | ||
| 87 | |||
| 88 | static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev) | ||
| 89 | { | ||
| 90 | int i, j, r; | ||
| 91 | struct sk_buff *skb_pipe_list, *skb_pipe_info; | ||
| 92 | struct st21nfca_pipe_info *info; | ||
| 93 | |||
| 94 | u8 pipe_list[] = { ST21NFCA_DM_GETINFO_PIPE_LIST, | ||
| 95 | NFC_HCI_TERMINAL_HOST_ID | ||
| 96 | }; | ||
| 97 | u8 pipe_info[] = { ST21NFCA_DM_GETINFO_PIPE_INFO, | ||
| 98 | NFC_HCI_TERMINAL_HOST_ID, 0 | ||
| 99 | }; | ||
| 100 | |||
| 101 | skb_pipe_list = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE, GFP_KERNEL); | ||
| 102 | if (!skb_pipe_list) { | ||
| 103 | r = -ENOMEM; | ||
| 104 | goto free_list; | ||
| 105 | } | ||
| 106 | |||
| 107 | skb_pipe_info = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE, GFP_KERNEL); | ||
| 108 | if (!skb_pipe_info) { | ||
| 109 | r = -ENOMEM; | ||
| 110 | goto free_info; | ||
| 111 | } | ||
| 112 | |||
| 113 | /* On ST21NFCA device pipes number are dynamics | ||
| 114 | * A maximum of 16 pipes can be created at the same time | ||
| 115 | * If pipes are already created, hci_dev_up will fail. | ||
| 116 | * Doing a clear all pipe is a bad idea because: | ||
| 117 | * - It does useless EEPROM cycling | ||
| 118 | * - It might cause issue for secure elements support | ||
| 119 | * (such as removing connectivity or APDU reader pipe) | ||
| 120 | * A better approach on ST21NFCA is to: | ||
| 121 | * - get a pipe list for each host. | ||
| 122 | * (eg: NFC_HCI_HOST_CONTROLLER_ID for now). | ||
| 123 | * (TODO Later on UICC HOST and eSE HOST) | ||
| 124 | * - get pipe information | ||
| 125 | * - match retrieved pipe list in st21nfca_gates | ||
| 126 | * ST21NFCA_DEVICE_MGNT_GATE is a proprietary gate | ||
| 127 | * with ST21NFCA_DEVICE_MGNT_PIPE. | ||
| 128 | * Pipe can be closed and need to be open. | ||
| 129 | */ | ||
| 130 | r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, | ||
| 131 | ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE); | ||
| 132 | if (r < 0) | ||
| 133 | goto free_info; | ||
| 134 | |||
| 135 | /* Get pipe list */ | ||
| 136 | r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, | ||
| 137 | ST21NFCA_DM_GETINFO, pipe_list, sizeof(pipe_list), | ||
| 138 | &skb_pipe_list); | ||
| 139 | if (r < 0) | ||
| 140 | goto free_info; | ||
| 141 | |||
| 142 | /* Complete the existing gate_pipe table */ | ||
| 143 | for (i = 0; i < skb_pipe_list->len; i++) { | ||
| 144 | pipe_info[2] = skb_pipe_list->data[i]; | ||
| 145 | r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, | ||
| 146 | ST21NFCA_DM_GETINFO, pipe_info, | ||
| 147 | sizeof(pipe_info), &skb_pipe_info); | ||
| 148 | |||
| 149 | if (r) | ||
| 150 | continue; | ||
| 151 | |||
| 152 | /* | ||
| 153 | * Match pipe ID and gate ID | ||
| 154 | * Output format from ST21NFC_DM_GETINFO is: | ||
| 155 | * - pipe state (1byte) | ||
| 156 | * - source hid (1byte) | ||
| 157 | * - source gid (1byte) | ||
| 158 | * - destination hid (1byte) | ||
| 159 | * - destination gid (1byte) | ||
| 160 | */ | ||
| 161 | info = (struct st21nfca_pipe_info *) skb_pipe_info->data; | ||
| 162 | for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) && | ||
| 163 | (st21nfca_gates[j].gate != info->dst_gate_id); | ||
| 164 | j++) | ||
| 165 | ; | ||
| 166 | |||
| 167 | if (j < ARRAY_SIZE(st21nfca_gates) && | ||
| 168 | st21nfca_gates[j].gate == info->dst_gate_id && | ||
| 169 | ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) { | ||
| 170 | st21nfca_gates[j].pipe = pipe_info[2]; | ||
| 171 | hdev->gate2pipe[st21nfca_gates[j].gate] = | ||
| 172 | st21nfca_gates[j].pipe; | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 177 | * 3 gates have a well known pipe ID. | ||
| 178 | * They will never appear in the pipe list | ||
| 179 | */ | ||
| 180 | if (skb_pipe_list->len + 3 < ARRAY_SIZE(st21nfca_gates)) { | ||
| 181 | for (i = skb_pipe_list->len + 3; | ||
| 182 | i < ARRAY_SIZE(st21nfca_gates); i++) { | ||
| 183 | r = nfc_hci_connect_gate(hdev, | ||
| 184 | NFC_HCI_HOST_CONTROLLER_ID, | ||
| 185 | st21nfca_gates[i].gate, | ||
| 186 | st21nfca_gates[i].pipe); | ||
| 187 | if (r < 0) | ||
| 188 | goto free_info; | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | memcpy(hdev->init_data.gates, st21nfca_gates, sizeof(st21nfca_gates)); | ||
| 193 | free_info: | ||
| 194 | kfree_skb(skb_pipe_info); | ||
| 195 | free_list: | ||
| 196 | kfree_skb(skb_pipe_list); | ||
| 197 | return r; | ||
| 198 | } | ||
| 199 | |||
| 200 | static int st21nfca_hci_open(struct nfc_hci_dev *hdev) | ||
| 201 | { | ||
| 202 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
| 203 | int r; | ||
| 204 | |||
| 205 | mutex_lock(&info->info_lock); | ||
| 206 | |||
| 207 | if (info->state != ST21NFCA_ST_COLD) { | ||
| 208 | r = -EBUSY; | ||
| 209 | goto out; | ||
| 210 | } | ||
| 211 | |||
| 212 | r = info->phy_ops->enable(info->phy_id); | ||
| 213 | |||
| 214 | if (r == 0) | ||
| 215 | info->state = ST21NFCA_ST_READY; | ||
| 216 | |||
| 217 | out: | ||
| 218 | mutex_unlock(&info->info_lock); | ||
| 219 | return r; | ||
| 220 | } | ||
| 221 | |||
| 222 | static void st21nfca_hci_close(struct nfc_hci_dev *hdev) | ||
| 223 | { | ||
| 224 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
| 225 | |||
| 226 | mutex_lock(&info->info_lock); | ||
| 227 | |||
| 228 | if (info->state == ST21NFCA_ST_COLD) | ||
| 229 | goto out; | ||
| 230 | |||
| 231 | info->phy_ops->disable(info->phy_id); | ||
| 232 | info->state = ST21NFCA_ST_COLD; | ||
| 233 | |||
| 234 | out: | ||
| 235 | mutex_unlock(&info->info_lock); | ||
| 236 | } | ||
| 237 | |||
| 238 | static int st21nfca_hci_ready(struct nfc_hci_dev *hdev) | ||
| 239 | { | ||
| 240 | struct sk_buff *skb; | ||
| 241 | |||
| 242 | u8 param; | ||
| 243 | int r; | ||
| 244 | |||
| 245 | param = NFC_HCI_UICC_HOST_ID; | ||
| 246 | r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, | ||
| 247 | NFC_HCI_ADMIN_WHITELIST, ¶m, 1); | ||
| 248 | if (r < 0) | ||
| 249 | return r; | ||
| 250 | |||
| 251 | /* Set NFC_MODE in device management gate to enable */ | ||
| 252 | r = nfc_hci_get_param(hdev, ST21NFCA_DEVICE_MGNT_GATE, | ||
| 253 | ST21NFCA_NFC_MODE, &skb); | ||
| 254 | if (r < 0) | ||
| 255 | return r; | ||
| 256 | |||
| 257 | if (skb->data[0] == 0) { | ||
| 258 | kfree_skb(skb); | ||
| 259 | param = 1; | ||
| 260 | |||
| 261 | r = nfc_hci_set_param(hdev, ST21NFCA_DEVICE_MGNT_GATE, | ||
| 262 | ST21NFCA_NFC_MODE, ¶m, 1); | ||
| 263 | if (r < 0) | ||
| 264 | return r; | ||
| 265 | } | ||
| 266 | |||
| 267 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
| 268 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
| 269 | if (r < 0) | ||
| 270 | return r; | ||
| 271 | |||
| 272 | r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, | ||
| 273 | NFC_HCI_ID_MGMT_VERSION_SW, &skb); | ||
| 274 | if (r < 0) | ||
| 275 | return r; | ||
| 276 | |||
| 277 | if (skb->len != FULL_VERSION_LEN) { | ||
| 278 | kfree_skb(skb); | ||
| 279 | return -EINVAL; | ||
| 280 | } | ||
| 281 | |||
| 282 | print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ", | ||
| 283 | DUMP_PREFIX_NONE, 16, 1, | ||
| 284 | skb->data, FULL_VERSION_LEN, false); | ||
| 285 | |||
| 286 | kfree_skb(skb); | ||
| 287 | |||
| 288 | return 0; | ||
| 289 | } | ||
| 290 | |||
| 291 | static int st21nfca_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) | ||
| 292 | { | ||
| 293 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
| 294 | |||
| 295 | return info->phy_ops->write(info->phy_id, skb); | ||
| 296 | } | ||
| 297 | |||
| 298 | static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev, | ||
| 299 | u32 im_protocols, u32 tm_protocols) | ||
| 300 | { | ||
| 301 | int r; | ||
| 302 | |||
| 303 | pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", | ||
| 304 | __func__, im_protocols, tm_protocols); | ||
| 305 | |||
| 306 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
| 307 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
| 308 | if (r < 0) | ||
| 309 | return r; | ||
| 310 | if (im_protocols) { | ||
| 311 | /* | ||
| 312 | * enable polling according to im_protocols & tm_protocols | ||
| 313 | * - CLOSE pipe according to im_protocols & tm_protocols | ||
| 314 | */ | ||
| 315 | if ((NFC_HCI_RF_READER_B_GATE & im_protocols) == 0) { | ||
| 316 | r = nfc_hci_disconnect_gate(hdev, | ||
| 317 | NFC_HCI_RF_READER_B_GATE); | ||
| 318 | if (r < 0) | ||
| 319 | return r; | ||
| 320 | } | ||
| 321 | |||
| 322 | if ((NFC_HCI_RF_READER_A_GATE & im_protocols) == 0) { | ||
| 323 | r = nfc_hci_disconnect_gate(hdev, | ||
| 324 | NFC_HCI_RF_READER_A_GATE); | ||
| 325 | if (r < 0) | ||
| 326 | return r; | ||
| 327 | } | ||
| 328 | |||
| 329 | if ((ST21NFCA_RF_READER_F_GATE & im_protocols) == 0) { | ||
| 330 | r = nfc_hci_disconnect_gate(hdev, | ||
| 331 | ST21NFCA_RF_READER_F_GATE); | ||
| 332 | if (r < 0) | ||
| 333 | return r; | ||
| 334 | } | ||
| 335 | |||
| 336 | if ((ST21NFCA_RF_READER_14443_3_A_GATE & im_protocols) == 0) { | ||
| 337 | r = nfc_hci_disconnect_gate(hdev, | ||
| 338 | ST21NFCA_RF_READER_14443_3_A_GATE); | ||
| 339 | if (r < 0) | ||
| 340 | return r; | ||
| 341 | } | ||
| 342 | |||
| 343 | if ((ST21NFCA_RF_READER_ISO15693_GATE & im_protocols) == 0) { | ||
| 344 | r = nfc_hci_disconnect_gate(hdev, | ||
| 345 | ST21NFCA_RF_READER_ISO15693_GATE); | ||
| 346 | if (r < 0) | ||
| 347 | return r; | ||
| 348 | } | ||
| 349 | |||
| 350 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
| 351 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | ||
| 352 | if (r < 0) | ||
| 353 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
| 354 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
| 355 | } | ||
| 356 | return r; | ||
| 357 | } | ||
| 358 | |||
| 359 | static int st21nfca_get_iso14443_3_atqa(struct nfc_hci_dev *hdev, u16 *atqa) | ||
| 360 | { | ||
| 361 | int r; | ||
| 362 | struct sk_buff *atqa_skb = NULL; | ||
| 363 | |||
| 364 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE, | ||
| 365 | ST21NFCA_RF_READER_14443_3_A_ATQA, &atqa_skb); | ||
| 366 | if (r < 0) | ||
| 367 | goto exit; | ||
| 368 | |||
| 369 | if (atqa_skb->len != 2) { | ||
| 370 | r = -EPROTO; | ||
| 371 | goto exit; | ||
| 372 | } | ||
| 373 | |||
| 374 | *atqa = be16_to_cpu(*(__be16 *) atqa_skb->data); | ||
| 375 | |||
| 376 | exit: | ||
| 377 | kfree_skb(atqa_skb); | ||
| 378 | return r; | ||
| 379 | } | ||
| 380 | |||
| 381 | static int st21nfca_get_iso14443_3_sak(struct nfc_hci_dev *hdev, u8 *sak) | ||
| 382 | { | ||
| 383 | int r; | ||
| 384 | struct sk_buff *sak_skb = NULL; | ||
| 385 | |||
| 386 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE, | ||
| 387 | ST21NFCA_RF_READER_14443_3_A_SAK, &sak_skb); | ||
| 388 | if (r < 0) | ||
| 389 | goto exit; | ||
| 390 | |||
| 391 | if (sak_skb->len != 1) { | ||
| 392 | r = -EPROTO; | ||
| 393 | goto exit; | ||
| 394 | } | ||
| 395 | |||
| 396 | *sak = sak_skb->data[0]; | ||
| 397 | |||
| 398 | exit: | ||
| 399 | kfree_skb(sak_skb); | ||
| 400 | return r; | ||
| 401 | } | ||
| 402 | |||
| 403 | static int st21nfca_get_iso14443_3_uid(struct nfc_hci_dev *hdev, u8 *gate, | ||
| 404 | int *len) | ||
| 405 | { | ||
| 406 | int r; | ||
| 407 | struct sk_buff *uid_skb = NULL; | ||
| 408 | |||
| 409 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE, | ||
| 410 | ST21NFCA_RF_READER_14443_3_A_UID, &uid_skb); | ||
| 411 | if (r < 0) | ||
| 412 | goto exit; | ||
| 413 | |||
| 414 | if (uid_skb->len == 0 || uid_skb->len > NFC_NFCID1_MAXSIZE) { | ||
| 415 | r = -EPROTO; | ||
| 416 | goto exit; | ||
| 417 | } | ||
| 418 | |||
| 419 | gate = uid_skb->data; | ||
| 420 | *len = uid_skb->len; | ||
| 421 | exit: | ||
| 422 | kfree_skb(uid_skb); | ||
| 423 | return r; | ||
| 424 | } | ||
| 425 | |||
| 426 | static int st21nfca_get_iso15693_inventory(struct nfc_hci_dev *hdev, | ||
| 427 | struct nfc_target *target) | ||
| 428 | { | ||
| 429 | int r; | ||
| 430 | struct sk_buff *inventory_skb = NULL; | ||
| 431 | |||
| 432 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_ISO15693_GATE, | ||
| 433 | ST21NFCA_RF_READER_ISO15693_INVENTORY, | ||
| 434 | &inventory_skb); | ||
| 435 | if (r < 0) | ||
| 436 | goto exit; | ||
| 437 | |||
| 438 | skb_pull(inventory_skb, 2); | ||
| 439 | |||
| 440 | if (inventory_skb->len == 0 || | ||
| 441 | inventory_skb->len > NFC_ISO15693_UID_MAXSIZE) { | ||
| 442 | r = -EPROTO; | ||
| 443 | goto exit; | ||
| 444 | } | ||
| 445 | |||
| 446 | memcpy(target->iso15693_uid, inventory_skb->data, inventory_skb->len); | ||
| 447 | target->iso15693_dsfid = inventory_skb->data[1]; | ||
| 448 | target->is_iso15693 = 1; | ||
| 449 | exit: | ||
| 450 | kfree_skb(inventory_skb); | ||
| 451 | return r; | ||
| 452 | } | ||
| 453 | |||
| 454 | static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, | ||
| 455 | struct nfc_target *target) | ||
| 456 | { | ||
| 457 | int r, len; | ||
| 458 | u16 atqa; | ||
| 459 | u8 sak; | ||
| 460 | u8 uid[NFC_NFCID1_MAXSIZE]; | ||
| 461 | |||
| 462 | switch (gate) { | ||
| 463 | case ST21NFCA_RF_READER_F_GATE: | ||
| 464 | target->supported_protocols = NFC_PROTO_FELICA_MASK; | ||
| 465 | break; | ||
| 466 | case ST21NFCA_RF_READER_14443_3_A_GATE: | ||
| 467 | /* ISO14443-3 type 1 or 2 tags */ | ||
| 468 | r = st21nfca_get_iso14443_3_atqa(hdev, &atqa); | ||
| 469 | if (r < 0) | ||
| 470 | return r; | ||
| 471 | if (atqa == 0x000c) { | ||
| 472 | target->supported_protocols = NFC_PROTO_JEWEL_MASK; | ||
| 473 | target->sens_res = 0x0c00; | ||
| 474 | } else { | ||
| 475 | r = st21nfca_get_iso14443_3_sak(hdev, &sak); | ||
| 476 | if (r < 0) | ||
| 477 | return r; | ||
| 478 | |||
| 479 | r = st21nfca_get_iso14443_3_uid(hdev, uid, &len); | ||
| 480 | if (r < 0) | ||
| 481 | return r; | ||
| 482 | |||
| 483 | target->supported_protocols = | ||
| 484 | nfc_hci_sak_to_protocol(sak); | ||
| 485 | if (target->supported_protocols == 0xffffffff) | ||
| 486 | return -EPROTO; | ||
| 487 | |||
| 488 | target->sens_res = atqa; | ||
| 489 | target->sel_res = sak; | ||
| 490 | memcpy(target->nfcid1, uid, len); | ||
| 491 | target->nfcid1_len = len; | ||
| 492 | } | ||
| 493 | |||
| 494 | break; | ||
| 495 | case ST21NFCA_RF_READER_ISO15693_GATE: | ||
| 496 | target->supported_protocols = NFC_PROTO_ISO15693_MASK; | ||
| 497 | r = st21nfca_get_iso15693_inventory(hdev, target); | ||
| 498 | if (r < 0) | ||
| 499 | return r; | ||
| 500 | break; | ||
| 501 | default: | ||
| 502 | return -EPROTO; | ||
| 503 | } | ||
| 504 | |||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | |||
| 508 | #define ST21NFCA_CB_TYPE_READER_ISO15693 1 | ||
| 509 | static void st21nfca_hci_data_exchange_cb(void *context, struct sk_buff *skb, | ||
| 510 | int err) | ||
| 511 | { | ||
| 512 | struct st21nfca_hci_info *info = context; | ||
| 513 | |||
| 514 | switch (info->async_cb_type) { | ||
| 515 | case ST21NFCA_CB_TYPE_READER_ISO15693: | ||
| 516 | if (err == 0) | ||
| 517 | skb_trim(skb, skb->len - 1); | ||
| 518 | info->async_cb(info->async_cb_context, skb, err); | ||
| 519 | break; | ||
| 520 | default: | ||
| 521 | if (err == 0) | ||
| 522 | kfree_skb(skb); | ||
| 523 | break; | ||
| 524 | } | ||
| 525 | } | ||
| 526 | |||
| 527 | /* | ||
| 528 | * Returns: | ||
| 529 | * <= 0: driver handled the data exchange | ||
| 530 | * 1: driver doesn't especially handle, please do standard processing | ||
| 531 | */ | ||
| 532 | static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev, | ||
| 533 | struct nfc_target *target, | ||
| 534 | struct sk_buff *skb, | ||
| 535 | data_exchange_cb_t cb, void *cb_context) | ||
| 536 | { | ||
| 537 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
| 538 | |||
| 539 | pr_info(DRIVER_DESC ": %s for gate=%d len=%d\n", __func__, | ||
| 540 | target->hci_reader_gate, skb->len); | ||
| 541 | |||
| 542 | switch (target->hci_reader_gate) { | ||
| 543 | case ST21NFCA_RF_READER_F_GATE: | ||
| 544 | *skb_push(skb, 1) = 0x1a; | ||
| 545 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, | ||
| 546 | ST21NFCA_WR_XCHG_DATA, skb->data, | ||
| 547 | skb->len, cb, cb_context); | ||
| 548 | case ST21NFCA_RF_READER_14443_3_A_GATE: | ||
| 549 | *skb_push(skb, 1) = 0x1a; /* CTR, see spec:10.2.2.1 */ | ||
| 550 | |||
| 551 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, | ||
| 552 | ST21NFCA_WR_XCHG_DATA, skb->data, | ||
| 553 | skb->len, cb, cb_context); | ||
| 554 | case ST21NFCA_RF_READER_ISO15693_GATE: | ||
| 555 | info->async_cb_type = ST21NFCA_CB_TYPE_READER_ISO15693; | ||
| 556 | info->async_cb = cb; | ||
| 557 | info->async_cb_context = cb_context; | ||
| 558 | |||
| 559 | *skb_push(skb, 1) = 0x17; | ||
| 560 | |||
| 561 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, | ||
| 562 | ST21NFCA_WR_XCHG_DATA, skb->data, | ||
| 563 | skb->len, | ||
| 564 | st21nfca_hci_data_exchange_cb, | ||
| 565 | info); | ||
| 566 | break; | ||
| 567 | default: | ||
| 568 | return 1; | ||
| 569 | } | ||
| 570 | } | ||
| 571 | |||
| 572 | static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev, | ||
| 573 | struct nfc_target *target) | ||
| 574 | { | ||
| 575 | u8 fwi = 0x11; | ||
| 576 | switch (target->hci_reader_gate) { | ||
| 577 | case NFC_HCI_RF_READER_A_GATE: | ||
| 578 | case NFC_HCI_RF_READER_B_GATE: | ||
| 579 | /* | ||
| 580 | * PRESENCE_CHECK on those gates is available | ||
| 581 | * However, the answer to this command is taking 3 * fwi | ||
| 582 | * if the card is no present. | ||
| 583 | * Instead, we send an empty I-Frame with a very short | ||
| 584 | * configurable fwi ~604µs. | ||
| 585 | */ | ||
| 586 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | ||
| 587 | ST21NFCA_WR_XCHG_DATA, &fwi, 1, NULL); | ||
| 588 | case ST21NFCA_RF_READER_14443_3_A_GATE: | ||
| 589 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | ||
| 590 | ST21NFCA_RF_READER_CMD_PRESENCE_CHECK, | ||
| 591 | NULL, 0, NULL); | ||
| 592 | default: | ||
| 593 | return -EOPNOTSUPP; | ||
| 594 | } | ||
| 595 | } | ||
| 596 | |||
| 597 | static struct nfc_hci_ops st21nfca_hci_ops = { | ||
| 598 | .open = st21nfca_hci_open, | ||
| 599 | .close = st21nfca_hci_close, | ||
| 600 | .load_session = st21nfca_hci_load_session, | ||
| 601 | .hci_ready = st21nfca_hci_ready, | ||
| 602 | .xmit = st21nfca_hci_xmit, | ||
| 603 | .start_poll = st21nfca_hci_start_poll, | ||
| 604 | .target_from_gate = st21nfca_hci_target_from_gate, | ||
| 605 | .im_transceive = st21nfca_hci_im_transceive, | ||
| 606 | .check_presence = st21nfca_hci_check_presence, | ||
| 607 | }; | ||
| 608 | |||
| 609 | int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | ||
| 610 | char *llc_name, int phy_headroom, int phy_tailroom, | ||
| 611 | int phy_payload, struct nfc_hci_dev **hdev) | ||
| 612 | { | ||
| 613 | struct st21nfca_hci_info *info; | ||
| 614 | int r = 0; | ||
| 615 | int dev_num; | ||
| 616 | u32 protocols; | ||
| 617 | struct nfc_hci_init_data init_data; | ||
| 618 | unsigned long quirks = 0; | ||
| 619 | |||
| 620 | info = kzalloc(sizeof(struct st21nfca_hci_info), GFP_KERNEL); | ||
| 621 | if (!info) { | ||
| 622 | r = -ENOMEM; | ||
| 623 | goto err_alloc_hdev; | ||
| 624 | } | ||
| 625 | |||
| 626 | info->phy_ops = phy_ops; | ||
| 627 | info->phy_id = phy_id; | ||
| 628 | info->state = ST21NFCA_ST_COLD; | ||
| 629 | mutex_init(&info->info_lock); | ||
| 630 | |||
| 631 | init_data.gate_count = ARRAY_SIZE(st21nfca_gates); | ||
| 632 | |||
| 633 | memcpy(init_data.gates, st21nfca_gates, sizeof(st21nfca_gates)); | ||
| 634 | |||
| 635 | /* | ||
| 636 | * Session id must include the driver name + i2c bus addr | ||
| 637 | * persistent info to discriminate 2 identical chips | ||
| 638 | */ | ||
| 639 | dev_num = find_first_zero_bit(dev_mask, ST21NFCA_NUM_DEVICES); | ||
| 640 | if (dev_num >= ST21NFCA_NUM_DEVICES) | ||
| 641 | goto err_alloc_hdev; | ||
| 642 | |||
| 643 | scnprintf(init_data.session_id, sizeof(init_data.session_id), "%s%2x", | ||
| 644 | "ST21AH", dev_num); | ||
| 645 | |||
| 646 | protocols = NFC_PROTO_JEWEL_MASK | | ||
| 647 | NFC_PROTO_MIFARE_MASK | | ||
| 648 | NFC_PROTO_FELICA_MASK | | ||
| 649 | NFC_PROTO_ISO14443_MASK | | ||
| 650 | NFC_PROTO_ISO14443_B_MASK | | ||
| 651 | NFC_PROTO_ISO15693_MASK; | ||
| 652 | |||
| 653 | set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks); | ||
| 654 | |||
| 655 | info->hdev = | ||
| 656 | nfc_hci_allocate_device(&st21nfca_hci_ops, &init_data, quirks, | ||
| 657 | protocols, llc_name, | ||
| 658 | phy_headroom + ST21NFCA_CMDS_HEADROOM, | ||
| 659 | phy_tailroom, phy_payload); | ||
| 660 | |||
| 661 | if (!info->hdev) { | ||
| 662 | pr_err("Cannot allocate nfc hdev.\n"); | ||
| 663 | r = -ENOMEM; | ||
| 664 | goto err_alloc_hdev; | ||
| 665 | } | ||
| 666 | |||
| 667 | nfc_hci_set_clientdata(info->hdev, info); | ||
| 668 | |||
| 669 | r = nfc_hci_register_device(info->hdev); | ||
| 670 | if (r) | ||
| 671 | goto err_regdev; | ||
| 672 | |||
| 673 | *hdev = info->hdev; | ||
| 674 | |||
| 675 | return 0; | ||
| 676 | |||
| 677 | err_regdev: | ||
| 678 | nfc_hci_free_device(info->hdev); | ||
| 679 | |||
| 680 | err_alloc_hdev: | ||
| 681 | kfree(info); | ||
| 682 | |||
| 683 | return r; | ||
| 684 | } | ||
| 685 | EXPORT_SYMBOL(st21nfca_hci_probe); | ||
| 686 | |||
| 687 | void st21nfca_hci_remove(struct nfc_hci_dev *hdev) | ||
| 688 | { | ||
| 689 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
| 690 | |||
| 691 | nfc_hci_unregister_device(hdev); | ||
| 692 | nfc_hci_free_device(hdev); | ||
| 693 | kfree(info); | ||
| 694 | } | ||
| 695 | EXPORT_SYMBOL(st21nfca_hci_remove); | ||
| 696 | |||
| 697 | MODULE_LICENSE("GPL"); | ||
| 698 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h new file mode 100644 index 000000000000..334cd90bcc8c --- /dev/null +++ b/drivers/nfc/st21nfca/st21nfca.h | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify it | ||
| 5 | * under the terms and conditions of the GNU General Public License, | ||
| 6 | * version 2, as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef __LOCAL_ST21NFCA_H_ | ||
| 18 | #define __LOCAL_ST21NFCA_H_ | ||
| 19 | |||
| 20 | #include <net/nfc/hci.h> | ||
| 21 | |||
| 22 | #define HCI_MODE 0 | ||
| 23 | |||
| 24 | /* framing in HCI mode */ | ||
| 25 | #define ST21NFCA_SOF_EOF_LEN 2 | ||
| 26 | |||
| 27 | /* Almost every time value is 0 */ | ||
| 28 | #define ST21NFCA_HCI_LLC_LEN 1 | ||
| 29 | |||
| 30 | /* Size in worst case : | ||
| 31 | * In normal case CRC len = 2 but byte stuffing | ||
| 32 | * may appear in case one CRC byte = ST21NFCA_SOF_EOF | ||
| 33 | */ | ||
| 34 | #define ST21NFCA_HCI_LLC_CRC 4 | ||
| 35 | |||
| 36 | #define ST21NFCA_HCI_LLC_LEN_CRC (ST21NFCA_SOF_EOF_LEN + \ | ||
| 37 | ST21NFCA_HCI_LLC_LEN + \ | ||
| 38 | ST21NFCA_HCI_LLC_CRC) | ||
| 39 | #define ST21NFCA_HCI_LLC_MIN_SIZE (1 + ST21NFCA_HCI_LLC_LEN_CRC) | ||
| 40 | |||
| 41 | /* Worst case when adding byte stuffing between each byte */ | ||
| 42 | #define ST21NFCA_HCI_LLC_MAX_PAYLOAD 29 | ||
| 43 | #define ST21NFCA_HCI_LLC_MAX_SIZE (ST21NFCA_HCI_LLC_LEN_CRC + 1 + \ | ||
| 44 | ST21NFCA_HCI_LLC_MAX_PAYLOAD) | ||
| 45 | |||
| 46 | #define DRIVER_DESC "HCI NFC driver for ST21NFCA" | ||
| 47 | |||
| 48 | #define ST21NFCA_HCI_MODE 0 | ||
| 49 | |||
| 50 | #define ST21NFCA_NUM_DEVICES 256 | ||
| 51 | |||
| 52 | int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | ||
| 53 | char *llc_name, int phy_headroom, int phy_tailroom, | ||
| 54 | int phy_payload, struct nfc_hci_dev **hdev); | ||
| 55 | void st21nfca_hci_remove(struct nfc_hci_dev *hdev); | ||
| 56 | |||
| 57 | enum st21nfca_state { | ||
| 58 | ST21NFCA_ST_COLD, | ||
| 59 | ST21NFCA_ST_READY, | ||
| 60 | }; | ||
| 61 | |||
| 62 | struct st21nfca_hci_info { | ||
| 63 | struct nfc_phy_ops *phy_ops; | ||
| 64 | void *phy_id; | ||
| 65 | |||
| 66 | struct nfc_hci_dev *hdev; | ||
| 67 | |||
| 68 | enum st21nfca_state state; | ||
| 69 | |||
| 70 | struct mutex info_lock; | ||
| 71 | |||
| 72 | int async_cb_type; | ||
| 73 | data_exchange_cb_t async_cb; | ||
| 74 | void *async_cb_context; | ||
| 75 | |||
| 76 | } __packed; | ||
| 77 | |||
| 78 | /* Reader RF commands */ | ||
| 79 | #define ST21NFCA_WR_XCHG_DATA 0x10 | ||
| 80 | |||
| 81 | #define ST21NFCA_RF_READER_F_GATE 0x14 | ||
| 82 | #define ST21NFCA_RF_READER_F_DATARATE 0x01 | ||
| 83 | #define ST21NFCA_RF_READER_F_DATARATE_106 0x01 | ||
| 84 | #define ST21NFCA_RF_READER_F_DATARATE_212 0x02 | ||
| 85 | #define ST21NFCA_RF_READER_F_DATARATE_424 0x04 | ||
| 86 | |||
| 87 | #endif /* __LOCAL_ST21NFCA_H_ */ | ||
diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index d9babe986473..efb36593ecb4 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
| 17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
| 18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
| 19 | #include <linux/pm_runtime.h> | ||
| 19 | #include <linux/nfc.h> | 20 | #include <linux/nfc.h> |
| 20 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
| 21 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| @@ -67,14 +68,14 @@ | |||
| 67 | * only the SRX bit set, it means that all of the data has been received | 68 | * only the SRX bit set, it means that all of the data has been received |
| 68 | * (once what's in the fifo has been read). However, depending on timing | 69 | * (once what's in the fifo has been read). However, depending on timing |
| 69 | * an interrupt status with only the SRX bit set may not be recived. In | 70 | * an interrupt status with only the SRX bit set may not be recived. In |
| 70 | * those cases, the timeout mechanism is used to wait 5 ms in case more | 71 | * those cases, the timeout mechanism is used to wait 20 ms in case more |
| 71 | * data arrives. After 5 ms, it is assumed that all of the data has been | 72 | * data arrives. After 20 ms, it is assumed that all of the data has been |
| 72 | * received and the accumulated rx data is sent upstream. The | 73 | * received and the accumulated rx data is sent upstream. The |
| 73 | * 'TRF7970A_ST_WAIT_FOR_RX_DATA_CONT' state is used for this purpose | 74 | * 'TRF7970A_ST_WAIT_FOR_RX_DATA_CONT' state is used for this purpose |
| 74 | * (i.e., it indicates that some data has been received but we're not sure | 75 | * (i.e., it indicates that some data has been received but we're not sure |
| 75 | * if there is more coming so a timeout in this state means all data has | 76 | * if there is more coming so a timeout in this state means all data has |
| 76 | * been received and there isn't an error). The delay is 5 ms since delays | 77 | * been received and there isn't an error). The delay is 20 ms since delays |
| 77 | * over 2 ms have been observed during testing (a little extra just in case). | 78 | * of ~16 ms have been observed during testing. |
| 78 | * | 79 | * |
| 79 | * Type 2 write and sector select commands respond with a 4-bit ACK or NACK. | 80 | * Type 2 write and sector select commands respond with a 4-bit ACK or NACK. |
| 80 | * Having only 4 bits in the FIFO won't normally generate an interrupt so | 81 | * Having only 4 bits in the FIFO won't normally generate an interrupt so |
| @@ -104,7 +105,9 @@ | |||
| 104 | 105 | ||
| 105 | #define TRF7970A_SUPPORTED_PROTOCOLS \ | 106 | #define TRF7970A_SUPPORTED_PROTOCOLS \ |
| 106 | (NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK | \ | 107 | (NFC_PROTO_MIFARE_MASK | NFC_PROTO_ISO14443_MASK | \ |
| 107 | NFC_PROTO_ISO15693_MASK) | 108 | NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_ISO15693_MASK) |
| 109 | |||
| 110 | #define TRF7970A_AUTOSUSPEND_DELAY 30000 /* 30 seconds */ | ||
| 108 | 111 | ||
| 109 | /* TX data must be prefixed with a FIFO reset cmd, a cmd that depends | 112 | /* TX data must be prefixed with a FIFO reset cmd, a cmd that depends |
| 110 | * on what the current framing is, the address of the TX length byte 1 | 113 | * on what the current framing is, the address of the TX length byte 1 |
| @@ -120,7 +123,7 @@ | |||
| 120 | /* TX length is 3 nibbles long ==> 4KB - 1 bytes max */ | 123 | /* TX length is 3 nibbles long ==> 4KB - 1 bytes max */ |
| 121 | #define TRF7970A_TX_MAX (4096 - 1) | 124 | #define TRF7970A_TX_MAX (4096 - 1) |
| 122 | 125 | ||
| 123 | #define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT 5 | 126 | #define TRF7970A_WAIT_FOR_RX_DATA_TIMEOUT 20 |
| 124 | #define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 3 | 127 | #define TRF7970A_WAIT_FOR_FIFO_DRAIN_TIMEOUT 3 |
| 125 | #define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 20 | 128 | #define TRF7970A_WAIT_TO_ISSUE_ISO15693_EOF 20 |
| 126 | 129 | ||
| @@ -330,13 +333,15 @@ struct trf7970a { | |||
| 330 | struct regulator *regulator; | 333 | struct regulator *regulator; |
| 331 | struct nfc_digital_dev *ddev; | 334 | struct nfc_digital_dev *ddev; |
| 332 | u32 quirks; | 335 | u32 quirks; |
| 333 | bool powering_up; | ||
| 334 | bool aborting; | 336 | bool aborting; |
| 335 | struct sk_buff *tx_skb; | 337 | struct sk_buff *tx_skb; |
| 336 | struct sk_buff *rx_skb; | 338 | struct sk_buff *rx_skb; |
| 337 | nfc_digital_cmd_complete_t cb; | 339 | nfc_digital_cmd_complete_t cb; |
| 338 | void *cb_arg; | 340 | void *cb_arg; |
| 341 | u8 chip_status_ctrl; | ||
| 339 | u8 iso_ctrl; | 342 | u8 iso_ctrl; |
| 343 | u8 iso_ctrl_tech; | ||
| 344 | u8 modulator_sys_clk_ctrl; | ||
| 340 | u8 special_fcn_reg1; | 345 | u8 special_fcn_reg1; |
| 341 | int technology; | 346 | int technology; |
| 342 | int framing; | 347 | int framing; |
| @@ -681,7 +686,9 @@ static irqreturn_t trf7970a_irq(int irq, void *dev_id) | |||
| 681 | trf->ignore_timeout = | 686 | trf->ignore_timeout = |
| 682 | !cancel_delayed_work(&trf->timeout_work); | 687 | !cancel_delayed_work(&trf->timeout_work); |
| 683 | trf7970a_drain_fifo(trf, status); | 688 | trf7970a_drain_fifo(trf, status); |
| 684 | } else if (!(status & TRF7970A_IRQ_STATUS_TX)) { | 689 | } else if (status == TRF7970A_IRQ_STATUS_TX) { |
| 690 | trf7970a_cmd(trf, TRF7970A_CMD_FIFO_RESET); | ||
| 691 | } else { | ||
| 685 | trf7970a_send_err_upstream(trf, -EIO); | 692 | trf7970a_send_err_upstream(trf, -EIO); |
| 686 | } | 693 | } |
| 687 | break; | 694 | break; |
| @@ -757,8 +764,8 @@ static int trf7970a_init(struct trf7970a *trf) | |||
| 757 | if (ret) | 764 | if (ret) |
| 758 | goto err_out; | 765 | goto err_out; |
| 759 | 766 | ||
| 760 | ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, | 767 | /* Must clear NFC Target Detection Level reg due to erratum */ |
| 761 | TRF7970A_MODULATOR_DEPTH_OOK); | 768 | ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0); |
| 762 | if (ret) | 769 | if (ret) |
| 763 | goto err_out; | 770 | goto err_out; |
| 764 | 771 | ||
| @@ -774,12 +781,7 @@ static int trf7970a_init(struct trf7970a *trf) | |||
| 774 | 781 | ||
| 775 | trf->special_fcn_reg1 = 0; | 782 | trf->special_fcn_reg1 = 0; |
| 776 | 783 | ||
| 777 | ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, | 784 | trf->iso_ctrl = 0xff; |
| 778 | TRF7970A_CHIP_STATUS_RF_ON | | ||
| 779 | TRF7970A_CHIP_STATUS_VRS5_3); | ||
| 780 | if (ret) | ||
| 781 | goto err_out; | ||
| 782 | |||
| 783 | return 0; | 785 | return 0; |
| 784 | 786 | ||
| 785 | err_out: | 787 | err_out: |
| @@ -791,53 +793,29 @@ static void trf7970a_switch_rf_off(struct trf7970a *trf) | |||
| 791 | { | 793 | { |
| 792 | dev_dbg(trf->dev, "Switching rf off\n"); | 794 | dev_dbg(trf->dev, "Switching rf off\n"); |
| 793 | 795 | ||
| 794 | gpio_set_value(trf->en_gpio, 0); | 796 | trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON; |
| 795 | gpio_set_value(trf->en2_gpio, 0); | 797 | |
| 798 | trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, trf->chip_status_ctrl); | ||
| 796 | 799 | ||
| 797 | trf->aborting = false; | 800 | trf->aborting = false; |
| 798 | trf->state = TRF7970A_ST_OFF; | 801 | trf->state = TRF7970A_ST_OFF; |
| 802 | |||
| 803 | pm_runtime_mark_last_busy(trf->dev); | ||
| 804 | pm_runtime_put_autosuspend(trf->dev); | ||
| 799 | } | 805 | } |
| 800 | 806 | ||
| 801 | static int trf7970a_switch_rf_on(struct trf7970a *trf) | 807 | static void trf7970a_switch_rf_on(struct trf7970a *trf) |
| 802 | { | 808 | { |
| 803 | unsigned long delay; | ||
| 804 | int ret; | ||
| 805 | |||
| 806 | dev_dbg(trf->dev, "Switching rf on\n"); | 809 | dev_dbg(trf->dev, "Switching rf on\n"); |
| 807 | 810 | ||
| 808 | if (trf->powering_up) | 811 | pm_runtime_get_sync(trf->dev); |
| 809 | usleep_range(5000, 6000); | ||
| 810 | |||
| 811 | gpio_set_value(trf->en2_gpio, 1); | ||
| 812 | usleep_range(1000, 2000); | ||
| 813 | gpio_set_value(trf->en_gpio, 1); | ||
| 814 | 812 | ||
| 815 | /* The delay between enabling the trf7970a and issuing the first | 813 | trf->state = TRF7970A_ST_IDLE; |
| 816 | * command is significantly longer the very first time after powering | ||
| 817 | * up. Make sure the longer delay is only done the first time. | ||
| 818 | */ | ||
| 819 | if (trf->powering_up) { | ||
| 820 | delay = 20000; | ||
| 821 | trf->powering_up = false; | ||
| 822 | } else { | ||
| 823 | delay = 5000; | ||
| 824 | } | ||
| 825 | |||
| 826 | usleep_range(delay, delay + 1000); | ||
| 827 | |||
| 828 | ret = trf7970a_init(trf); | ||
| 829 | if (ret) | ||
| 830 | trf7970a_switch_rf_off(trf); | ||
| 831 | else | ||
| 832 | trf->state = TRF7970A_ST_IDLE; | ||
| 833 | |||
| 834 | return ret; | ||
| 835 | } | 814 | } |
| 836 | 815 | ||
| 837 | static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) | 816 | static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) |
| 838 | { | 817 | { |
| 839 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); | 818 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); |
| 840 | int ret = 0; | ||
| 841 | 819 | ||
| 842 | dev_dbg(trf->dev, "Switching RF - state: %d, on: %d\n", trf->state, on); | 820 | dev_dbg(trf->dev, "Switching RF - state: %d, on: %d\n", trf->state, on); |
| 843 | 821 | ||
| @@ -846,7 +824,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) | |||
| 846 | if (on) { | 824 | if (on) { |
| 847 | switch (trf->state) { | 825 | switch (trf->state) { |
| 848 | case TRF7970A_ST_OFF: | 826 | case TRF7970A_ST_OFF: |
| 849 | ret = trf7970a_switch_rf_on(trf); | 827 | trf7970a_switch_rf_on(trf); |
| 850 | break; | 828 | break; |
| 851 | case TRF7970A_ST_IDLE: | 829 | case TRF7970A_ST_IDLE: |
| 852 | case TRF7970A_ST_IDLE_RX_BLOCKED: | 830 | case TRF7970A_ST_IDLE_RX_BLOCKED: |
| @@ -871,7 +849,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) | |||
| 871 | } | 849 | } |
| 872 | 850 | ||
| 873 | mutex_unlock(&trf->lock); | 851 | mutex_unlock(&trf->lock); |
| 874 | return ret; | 852 | return 0; |
| 875 | } | 853 | } |
| 876 | 854 | ||
| 877 | static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech) | 855 | static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech) |
| @@ -882,10 +860,16 @@ static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech) | |||
| 882 | 860 | ||
| 883 | switch (tech) { | 861 | switch (tech) { |
| 884 | case NFC_DIGITAL_RF_TECH_106A: | 862 | case NFC_DIGITAL_RF_TECH_106A: |
| 885 | trf->iso_ctrl = TRF7970A_ISO_CTRL_14443A_106; | 863 | trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443A_106; |
| 864 | trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_OOK; | ||
| 865 | break; | ||
| 866 | case NFC_DIGITAL_RF_TECH_106B: | ||
| 867 | trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_14443B_106; | ||
| 868 | trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_ASK10; | ||
| 886 | break; | 869 | break; |
| 887 | case NFC_DIGITAL_RF_TECH_ISO15693: | 870 | case NFC_DIGITAL_RF_TECH_ISO15693: |
| 888 | trf->iso_ctrl = TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648; | 871 | trf->iso_ctrl_tech = TRF7970A_ISO_CTRL_15693_SGL_1OF4_2648; |
| 872 | trf->modulator_sys_clk_ctrl = TRF7970A_MODULATOR_DEPTH_OOK; | ||
| 889 | break; | 873 | break; |
| 890 | default: | 874 | default: |
| 891 | dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech); | 875 | dev_dbg(trf->dev, "Unsupported rf technology: %d\n", tech); |
| @@ -899,24 +883,29 @@ static int trf7970a_config_rf_tech(struct trf7970a *trf, int tech) | |||
| 899 | 883 | ||
| 900 | static int trf7970a_config_framing(struct trf7970a *trf, int framing) | 884 | static int trf7970a_config_framing(struct trf7970a *trf, int framing) |
| 901 | { | 885 | { |
| 886 | u8 iso_ctrl = trf->iso_ctrl_tech; | ||
| 887 | int ret; | ||
| 888 | |||
| 902 | dev_dbg(trf->dev, "framing: %d\n", framing); | 889 | dev_dbg(trf->dev, "framing: %d\n", framing); |
| 903 | 890 | ||
| 904 | switch (framing) { | 891 | switch (framing) { |
| 905 | case NFC_DIGITAL_FRAMING_NFCA_SHORT: | 892 | case NFC_DIGITAL_FRAMING_NFCA_SHORT: |
| 906 | case NFC_DIGITAL_FRAMING_NFCA_STANDARD: | 893 | case NFC_DIGITAL_FRAMING_NFCA_STANDARD: |
| 907 | trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC; | 894 | trf->tx_cmd = TRF7970A_CMD_TRANSMIT_NO_CRC; |
| 908 | trf->iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; | 895 | iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; |
| 909 | break; | 896 | break; |
| 910 | case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A: | 897 | case NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A: |
| 911 | case NFC_DIGITAL_FRAMING_NFCA_T4T: | 898 | case NFC_DIGITAL_FRAMING_NFCA_T4T: |
| 899 | case NFC_DIGITAL_FRAMING_NFCB: | ||
| 900 | case NFC_DIGITAL_FRAMING_NFCB_T4T: | ||
| 912 | case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY: | 901 | case NFC_DIGITAL_FRAMING_ISO15693_INVENTORY: |
| 913 | case NFC_DIGITAL_FRAMING_ISO15693_T5T: | 902 | case NFC_DIGITAL_FRAMING_ISO15693_T5T: |
| 914 | trf->tx_cmd = TRF7970A_CMD_TRANSMIT; | 903 | trf->tx_cmd = TRF7970A_CMD_TRANSMIT; |
| 915 | trf->iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N; | 904 | iso_ctrl &= ~TRF7970A_ISO_CTRL_RX_CRC_N; |
| 916 | break; | 905 | break; |
| 917 | case NFC_DIGITAL_FRAMING_NFCA_T2T: | 906 | case NFC_DIGITAL_FRAMING_NFCA_T2T: |
| 918 | trf->tx_cmd = TRF7970A_CMD_TRANSMIT; | 907 | trf->tx_cmd = TRF7970A_CMD_TRANSMIT; |
| 919 | trf->iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; | 908 | iso_ctrl |= TRF7970A_ISO_CTRL_RX_CRC_N; |
| 920 | break; | 909 | break; |
| 921 | default: | 910 | default: |
| 922 | dev_dbg(trf->dev, "Unsupported Framing: %d\n", framing); | 911 | dev_dbg(trf->dev, "Unsupported Framing: %d\n", framing); |
| @@ -925,24 +914,46 @@ static int trf7970a_config_framing(struct trf7970a *trf, int framing) | |||
| 925 | 914 | ||
| 926 | trf->framing = framing; | 915 | trf->framing = framing; |
| 927 | 916 | ||
| 928 | return trf7970a_write(trf, TRF7970A_ISO_CTRL, trf->iso_ctrl); | 917 | if (iso_ctrl != trf->iso_ctrl) { |
| 918 | ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); | ||
| 919 | if (ret) | ||
| 920 | return ret; | ||
| 921 | |||
| 922 | trf->iso_ctrl = iso_ctrl; | ||
| 923 | |||
| 924 | ret = trf7970a_write(trf, TRF7970A_MODULATOR_SYS_CLK_CTRL, | ||
| 925 | trf->modulator_sys_clk_ctrl); | ||
| 926 | if (ret) | ||
| 927 | return ret; | ||
| 928 | } | ||
| 929 | |||
| 930 | if (!(trf->chip_status_ctrl & TRF7970A_CHIP_STATUS_RF_ON)) { | ||
| 931 | ret = trf7970a_write(trf, TRF7970A_CHIP_STATUS_CTRL, | ||
| 932 | trf->chip_status_ctrl | | ||
| 933 | TRF7970A_CHIP_STATUS_RF_ON); | ||
| 934 | if (ret) | ||
| 935 | return ret; | ||
| 936 | |||
| 937 | trf->chip_status_ctrl |= TRF7970A_CHIP_STATUS_RF_ON; | ||
| 938 | |||
| 939 | usleep_range(5000, 6000); | ||
| 940 | } | ||
| 941 | |||
| 942 | return 0; | ||
| 929 | } | 943 | } |
| 930 | 944 | ||
| 931 | static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type, | 945 | static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type, |
| 932 | int param) | 946 | int param) |
| 933 | { | 947 | { |
| 934 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); | 948 | struct trf7970a *trf = nfc_digital_get_drvdata(ddev); |
| 935 | int ret = 0; | 949 | int ret; |
| 936 | 950 | ||
| 937 | dev_dbg(trf->dev, "Configure hw - type: %d, param: %d\n", type, param); | 951 | dev_dbg(trf->dev, "Configure hw - type: %d, param: %d\n", type, param); |
| 938 | 952 | ||
| 939 | mutex_lock(&trf->lock); | 953 | mutex_lock(&trf->lock); |
| 940 | 954 | ||
| 941 | if (trf->state == TRF7970A_ST_OFF) { | 955 | if (trf->state == TRF7970A_ST_OFF) |
| 942 | ret = trf7970a_switch_rf_on(trf); | 956 | trf7970a_switch_rf_on(trf); |
| 943 | if (ret) | ||
| 944 | goto err_out; | ||
| 945 | } | ||
| 946 | 957 | ||
| 947 | switch (type) { | 958 | switch (type) { |
| 948 | case NFC_DIGITAL_CONFIG_RF_TECH: | 959 | case NFC_DIGITAL_CONFIG_RF_TECH: |
| @@ -956,7 +967,6 @@ static int trf7970a_in_configure_hw(struct nfc_digital_dev *ddev, int type, | |||
| 956 | ret = -EINVAL; | 967 | ret = -EINVAL; |
| 957 | } | 968 | } |
| 958 | 969 | ||
| 959 | err_out: | ||
| 960 | mutex_unlock(&trf->lock); | 970 | mutex_unlock(&trf->lock); |
| 961 | return ret; | 971 | return ret; |
| 962 | } | 972 | } |
| @@ -1191,7 +1201,18 @@ static void trf7970a_abort_cmd(struct nfc_digital_dev *ddev) | |||
| 1191 | dev_dbg(trf->dev, "Abort process initiated\n"); | 1201 | dev_dbg(trf->dev, "Abort process initiated\n"); |
| 1192 | 1202 | ||
| 1193 | mutex_lock(&trf->lock); | 1203 | mutex_lock(&trf->lock); |
| 1194 | trf->aborting = true; | 1204 | |
| 1205 | switch (trf->state) { | ||
| 1206 | case TRF7970A_ST_WAIT_FOR_TX_FIFO: | ||
| 1207 | case TRF7970A_ST_WAIT_FOR_RX_DATA: | ||
| 1208 | case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: | ||
| 1209 | case TRF7970A_ST_WAIT_TO_ISSUE_EOF: | ||
| 1210 | trf->aborting = true; | ||
| 1211 | break; | ||
| 1212 | default: | ||
| 1213 | break; | ||
| 1214 | } | ||
| 1215 | |||
| 1195 | mutex_unlock(&trf->lock); | 1216 | mutex_unlock(&trf->lock); |
| 1196 | } | 1217 | } |
| 1197 | 1218 | ||
| @@ -1206,12 +1227,25 @@ static struct nfc_digital_ops trf7970a_nfc_ops = { | |||
| 1206 | .abort_cmd = trf7970a_abort_cmd, | 1227 | .abort_cmd = trf7970a_abort_cmd, |
| 1207 | }; | 1228 | }; |
| 1208 | 1229 | ||
| 1230 | static int trf7970a_get_autosuspend_delay(struct device_node *np) | ||
| 1231 | { | ||
| 1232 | int autosuspend_delay, ret; | ||
| 1233 | |||
| 1234 | ret = of_property_read_u32(np, "autosuspend-delay", &autosuspend_delay); | ||
| 1235 | if (ret) | ||
| 1236 | autosuspend_delay = TRF7970A_AUTOSUSPEND_DELAY; | ||
| 1237 | |||
| 1238 | of_node_put(np); | ||
| 1239 | |||
| 1240 | return autosuspend_delay; | ||
| 1241 | } | ||
| 1242 | |||
| 1209 | static int trf7970a_probe(struct spi_device *spi) | 1243 | static int trf7970a_probe(struct spi_device *spi) |
| 1210 | { | 1244 | { |
| 1211 | struct device_node *np = spi->dev.of_node; | 1245 | struct device_node *np = spi->dev.of_node; |
| 1212 | const struct spi_device_id *id = spi_get_device_id(spi); | 1246 | const struct spi_device_id *id = spi_get_device_id(spi); |
| 1213 | struct trf7970a *trf; | 1247 | struct trf7970a *trf; |
| 1214 | int ret; | 1248 | int uvolts, autosuspend_delay, ret; |
| 1215 | 1249 | ||
| 1216 | if (!np) { | 1250 | if (!np) { |
| 1217 | dev_err(&spi->dev, "No Device Tree entry\n"); | 1251 | dev_err(&spi->dev, "No Device Tree entry\n"); |
| @@ -1281,7 +1315,10 @@ static int trf7970a_probe(struct spi_device *spi) | |||
| 1281 | goto err_destroy_lock; | 1315 | goto err_destroy_lock; |
| 1282 | } | 1316 | } |
| 1283 | 1317 | ||
| 1284 | trf->powering_up = true; | 1318 | uvolts = regulator_get_voltage(trf->regulator); |
| 1319 | |||
| 1320 | if (uvolts > 4000000) | ||
| 1321 | trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3; | ||
| 1285 | 1322 | ||
| 1286 | trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops, | 1323 | trf->ddev = nfc_digital_allocate_device(&trf7970a_nfc_ops, |
| 1287 | TRF7970A_SUPPORTED_PROTOCOLS, | 1324 | TRF7970A_SUPPORTED_PROTOCOLS, |
| @@ -1297,6 +1334,12 @@ static int trf7970a_probe(struct spi_device *spi) | |||
| 1297 | nfc_digital_set_drvdata(trf->ddev, trf); | 1334 | nfc_digital_set_drvdata(trf->ddev, trf); |
| 1298 | spi_set_drvdata(spi, trf); | 1335 | spi_set_drvdata(spi, trf); |
| 1299 | 1336 | ||
| 1337 | autosuspend_delay = trf7970a_get_autosuspend_delay(np); | ||
| 1338 | |||
| 1339 | pm_runtime_set_autosuspend_delay(trf->dev, autosuspend_delay); | ||
| 1340 | pm_runtime_use_autosuspend(trf->dev); | ||
| 1341 | pm_runtime_enable(trf->dev); | ||
| 1342 | |||
| 1300 | ret = nfc_digital_register_device(trf->ddev); | 1343 | ret = nfc_digital_register_device(trf->ddev); |
| 1301 | if (ret) { | 1344 | if (ret) { |
| 1302 | dev_err(trf->dev, "Can't register NFC digital device: %d\n", | 1345 | dev_err(trf->dev, "Can't register NFC digital device: %d\n", |
| @@ -1307,6 +1350,7 @@ static int trf7970a_probe(struct spi_device *spi) | |||
| 1307 | return 0; | 1350 | return 0; |
| 1308 | 1351 | ||
| 1309 | err_free_ddev: | 1352 | err_free_ddev: |
| 1353 | pm_runtime_disable(trf->dev); | ||
| 1310 | nfc_digital_free_device(trf->ddev); | 1354 | nfc_digital_free_device(trf->ddev); |
| 1311 | err_disable_regulator: | 1355 | err_disable_regulator: |
| 1312 | regulator_disable(trf->regulator); | 1356 | regulator_disable(trf->regulator); |
| @@ -1321,15 +1365,16 @@ static int trf7970a_remove(struct spi_device *spi) | |||
| 1321 | 1365 | ||
| 1322 | mutex_lock(&trf->lock); | 1366 | mutex_lock(&trf->lock); |
| 1323 | 1367 | ||
| 1324 | trf7970a_switch_rf_off(trf); | ||
| 1325 | trf7970a_init(trf); | ||
| 1326 | |||
| 1327 | switch (trf->state) { | 1368 | switch (trf->state) { |
| 1328 | case TRF7970A_ST_WAIT_FOR_TX_FIFO: | 1369 | case TRF7970A_ST_WAIT_FOR_TX_FIFO: |
| 1329 | case TRF7970A_ST_WAIT_FOR_RX_DATA: | 1370 | case TRF7970A_ST_WAIT_FOR_RX_DATA: |
| 1330 | case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: | 1371 | case TRF7970A_ST_WAIT_FOR_RX_DATA_CONT: |
| 1331 | case TRF7970A_ST_WAIT_TO_ISSUE_EOF: | 1372 | case TRF7970A_ST_WAIT_TO_ISSUE_EOF: |
| 1332 | trf7970a_send_err_upstream(trf, -ECANCELED); | 1373 | trf7970a_send_err_upstream(trf, -ECANCELED); |
| 1374 | /* FALLTHROUGH */ | ||
| 1375 | case TRF7970A_ST_IDLE: | ||
| 1376 | case TRF7970A_ST_IDLE_RX_BLOCKED: | ||
| 1377 | pm_runtime_put_sync(trf->dev); | ||
| 1333 | break; | 1378 | break; |
| 1334 | default: | 1379 | default: |
| 1335 | break; | 1380 | break; |
| @@ -1337,6 +1382,8 @@ static int trf7970a_remove(struct spi_device *spi) | |||
| 1337 | 1382 | ||
| 1338 | mutex_unlock(&trf->lock); | 1383 | mutex_unlock(&trf->lock); |
| 1339 | 1384 | ||
| 1385 | pm_runtime_disable(trf->dev); | ||
| 1386 | |||
| 1340 | nfc_digital_unregister_device(trf->ddev); | 1387 | nfc_digital_unregister_device(trf->ddev); |
| 1341 | nfc_digital_free_device(trf->ddev); | 1388 | nfc_digital_free_device(trf->ddev); |
| 1342 | 1389 | ||
| @@ -1347,6 +1394,70 @@ static int trf7970a_remove(struct spi_device *spi) | |||
| 1347 | return 0; | 1394 | return 0; |
| 1348 | } | 1395 | } |
| 1349 | 1396 | ||
| 1397 | #ifdef CONFIG_PM_RUNTIME | ||
| 1398 | static int trf7970a_pm_runtime_suspend(struct device *dev) | ||
| 1399 | { | ||
| 1400 | struct spi_device *spi = container_of(dev, struct spi_device, dev); | ||
| 1401 | struct trf7970a *trf = spi_get_drvdata(spi); | ||
| 1402 | int ret; | ||
| 1403 | |||
| 1404 | dev_dbg(dev, "Runtime suspend\n"); | ||
| 1405 | |||
| 1406 | if (trf->state != TRF7970A_ST_OFF) { | ||
| 1407 | dev_dbg(dev, "Can't suspend - not in OFF state (%d)\n", | ||
| 1408 | trf->state); | ||
| 1409 | return -EBUSY; | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | gpio_set_value(trf->en_gpio, 0); | ||
| 1413 | gpio_set_value(trf->en2_gpio, 0); | ||
| 1414 | |||
| 1415 | ret = regulator_disable(trf->regulator); | ||
| 1416 | if (ret) | ||
| 1417 | dev_err(dev, "%s - Can't disable VIN: %d\n", __func__, ret); | ||
| 1418 | |||
| 1419 | return ret; | ||
| 1420 | } | ||
| 1421 | |||
| 1422 | static int trf7970a_pm_runtime_resume(struct device *dev) | ||
| 1423 | { | ||
| 1424 | struct spi_device *spi = container_of(dev, struct spi_device, dev); | ||
| 1425 | struct trf7970a *trf = spi_get_drvdata(spi); | ||
| 1426 | int ret; | ||
| 1427 | |||
| 1428 | dev_dbg(dev, "Runtime resume\n"); | ||
| 1429 | |||
| 1430 | ret = regulator_enable(trf->regulator); | ||
| 1431 | if (ret) { | ||
| 1432 | dev_err(dev, "%s - Can't enable VIN: %d\n", __func__, ret); | ||
| 1433 | return ret; | ||
| 1434 | } | ||
| 1435 | |||
| 1436 | usleep_range(5000, 6000); | ||
| 1437 | |||
| 1438 | gpio_set_value(trf->en2_gpio, 1); | ||
| 1439 | usleep_range(1000, 2000); | ||
| 1440 | gpio_set_value(trf->en_gpio, 1); | ||
| 1441 | |||
| 1442 | usleep_range(20000, 21000); | ||
| 1443 | |||
| 1444 | ret = trf7970a_init(trf); | ||
| 1445 | if (ret) { | ||
| 1446 | dev_err(dev, "%s - Can't initialize: %d\n", __func__, ret); | ||
| 1447 | return ret; | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | pm_runtime_mark_last_busy(dev); | ||
| 1451 | |||
| 1452 | return 0; | ||
| 1453 | } | ||
| 1454 | #endif | ||
| 1455 | |||
| 1456 | static const struct dev_pm_ops trf7970a_pm_ops = { | ||
| 1457 | SET_RUNTIME_PM_OPS(trf7970a_pm_runtime_suspend, | ||
| 1458 | trf7970a_pm_runtime_resume, NULL) | ||
| 1459 | }; | ||
| 1460 | |||
| 1350 | static const struct spi_device_id trf7970a_id_table[] = { | 1461 | static const struct spi_device_id trf7970a_id_table[] = { |
| 1351 | { "trf7970a", TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA }, | 1462 | { "trf7970a", TRF7970A_QUIRK_IRQ_STATUS_READ_ERRATA }, |
| 1352 | { } | 1463 | { } |
| @@ -1360,6 +1471,7 @@ static struct spi_driver trf7970a_spi_driver = { | |||
| 1360 | .driver = { | 1471 | .driver = { |
| 1361 | .name = "trf7970a", | 1472 | .name = "trf7970a", |
| 1362 | .owner = THIS_MODULE, | 1473 | .owner = THIS_MODULE, |
| 1474 | .pm = &trf7970a_pm_ops, | ||
| 1363 | }, | 1475 | }, |
| 1364 | }; | 1476 | }; |
| 1365 | 1477 | ||
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 7c6e277cdd1f..2fe922bfade8 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c | |||
| @@ -88,6 +88,27 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi | |||
| 88 | return 0; | 88 | return 0; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | static int of_mdio_parse_addr(struct device *dev, const struct device_node *np) | ||
| 92 | { | ||
| 93 | u32 addr; | ||
| 94 | int ret; | ||
| 95 | |||
| 96 | ret = of_property_read_u32(np, "reg", &addr); | ||
| 97 | if (ret < 0) { | ||
| 98 | dev_err(dev, "%s has invalid PHY address\n", np->full_name); | ||
| 99 | return ret; | ||
| 100 | } | ||
| 101 | |||
| 102 | /* A PHY must have a reg property in the range [0-31] */ | ||
| 103 | if (addr >= PHY_MAX_ADDR) { | ||
| 104 | dev_err(dev, "%s PHY address %i is too large\n", | ||
| 105 | np->full_name, addr); | ||
| 106 | return -EINVAL; | ||
| 107 | } | ||
| 108 | |||
| 109 | return addr; | ||
| 110 | } | ||
| 111 | |||
| 91 | /** | 112 | /** |
| 92 | * of_mdiobus_register - Register mii_bus and create PHYs from the device tree | 113 | * of_mdiobus_register - Register mii_bus and create PHYs from the device tree |
| 93 | * @mdio: pointer to mii_bus structure | 114 | * @mdio: pointer to mii_bus structure |
| @@ -102,7 +123,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) | |||
| 102 | const __be32 *paddr; | 123 | const __be32 *paddr; |
| 103 | u32 addr; | 124 | u32 addr; |
| 104 | bool scanphys = false; | 125 | bool scanphys = false; |
| 105 | int rc, i, len; | 126 | int rc, i; |
| 106 | 127 | ||
| 107 | /* Mask out all PHYs from auto probing. Instead the PHYs listed in | 128 | /* Mask out all PHYs from auto probing. Instead the PHYs listed in |
| 108 | * the device tree are populated after the bus has been registered */ | 129 | * the device tree are populated after the bus has been registered */ |
| @@ -122,19 +143,9 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) | |||
| 122 | 143 | ||
| 123 | /* Loop over the child nodes and register a phy_device for each one */ | 144 | /* Loop over the child nodes and register a phy_device for each one */ |
| 124 | for_each_available_child_of_node(np, child) { | 145 | for_each_available_child_of_node(np, child) { |
| 125 | /* A PHY must have a reg property in the range [0-31] */ | 146 | addr = of_mdio_parse_addr(&mdio->dev, child); |
| 126 | paddr = of_get_property(child, "reg", &len); | 147 | if (addr < 0) { |
| 127 | if (!paddr || len < sizeof(*paddr)) { | ||
| 128 | scanphys = true; | 148 | scanphys = true; |
| 129 | dev_err(&mdio->dev, "%s has invalid PHY address\n", | ||
| 130 | child->full_name); | ||
| 131 | continue; | ||
| 132 | } | ||
| 133 | |||
| 134 | addr = be32_to_cpup(paddr); | ||
| 135 | if (addr >= PHY_MAX_ADDR) { | ||
| 136 | dev_err(&mdio->dev, "%s PHY address %i is too large\n", | ||
| 137 | child->full_name, addr); | ||
| 138 | continue; | 149 | continue; |
| 139 | } | 150 | } |
| 140 | 151 | ||
| @@ -149,7 +160,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) | |||
| 149 | /* auto scan for PHYs with empty reg property */ | 160 | /* auto scan for PHYs with empty reg property */ |
| 150 | for_each_available_child_of_node(np, child) { | 161 | for_each_available_child_of_node(np, child) { |
| 151 | /* Skip PHYs with reg property set */ | 162 | /* Skip PHYs with reg property set */ |
| 152 | paddr = of_get_property(child, "reg", &len); | 163 | paddr = of_get_property(child, "reg", NULL); |
| 153 | if (paddr) | 164 | if (paddr) |
| 154 | continue; | 165 | continue; |
| 155 | 166 | ||
| @@ -172,6 +183,39 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) | |||
| 172 | } | 183 | } |
| 173 | EXPORT_SYMBOL(of_mdiobus_register); | 184 | EXPORT_SYMBOL(of_mdiobus_register); |
| 174 | 185 | ||
| 186 | /** | ||
| 187 | * of_mdiobus_link_phydev - Find a device node for a phy | ||
| 188 | * @mdio: pointer to mii_bus structure | ||
| 189 | * @phydev: phydev for which the of_node pointer should be set | ||
| 190 | * | ||
| 191 | * Walk the list of subnodes of a mdio bus and look for a node that matches the | ||
| 192 | * phy's address with its 'reg' property. If found, set the of_node pointer for | ||
| 193 | * the phy. This allows auto-probed pyh devices to be supplied with information | ||
| 194 | * passed in via DT. | ||
| 195 | */ | ||
| 196 | void of_mdiobus_link_phydev(struct mii_bus *mdio, | ||
| 197 | struct phy_device *phydev) | ||
| 198 | { | ||
| 199 | struct device *dev = &phydev->dev; | ||
| 200 | struct device_node *child; | ||
| 201 | |||
| 202 | if (dev->of_node || !mdio->dev.of_node) | ||
| 203 | return; | ||
| 204 | |||
| 205 | for_each_available_child_of_node(mdio->dev.of_node, child) { | ||
| 206 | int addr; | ||
| 207 | |||
| 208 | addr = of_mdio_parse_addr(&mdio->dev, child); | ||
| 209 | if (addr < 0) | ||
| 210 | continue; | ||
| 211 | |||
| 212 | if (addr == phydev->addr) { | ||
| 213 | dev->of_node = child; | ||
| 214 | return; | ||
| 215 | } | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 175 | /* Helper function for of_phy_find_device */ | 219 | /* Helper function for of_phy_find_device */ |
| 176 | static int of_phy_match(struct device *dev, void *phy_np) | 220 | static int of_phy_match(struct device *dev, void *phy_np) |
| 177 | { | 221 | { |
diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c index 985b5dcbdac8..6bcfbbb20f04 100644 --- a/drivers/s390/net/ctcm_sysfs.c +++ b/drivers/s390/net/ctcm_sysfs.c | |||
| @@ -34,8 +34,9 @@ static ssize_t ctcm_buffer_write(struct device *dev, | |||
| 34 | struct device_attribute *attr, const char *buf, size_t count) | 34 | struct device_attribute *attr, const char *buf, size_t count) |
| 35 | { | 35 | { |
| 36 | struct net_device *ndev; | 36 | struct net_device *ndev; |
| 37 | int bs1; | 37 | unsigned int bs1; |
| 38 | struct ctcm_priv *priv = dev_get_drvdata(dev); | 38 | struct ctcm_priv *priv = dev_get_drvdata(dev); |
| 39 | int rc; | ||
| 39 | 40 | ||
| 40 | ndev = priv->channel[CTCM_READ]->netdev; | 41 | ndev = priv->channel[CTCM_READ]->netdev; |
| 41 | if (!(priv && priv->channel[CTCM_READ] && ndev)) { | 42 | if (!(priv && priv->channel[CTCM_READ] && ndev)) { |
| @@ -43,7 +44,9 @@ static ssize_t ctcm_buffer_write(struct device *dev, | |||
| 43 | return -ENODEV; | 44 | return -ENODEV; |
| 44 | } | 45 | } |
| 45 | 46 | ||
| 46 | sscanf(buf, "%u", &bs1); | 47 | rc = sscanf(buf, "%u", &bs1); |
| 48 | if (rc != 1) | ||
| 49 | goto einval; | ||
| 47 | if (bs1 > CTCM_BUFSIZE_LIMIT) | 50 | if (bs1 > CTCM_BUFSIZE_LIMIT) |
| 48 | goto einval; | 51 | goto einval; |
| 49 | if (bs1 < (576 + LL_HEADER_LENGTH + 2)) | 52 | if (bs1 < (576 + LL_HEADER_LENGTH + 2)) |
| @@ -143,13 +146,14 @@ static ssize_t ctcm_proto_show(struct device *dev, | |||
| 143 | static ssize_t ctcm_proto_store(struct device *dev, | 146 | static ssize_t ctcm_proto_store(struct device *dev, |
| 144 | struct device_attribute *attr, const char *buf, size_t count) | 147 | struct device_attribute *attr, const char *buf, size_t count) |
| 145 | { | 148 | { |
| 146 | int value; | 149 | int value, rc; |
| 147 | struct ctcm_priv *priv = dev_get_drvdata(dev); | 150 | struct ctcm_priv *priv = dev_get_drvdata(dev); |
| 148 | 151 | ||
| 149 | if (!priv) | 152 | if (!priv) |
| 150 | return -ENODEV; | 153 | return -ENODEV; |
| 151 | sscanf(buf, "%u", &value); | 154 | rc = sscanf(buf, "%d", &value); |
| 152 | if (!((value == CTCM_PROTO_S390) || | 155 | if ((rc != 1) || |
| 156 | !((value == CTCM_PROTO_S390) || | ||
| 153 | (value == CTCM_PROTO_LINUX) || | 157 | (value == CTCM_PROTO_LINUX) || |
| 154 | (value == CTCM_PROTO_MPC) || | 158 | (value == CTCM_PROTO_MPC) || |
| 155 | (value == CTCM_PROTO_OS390))) | 159 | (value == CTCM_PROTO_OS390))) |
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 8d5d96969c39..0a7d87c372b8 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
| @@ -1943,14 +1943,16 @@ static ssize_t | |||
| 1943 | lcs_portno_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1943 | lcs_portno_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
| 1944 | { | 1944 | { |
| 1945 | struct lcs_card *card; | 1945 | struct lcs_card *card; |
| 1946 | int value; | 1946 | int value, rc; |
| 1947 | 1947 | ||
| 1948 | card = dev_get_drvdata(dev); | 1948 | card = dev_get_drvdata(dev); |
| 1949 | 1949 | ||
| 1950 | if (!card) | 1950 | if (!card) |
| 1951 | return 0; | 1951 | return 0; |
| 1952 | 1952 | ||
| 1953 | sscanf(buf, "%u", &value); | 1953 | rc = sscanf(buf, "%d", &value); |
| 1954 | if (rc != 1) | ||
| 1955 | return -EINVAL; | ||
| 1954 | /* TODO: sanity checks */ | 1956 | /* TODO: sanity checks */ |
| 1955 | card->portno = value; | 1957 | card->portno = value; |
| 1956 | 1958 | ||
| @@ -1997,14 +1999,17 @@ static ssize_t | |||
| 1997 | lcs_timeout_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1999 | lcs_timeout_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
| 1998 | { | 2000 | { |
| 1999 | struct lcs_card *card; | 2001 | struct lcs_card *card; |
| 2000 | int value; | 2002 | unsigned int value; |
| 2003 | int rc; | ||
| 2001 | 2004 | ||
| 2002 | card = dev_get_drvdata(dev); | 2005 | card = dev_get_drvdata(dev); |
| 2003 | 2006 | ||
| 2004 | if (!card) | 2007 | if (!card) |
| 2005 | return 0; | 2008 | return 0; |
| 2006 | 2009 | ||
| 2007 | sscanf(buf, "%u", &value); | 2010 | rc = sscanf(buf, "%u", &value); |
| 2011 | if (rc != 1) | ||
| 2012 | return -EINVAL; | ||
| 2008 | /* TODO: sanity checks */ | 2013 | /* TODO: sanity checks */ |
| 2009 | card->lancmd_timeout = value; | 2014 | card->lancmd_timeout = value; |
| 2010 | 2015 | ||
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 34993009a9e1..549e9fd5bfdc 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
| @@ -1013,7 +1013,7 @@ static long __qeth_check_irb_error(struct ccw_device *cdev, | |||
| 1013 | 1013 | ||
| 1014 | card = CARD_FROM_CDEV(cdev); | 1014 | card = CARD_FROM_CDEV(cdev); |
| 1015 | 1015 | ||
| 1016 | if (!IS_ERR(irb)) | 1016 | if (!card || !IS_ERR(irb)) |
| 1017 | return 0; | 1017 | return 0; |
| 1018 | 1018 | ||
| 1019 | switch (PTR_ERR(irb)) { | 1019 | switch (PTR_ERR(irb)) { |
| @@ -1029,7 +1029,7 @@ static long __qeth_check_irb_error(struct ccw_device *cdev, | |||
| 1029 | QETH_CARD_TEXT(card, 2, "ckirberr"); | 1029 | QETH_CARD_TEXT(card, 2, "ckirberr"); |
| 1030 | QETH_CARD_TEXT_(card, 2, " rc%d", -ETIMEDOUT); | 1030 | QETH_CARD_TEXT_(card, 2, " rc%d", -ETIMEDOUT); |
| 1031 | if (intparm == QETH_RCD_PARM) { | 1031 | if (intparm == QETH_RCD_PARM) { |
| 1032 | if (card && (card->data.ccwdev == cdev)) { | 1032 | if (card->data.ccwdev == cdev) { |
| 1033 | card->data.state = CH_STATE_DOWN; | 1033 | card->data.state = CH_STATE_DOWN; |
| 1034 | wake_up(&card->wait_q); | 1034 | wake_up(&card->wait_q); |
| 1035 | } | 1035 | } |
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index c58f82af3658..14e0b5810e8c 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
| @@ -63,7 +63,7 @@ void qeth_l3_ipaddr4_to_string(const __u8 *addr, char *buf) | |||
| 63 | int qeth_l3_string_to_ipaddr4(const char *buf, __u8 *addr) | 63 | int qeth_l3_string_to_ipaddr4(const char *buf, __u8 *addr) |
| 64 | { | 64 | { |
| 65 | int count = 0, rc = 0; | 65 | int count = 0, rc = 0; |
| 66 | int in[4]; | 66 | unsigned int in[4]; |
| 67 | char c; | 67 | char c; |
| 68 | 68 | ||
| 69 | rc = sscanf(buf, "%u.%u.%u.%u%c", | 69 | rc = sscanf(buf, "%u.%u.%u.%u%c", |
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index f76f95c29617..723319ee08f3 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c | |||
| @@ -84,7 +84,7 @@ static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data) | |||
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | static int prism2_domibset_pstr32(wlandevice_t *wlandev, | 86 | static int prism2_domibset_pstr32(wlandevice_t *wlandev, |
| 87 | u32 did, u8 len, u8 *data) | 87 | u32 did, u8 len, const u8 *data) |
| 88 | { | 88 | { |
| 89 | struct p80211msg_dot11req_mibset msg; | 89 | struct p80211msg_dot11req_mibset msg; |
| 90 | p80211item_pstr32_t *mibitem = | 90 | p80211item_pstr32_t *mibitem = |
| @@ -298,7 +298,7 @@ static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, | |||
| 298 | 298 | ||
| 299 | 299 | ||
| 300 | static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, | 300 | static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, |
| 301 | u8 *mac, struct station_info *sinfo) | 301 | const u8 *mac, struct station_info *sinfo) |
| 302 | { | 302 | { |
| 303 | wlandevice_t *wlandev = dev->ml_priv; | 303 | wlandevice_t *wlandev = dev->ml_priv; |
| 304 | struct p80211msg_lnxreq_commsquality quality; | 304 | struct p80211msg_lnxreq_commsquality quality; |
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h index 8598f8eacb20..a495a959e8a7 100644 --- a/include/linux/ath9k_platform.h +++ b/include/linux/ath9k_platform.h | |||
| @@ -36,6 +36,8 @@ struct ath9k_platform_data { | |||
| 36 | 36 | ||
| 37 | int (*get_mac_revision)(void); | 37 | int (*get_mac_revision)(void); |
| 38 | int (*external_reset)(void); | 38 | int (*external_reset)(void); |
| 39 | |||
| 40 | bool use_eeprom; | ||
| 39 | }; | 41 | }; |
| 40 | 42 | ||
| 41 | #endif /* _LINUX_ATH9K_PLATFORM_H */ | 43 | #endif /* _LINUX_ATH9K_PLATFORM_H */ |
diff --git a/include/linux/crc7.h b/include/linux/crc7.h index 1786e772d5c6..d590765106f3 100644 --- a/include/linux/crc7.h +++ b/include/linux/crc7.h | |||
| @@ -2,13 +2,13 @@ | |||
| 2 | #define _LINUX_CRC7_H | 2 | #define _LINUX_CRC7_H |
| 3 | #include <linux/types.h> | 3 | #include <linux/types.h> |
| 4 | 4 | ||
| 5 | extern const u8 crc7_syndrome_table[256]; | 5 | extern const u8 crc7_be_syndrome_table[256]; |
| 6 | 6 | ||
| 7 | static inline u8 crc7_byte(u8 crc, u8 data) | 7 | static inline u8 crc7_be_byte(u8 crc, u8 data) |
| 8 | { | 8 | { |
| 9 | return crc7_syndrome_table[(crc << 1) ^ data]; | 9 | return crc7_be_syndrome_table[crc ^ data]; |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | extern u8 crc7(u8 crc, const u8 *buffer, size_t len); | 12 | extern u8 crc7_be(u8 crc, const u8 *buffer, size_t len); |
| 13 | 13 | ||
| 14 | #endif | 14 | #endif |
diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h index d449018d0726..a70c9493d55a 100644 --- a/include/linux/of_mdio.h +++ b/include/linux/of_mdio.h | |||
| @@ -25,6 +25,9 @@ struct phy_device *of_phy_attach(struct net_device *dev, | |||
| 25 | 25 | ||
| 26 | extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np); | 26 | extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np); |
| 27 | 27 | ||
| 28 | extern void of_mdiobus_link_phydev(struct mii_bus *mdio, | ||
| 29 | struct phy_device *phydev); | ||
| 30 | |||
| 28 | #else /* CONFIG_OF */ | 31 | #else /* CONFIG_OF */ |
| 29 | static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) | 32 | static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) |
| 30 | { | 33 | { |
| @@ -60,6 +63,11 @@ static inline struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np) | |||
| 60 | { | 63 | { |
| 61 | return NULL; | 64 | return NULL; |
| 62 | } | 65 | } |
| 66 | |||
| 67 | static inline void of_mdiobus_link_phydev(struct mii_bus *mdio, | ||
| 68 | struct phy_device *phydev) | ||
| 69 | { | ||
| 70 | } | ||
| 63 | #endif /* CONFIG_OF */ | 71 | #endif /* CONFIG_OF */ |
| 64 | 72 | ||
| 65 | #if defined(CONFIG_OF) && defined(CONFIG_FIXED_PHY) | 73 | #if defined(CONFIG_OF) && defined(CONFIG_FIXED_PHY) |
diff --git a/include/linux/platform_data/st21nfca.h b/include/linux/platform_data/st21nfca.h new file mode 100644 index 000000000000..1730312398ff --- /dev/null +++ b/include/linux/platform_data/st21nfca.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | /* | ||
| 2 | * Driver include for the ST21NFCA NFC chip. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms and conditions of the GNU General Public License, | ||
| 8 | * version 2, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef _ST21NFCA_HCI_H_ | ||
| 20 | #define _ST21NFCA_HCI_H_ | ||
| 21 | |||
| 22 | #include <linux/i2c.h> | ||
| 23 | |||
| 24 | #define ST21NFCA_HCI_DRIVER_NAME "st21nfca_hci" | ||
| 25 | |||
| 26 | struct st21nfca_nfc_platform_data { | ||
| 27 | unsigned int gpio_irq; | ||
| 28 | unsigned int gpio_ena; | ||
| 29 | unsigned int irq_polarity; | ||
| 30 | }; | ||
| 31 | |||
| 32 | #endif /* _ST21NFCA_HCI_H_ */ | ||
diff --git a/include/linux/rfkill-gpio.h b/include/linux/rfkill-gpio.h index 4d09f6eab359..20bcb55498cd 100644 --- a/include/linux/rfkill-gpio.h +++ b/include/linux/rfkill-gpio.h | |||
| @@ -27,21 +27,11 @@ | |||
| 27 | * struct rfkill_gpio_platform_data - platform data for rfkill gpio device. | 27 | * struct rfkill_gpio_platform_data - platform data for rfkill gpio device. |
| 28 | * for unused gpio's, the expected value is -1. | 28 | * for unused gpio's, the expected value is -1. |
| 29 | * @name: name for the gpio rf kill instance | 29 | * @name: name for the gpio rf kill instance |
| 30 | * @reset_gpio: GPIO which is used for reseting rfkill switch | ||
| 31 | * @shutdown_gpio: GPIO which is used for shutdown of rfkill switch | ||
| 32 | * @power_clk_name: [optional] name of clk to turn off while blocked | ||
| 33 | * @gpio_runtime_close: clean up platform specific gpio configuration | ||
| 34 | * @gpio_runtime_setup: set up platform specific gpio configuration | ||
| 35 | */ | 30 | */ |
| 36 | 31 | ||
| 37 | struct rfkill_gpio_platform_data { | 32 | struct rfkill_gpio_platform_data { |
| 38 | char *name; | 33 | char *name; |
| 39 | int reset_gpio; | ||
| 40 | int shutdown_gpio; | ||
| 41 | const char *power_clk_name; | ||
| 42 | enum rfkill_type type; | 34 | enum rfkill_type type; |
| 43 | void (*gpio_runtime_close)(struct platform_device *); | ||
| 44 | int (*gpio_runtime_setup)(struct platform_device *); | ||
| 45 | }; | 35 | }; |
| 46 | 36 | ||
| 47 | #endif /* __RFKILL_GPIO_H */ | 37 | #endif /* __RFKILL_GPIO_H */ |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 07ef9b82b66d..4568a5cc9ab8 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
| @@ -33,6 +33,7 @@ struct ssb_sprom { | |||
| 33 | u8 et1phyaddr; /* MII address for enet1 */ | 33 | u8 et1phyaddr; /* MII address for enet1 */ |
| 34 | u8 et0mdcport; /* MDIO for enet0 */ | 34 | u8 et0mdcport; /* MDIO for enet0 */ |
| 35 | u8 et1mdcport; /* MDIO for enet1 */ | 35 | u8 et1mdcport; /* MDIO for enet1 */ |
| 36 | u16 dev_id; /* Device ID overriding e.g. PCI ID */ | ||
| 36 | u16 board_rev; /* Board revision number from SPROM. */ | 37 | u16 board_rev; /* Board revision number from SPROM. */ |
| 37 | u16 board_num; /* Board number from SPROM. */ | 38 | u16 board_num; /* Board number from SPROM. */ |
| 38 | u16 board_type; /* Board type from SPROM. */ | 39 | u16 board_type; /* Board type from SPROM. */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f2c318655519..e46c437944f7 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
| @@ -341,8 +341,8 @@ struct vif_params { | |||
| 341 | * @seq_len: length of @seq. | 341 | * @seq_len: length of @seq. |
| 342 | */ | 342 | */ |
| 343 | struct key_params { | 343 | struct key_params { |
| 344 | u8 *key; | 344 | const u8 *key; |
| 345 | u8 *seq; | 345 | const u8 *seq; |
| 346 | int key_len; | 346 | int key_len; |
| 347 | int seq_len; | 347 | int seq_len; |
| 348 | u32 cipher; | 348 | u32 cipher; |
| @@ -458,7 +458,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, | |||
| 458 | */ | 458 | */ |
| 459 | int cfg80211_chandef_dfs_required(struct wiphy *wiphy, | 459 | int cfg80211_chandef_dfs_required(struct wiphy *wiphy, |
| 460 | const struct cfg80211_chan_def *chandef, | 460 | const struct cfg80211_chan_def *chandef, |
| 461 | enum nl80211_iftype); | 461 | enum nl80211_iftype iftype); |
| 462 | 462 | ||
| 463 | /** | 463 | /** |
| 464 | * ieee80211_chandef_rate_flags - returns rate flags for a channel | 464 | * ieee80211_chandef_rate_flags - returns rate flags for a channel |
| @@ -694,8 +694,10 @@ struct cfg80211_ap_settings { | |||
| 694 | * | 694 | * |
| 695 | * @chandef: defines the channel to use after the switch | 695 | * @chandef: defines the channel to use after the switch |
| 696 | * @beacon_csa: beacon data while performing the switch | 696 | * @beacon_csa: beacon data while performing the switch |
| 697 | * @counter_offset_beacon: offset for the counter within the beacon (tail) | 697 | * @counter_offsets_beacon: offsets of the counters within the beacon (tail) |
| 698 | * @counter_offset_presp: offset for the counter within the probe response | 698 | * @counter_offsets_presp: offsets of the counters within the probe response |
| 699 | * @n_counter_offsets_beacon: number of csa counters the beacon (tail) | ||
| 700 | * @n_counter_offsets_presp: number of csa counters in the probe response | ||
| 699 | * @beacon_after: beacon data to be used on the new channel | 701 | * @beacon_after: beacon data to be used on the new channel |
| 700 | * @radar_required: whether radar detection is required on the new channel | 702 | * @radar_required: whether radar detection is required on the new channel |
| 701 | * @block_tx: whether transmissions should be blocked while changing | 703 | * @block_tx: whether transmissions should be blocked while changing |
| @@ -704,7 +706,10 @@ struct cfg80211_ap_settings { | |||
| 704 | struct cfg80211_csa_settings { | 706 | struct cfg80211_csa_settings { |
| 705 | struct cfg80211_chan_def chandef; | 707 | struct cfg80211_chan_def chandef; |
| 706 | struct cfg80211_beacon_data beacon_csa; | 708 | struct cfg80211_beacon_data beacon_csa; |
| 707 | u16 counter_offset_beacon, counter_offset_presp; | 709 | const u16 *counter_offsets_beacon; |
| 710 | const u16 *counter_offsets_presp; | ||
| 711 | unsigned int n_counter_offsets_beacon; | ||
| 712 | unsigned int n_counter_offsets_presp; | ||
| 708 | struct cfg80211_beacon_data beacon_after; | 713 | struct cfg80211_beacon_data beacon_after; |
| 709 | bool radar_required; | 714 | bool radar_required; |
| 710 | bool block_tx; | 715 | bool block_tx; |
| @@ -868,36 +873,38 @@ int cfg80211_check_station_change(struct wiphy *wiphy, | |||
| 868 | * @STATION_INFO_NONPEER_PM: @nonpeer_pm filled | 873 | * @STATION_INFO_NONPEER_PM: @nonpeer_pm filled |
| 869 | * @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled | 874 | * @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled |
| 870 | * @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled | 875 | * @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled |
| 876 | * @STATION_INFO_EXPECTED_THROUGHPUT: @expected_throughput filled | ||
| 871 | */ | 877 | */ |
| 872 | enum station_info_flags { | 878 | enum station_info_flags { |
| 873 | STATION_INFO_INACTIVE_TIME = 1<<0, | 879 | STATION_INFO_INACTIVE_TIME = BIT(0), |
| 874 | STATION_INFO_RX_BYTES = 1<<1, | 880 | STATION_INFO_RX_BYTES = BIT(1), |
| 875 | STATION_INFO_TX_BYTES = 1<<2, | 881 | STATION_INFO_TX_BYTES = BIT(2), |
| 876 | STATION_INFO_LLID = 1<<3, | 882 | STATION_INFO_LLID = BIT(3), |
| 877 | STATION_INFO_PLID = 1<<4, | 883 | STATION_INFO_PLID = BIT(4), |
| 878 | STATION_INFO_PLINK_STATE = 1<<5, | 884 | STATION_INFO_PLINK_STATE = BIT(5), |
| 879 | STATION_INFO_SIGNAL = 1<<6, | 885 | STATION_INFO_SIGNAL = BIT(6), |
| 880 | STATION_INFO_TX_BITRATE = 1<<7, | 886 | STATION_INFO_TX_BITRATE = BIT(7), |
| 881 | STATION_INFO_RX_PACKETS = 1<<8, | 887 | STATION_INFO_RX_PACKETS = BIT(8), |
| 882 | STATION_INFO_TX_PACKETS = 1<<9, | 888 | STATION_INFO_TX_PACKETS = BIT(9), |
| 883 | STATION_INFO_TX_RETRIES = 1<<10, | 889 | STATION_INFO_TX_RETRIES = BIT(10), |
| 884 | STATION_INFO_TX_FAILED = 1<<11, | 890 | STATION_INFO_TX_FAILED = BIT(11), |
| 885 | STATION_INFO_RX_DROP_MISC = 1<<12, | 891 | STATION_INFO_RX_DROP_MISC = BIT(12), |
| 886 | STATION_INFO_SIGNAL_AVG = 1<<13, | 892 | STATION_INFO_SIGNAL_AVG = BIT(13), |
| 887 | STATION_INFO_RX_BITRATE = 1<<14, | 893 | STATION_INFO_RX_BITRATE = BIT(14), |
| 888 | STATION_INFO_BSS_PARAM = 1<<15, | 894 | STATION_INFO_BSS_PARAM = BIT(15), |
| 889 | STATION_INFO_CONNECTED_TIME = 1<<16, | 895 | STATION_INFO_CONNECTED_TIME = BIT(16), |
| 890 | STATION_INFO_ASSOC_REQ_IES = 1<<17, | 896 | STATION_INFO_ASSOC_REQ_IES = BIT(17), |
| 891 | STATION_INFO_STA_FLAGS = 1<<18, | 897 | STATION_INFO_STA_FLAGS = BIT(18), |
| 892 | STATION_INFO_BEACON_LOSS_COUNT = 1<<19, | 898 | STATION_INFO_BEACON_LOSS_COUNT = BIT(19), |
| 893 | STATION_INFO_T_OFFSET = 1<<20, | 899 | STATION_INFO_T_OFFSET = BIT(20), |
| 894 | STATION_INFO_LOCAL_PM = 1<<21, | 900 | STATION_INFO_LOCAL_PM = BIT(21), |
| 895 | STATION_INFO_PEER_PM = 1<<22, | 901 | STATION_INFO_PEER_PM = BIT(22), |
| 896 | STATION_INFO_NONPEER_PM = 1<<23, | 902 | STATION_INFO_NONPEER_PM = BIT(23), |
| 897 | STATION_INFO_RX_BYTES64 = 1<<24, | 903 | STATION_INFO_RX_BYTES64 = BIT(24), |
| 898 | STATION_INFO_TX_BYTES64 = 1<<25, | 904 | STATION_INFO_TX_BYTES64 = BIT(25), |
| 899 | STATION_INFO_CHAIN_SIGNAL = 1<<26, | 905 | STATION_INFO_CHAIN_SIGNAL = BIT(26), |
| 900 | STATION_INFO_CHAIN_SIGNAL_AVG = 1<<27, | 906 | STATION_INFO_CHAIN_SIGNAL_AVG = BIT(27), |
| 907 | STATION_INFO_EXPECTED_THROUGHPUT = BIT(28), | ||
| 901 | }; | 908 | }; |
| 902 | 909 | ||
| 903 | /** | 910 | /** |
| @@ -1019,6 +1026,8 @@ struct sta_bss_parameters { | |||
| 1019 | * @local_pm: local mesh STA power save mode | 1026 | * @local_pm: local mesh STA power save mode |
| 1020 | * @peer_pm: peer mesh STA power save mode | 1027 | * @peer_pm: peer mesh STA power save mode |
| 1021 | * @nonpeer_pm: non-peer mesh STA power save mode | 1028 | * @nonpeer_pm: non-peer mesh STA power save mode |
| 1029 | * @expected_throughput: expected throughput in kbps (including 802.11 headers) | ||
| 1030 | * towards this station. | ||
| 1022 | */ | 1031 | */ |
| 1023 | struct station_info { | 1032 | struct station_info { |
| 1024 | u32 filled; | 1033 | u32 filled; |
| @@ -1057,6 +1066,8 @@ struct station_info { | |||
| 1057 | enum nl80211_mesh_power_mode peer_pm; | 1066 | enum nl80211_mesh_power_mode peer_pm; |
| 1058 | enum nl80211_mesh_power_mode nonpeer_pm; | 1067 | enum nl80211_mesh_power_mode nonpeer_pm; |
| 1059 | 1068 | ||
| 1069 | u32 expected_throughput; | ||
| 1070 | |||
| 1060 | /* | 1071 | /* |
| 1061 | * Note: Add a new enum station_info_flags value for each new field and | 1072 | * Note: Add a new enum station_info_flags value for each new field and |
| 1062 | * use it to check which fields are initialized. | 1073 | * use it to check which fields are initialized. |
| @@ -1064,6 +1075,19 @@ struct station_info { | |||
| 1064 | }; | 1075 | }; |
| 1065 | 1076 | ||
| 1066 | /** | 1077 | /** |
| 1078 | * cfg80211_get_station - retrieve information about a given station | ||
| 1079 | * @dev: the device where the station is supposed to be connected to | ||
| 1080 | * @mac_addr: the mac address of the station of interest | ||
| 1081 | * @sinfo: pointer to the structure to fill with the information | ||
| 1082 | * | ||
| 1083 | * Returns 0 on success and sinfo is filled with the available information | ||
| 1084 | * otherwise returns a negative error code and the content of sinfo has to be | ||
| 1085 | * considered undefined. | ||
| 1086 | */ | ||
| 1087 | int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr, | ||
| 1088 | struct station_info *sinfo); | ||
| 1089 | |||
| 1090 | /** | ||
| 1067 | * enum monitor_flags - monitor flags | 1091 | * enum monitor_flags - monitor flags |
| 1068 | * | 1092 | * |
| 1069 | * Monitor interface configuration flags. Note that these must be the bits | 1093 | * Monitor interface configuration flags. Note that these must be the bits |
| @@ -1164,7 +1188,7 @@ struct bss_parameters { | |||
| 1164 | int use_cts_prot; | 1188 | int use_cts_prot; |
| 1165 | int use_short_preamble; | 1189 | int use_short_preamble; |
| 1166 | int use_short_slot_time; | 1190 | int use_short_slot_time; |
| 1167 | u8 *basic_rates; | 1191 | const u8 *basic_rates; |
| 1168 | u8 basic_rates_len; | 1192 | u8 basic_rates_len; |
| 1169 | int ap_isolate; | 1193 | int ap_isolate; |
| 1170 | int ht_opmode; | 1194 | int ht_opmode; |
| @@ -1694,10 +1718,10 @@ struct cfg80211_disassoc_request { | |||
| 1694 | * @ht_capa_mask: The bits of ht_capa which are to be used. | 1718 | * @ht_capa_mask: The bits of ht_capa which are to be used. |
| 1695 | */ | 1719 | */ |
| 1696 | struct cfg80211_ibss_params { | 1720 | struct cfg80211_ibss_params { |
| 1697 | u8 *ssid; | 1721 | const u8 *ssid; |
| 1698 | u8 *bssid; | 1722 | const u8 *bssid; |
| 1699 | struct cfg80211_chan_def chandef; | 1723 | struct cfg80211_chan_def chandef; |
| 1700 | u8 *ie; | 1724 | const u8 *ie; |
| 1701 | u8 ssid_len, ie_len; | 1725 | u8 ssid_len, ie_len; |
| 1702 | u16 beacon_interval; | 1726 | u16 beacon_interval; |
| 1703 | u32 basic_rates; | 1727 | u32 basic_rates; |
| @@ -1806,8 +1830,8 @@ struct cfg80211_bitrate_mask { | |||
| 1806 | * @pmkid: The PMK material itself. | 1830 | * @pmkid: The PMK material itself. |
| 1807 | */ | 1831 | */ |
| 1808 | struct cfg80211_pmksa { | 1832 | struct cfg80211_pmksa { |
| 1809 | u8 *bssid; | 1833 | const u8 *bssid; |
| 1810 | u8 *pmkid; | 1834 | const u8 *pmkid; |
| 1811 | }; | 1835 | }; |
| 1812 | 1836 | ||
| 1813 | /** | 1837 | /** |
| @@ -1822,7 +1846,7 @@ struct cfg80211_pmksa { | |||
| 1822 | * memory, free @mask only! | 1846 | * memory, free @mask only! |
| 1823 | */ | 1847 | */ |
| 1824 | struct cfg80211_pkt_pattern { | 1848 | struct cfg80211_pkt_pattern { |
| 1825 | u8 *mask, *pattern; | 1849 | const u8 *mask, *pattern; |
| 1826 | int pattern_len; | 1850 | int pattern_len; |
| 1827 | int pkt_offset; | 1851 | int pkt_offset; |
| 1828 | }; | 1852 | }; |
| @@ -1986,6 +2010,8 @@ struct cfg80211_update_ft_ies_params { | |||
| 1986 | * @len: buffer length | 2010 | * @len: buffer length |
| 1987 | * @no_cck: don't use cck rates for this frame | 2011 | * @no_cck: don't use cck rates for this frame |
| 1988 | * @dont_wait_for_ack: tells the low level not to wait for an ack | 2012 | * @dont_wait_for_ack: tells the low level not to wait for an ack |
| 2013 | * @n_csa_offsets: length of csa_offsets array | ||
| 2014 | * @csa_offsets: array of all the csa offsets in the frame | ||
| 1989 | */ | 2015 | */ |
| 1990 | struct cfg80211_mgmt_tx_params { | 2016 | struct cfg80211_mgmt_tx_params { |
| 1991 | struct ieee80211_channel *chan; | 2017 | struct ieee80211_channel *chan; |
| @@ -1995,6 +2021,8 @@ struct cfg80211_mgmt_tx_params { | |||
| 1995 | size_t len; | 2021 | size_t len; |
| 1996 | bool no_cck; | 2022 | bool no_cck; |
| 1997 | bool dont_wait_for_ack; | 2023 | bool dont_wait_for_ack; |
| 2024 | int n_csa_offsets; | ||
| 2025 | const u16 *csa_offsets; | ||
| 1998 | }; | 2026 | }; |
| 1999 | 2027 | ||
| 2000 | /** | 2028 | /** |
| @@ -2336,28 +2364,29 @@ struct cfg80211_ops { | |||
| 2336 | 2364 | ||
| 2337 | 2365 | ||
| 2338 | int (*add_station)(struct wiphy *wiphy, struct net_device *dev, | 2366 | int (*add_station)(struct wiphy *wiphy, struct net_device *dev, |
| 2339 | u8 *mac, struct station_parameters *params); | 2367 | const u8 *mac, |
| 2368 | struct station_parameters *params); | ||
| 2340 | int (*del_station)(struct wiphy *wiphy, struct net_device *dev, | 2369 | int (*del_station)(struct wiphy *wiphy, struct net_device *dev, |
| 2341 | u8 *mac); | 2370 | const u8 *mac); |
| 2342 | int (*change_station)(struct wiphy *wiphy, struct net_device *dev, | 2371 | int (*change_station)(struct wiphy *wiphy, struct net_device *dev, |
| 2343 | u8 *mac, struct station_parameters *params); | 2372 | const u8 *mac, |
| 2373 | struct station_parameters *params); | ||
| 2344 | int (*get_station)(struct wiphy *wiphy, struct net_device *dev, | 2374 | int (*get_station)(struct wiphy *wiphy, struct net_device *dev, |
| 2345 | u8 *mac, struct station_info *sinfo); | 2375 | const u8 *mac, struct station_info *sinfo); |
| 2346 | int (*dump_station)(struct wiphy *wiphy, struct net_device *dev, | 2376 | int (*dump_station)(struct wiphy *wiphy, struct net_device *dev, |
| 2347 | int idx, u8 *mac, struct station_info *sinfo); | 2377 | int idx, u8 *mac, struct station_info *sinfo); |
| 2348 | 2378 | ||
| 2349 | int (*add_mpath)(struct wiphy *wiphy, struct net_device *dev, | 2379 | int (*add_mpath)(struct wiphy *wiphy, struct net_device *dev, |
| 2350 | u8 *dst, u8 *next_hop); | 2380 | const u8 *dst, const u8 *next_hop); |
| 2351 | int (*del_mpath)(struct wiphy *wiphy, struct net_device *dev, | 2381 | int (*del_mpath)(struct wiphy *wiphy, struct net_device *dev, |
| 2352 | u8 *dst); | 2382 | const u8 *dst); |
| 2353 | int (*change_mpath)(struct wiphy *wiphy, struct net_device *dev, | 2383 | int (*change_mpath)(struct wiphy *wiphy, struct net_device *dev, |
| 2354 | u8 *dst, u8 *next_hop); | 2384 | const u8 *dst, const u8 *next_hop); |
| 2355 | int (*get_mpath)(struct wiphy *wiphy, struct net_device *dev, | 2385 | int (*get_mpath)(struct wiphy *wiphy, struct net_device *dev, |
| 2356 | u8 *dst, u8 *next_hop, | 2386 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo); |
| 2357 | struct mpath_info *pinfo); | ||
| 2358 | int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev, | 2387 | int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev, |
| 2359 | int idx, u8 *dst, u8 *next_hop, | 2388 | int idx, u8 *dst, u8 *next_hop, |
| 2360 | struct mpath_info *pinfo); | 2389 | struct mpath_info *pinfo); |
| 2361 | int (*get_mesh_config)(struct wiphy *wiphy, | 2390 | int (*get_mesh_config)(struct wiphy *wiphy, |
| 2362 | struct net_device *dev, | 2391 | struct net_device *dev, |
| 2363 | struct mesh_config *conf); | 2392 | struct mesh_config *conf); |
| @@ -2487,11 +2516,11 @@ struct cfg80211_ops { | |||
| 2487 | struct cfg80211_gtk_rekey_data *data); | 2516 | struct cfg80211_gtk_rekey_data *data); |
| 2488 | 2517 | ||
| 2489 | int (*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev, | 2518 | int (*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev, |
| 2490 | u8 *peer, u8 action_code, u8 dialog_token, | 2519 | const u8 *peer, u8 action_code, u8 dialog_token, |
| 2491 | u16 status_code, u32 peer_capability, | 2520 | u16 status_code, u32 peer_capability, |
| 2492 | const u8 *buf, size_t len); | 2521 | const u8 *buf, size_t len); |
| 2493 | int (*tdls_oper)(struct wiphy *wiphy, struct net_device *dev, | 2522 | int (*tdls_oper)(struct wiphy *wiphy, struct net_device *dev, |
| 2494 | u8 *peer, enum nl80211_tdls_operation oper); | 2523 | const u8 *peer, enum nl80211_tdls_operation oper); |
| 2495 | 2524 | ||
| 2496 | int (*probe_client)(struct wiphy *wiphy, struct net_device *dev, | 2525 | int (*probe_client)(struct wiphy *wiphy, struct net_device *dev, |
| 2497 | const u8 *peer, u64 *cookie); | 2526 | const u8 *peer, u64 *cookie); |
| @@ -2638,6 +2667,7 @@ struct ieee80211_iface_limit { | |||
| 2638 | * between infrastructure and AP types must match. This is required | 2667 | * between infrastructure and AP types must match. This is required |
| 2639 | * only in special cases. | 2668 | * only in special cases. |
| 2640 | * @radar_detect_widths: bitmap of channel widths supported for radar detection | 2669 | * @radar_detect_widths: bitmap of channel widths supported for radar detection |
| 2670 | * @radar_detect_regions: bitmap of regions supported for radar detection | ||
| 2641 | * | 2671 | * |
| 2642 | * With this structure the driver can describe which interface | 2672 | * With this structure the driver can describe which interface |
| 2643 | * combinations it supports concurrently. | 2673 | * combinations it supports concurrently. |
| @@ -2695,6 +2725,7 @@ struct ieee80211_iface_combination { | |||
| 2695 | u8 n_limits; | 2725 | u8 n_limits; |
| 2696 | bool beacon_int_infra_match; | 2726 | bool beacon_int_infra_match; |
| 2697 | u8 radar_detect_widths; | 2727 | u8 radar_detect_widths; |
| 2728 | u8 radar_detect_regions; | ||
| 2698 | }; | 2729 | }; |
| 2699 | 2730 | ||
| 2700 | struct ieee80211_txrx_stypes { | 2731 | struct ieee80211_txrx_stypes { |
| @@ -2925,6 +2956,17 @@ struct wiphy_vendor_command { | |||
| 2925 | * (including P2P GO) or 0 to indicate no such limit is advertised. The | 2956 | * (including P2P GO) or 0 to indicate no such limit is advertised. The |
| 2926 | * driver is allowed to advertise a theoretical limit that it can reach in | 2957 | * driver is allowed to advertise a theoretical limit that it can reach in |
| 2927 | * some cases, but may not always reach. | 2958 | * some cases, but may not always reach. |
| 2959 | * | ||
| 2960 | * @max_num_csa_counters: Number of supported csa_counters in beacons | ||
| 2961 | * and probe responses. This value should be set if the driver | ||
| 2962 | * wishes to limit the number of csa counters. Default (0) means | ||
| 2963 | * infinite. | ||
| 2964 | * @max_adj_channel_rssi_comp: max offset of between the channel on which the | ||
| 2965 | * frame was sent and the channel on which the frame was heard for which | ||
| 2966 | * the reported rssi is still valid. If a driver is able to compensate the | ||
| 2967 | * low rssi when a frame is heard on different channel, then it should set | ||
| 2968 | * this variable to the maximal offset for which it can compensate. | ||
| 2969 | * This value should be set in MHz. | ||
| 2928 | */ | 2970 | */ |
| 2929 | struct wiphy { | 2971 | struct wiphy { |
| 2930 | /* assign these fields before you register the wiphy */ | 2972 | /* assign these fields before you register the wiphy */ |
| @@ -3042,6 +3084,9 @@ struct wiphy { | |||
| 3042 | 3084 | ||
| 3043 | u16 max_ap_assoc_sta; | 3085 | u16 max_ap_assoc_sta; |
| 3044 | 3086 | ||
| 3087 | u8 max_num_csa_counters; | ||
| 3088 | u8 max_adj_channel_rssi_comp; | ||
| 3089 | |||
| 3045 | char priv[0] __aligned(NETDEV_ALIGN); | 3090 | char priv[0] __aligned(NETDEV_ALIGN); |
| 3046 | }; | 3091 | }; |
| 3047 | 3092 | ||
| @@ -3270,7 +3315,7 @@ struct wireless_dev { | |||
| 3270 | struct cfg80211_ibss_params ibss; | 3315 | struct cfg80211_ibss_params ibss; |
| 3271 | struct cfg80211_connect_params connect; | 3316 | struct cfg80211_connect_params connect; |
| 3272 | struct cfg80211_cached_keys *keys; | 3317 | struct cfg80211_cached_keys *keys; |
| 3273 | u8 *ie; | 3318 | const u8 *ie; |
| 3274 | size_t ie_len; | 3319 | size_t ie_len; |
| 3275 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; | 3320 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; |
| 3276 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 3321 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
| @@ -3511,7 +3556,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
| 3511 | * Return: 0 on success, or a negative error code. | 3556 | * Return: 0 on success, or a negative error code. |
| 3512 | */ | 3557 | */ |
| 3513 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, | 3558 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, |
| 3514 | enum nl80211_iftype iftype, u8 *bssid, bool qos); | 3559 | enum nl80211_iftype iftype, const u8 *bssid, |
| 3560 | bool qos); | ||
| 3515 | 3561 | ||
| 3516 | /** | 3562 | /** |
| 3517 | * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame | 3563 | * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame |
| @@ -4312,7 +4358,7 @@ void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss, | |||
| 4312 | * and not try to connect to any AP any more. | 4358 | * and not try to connect to any AP any more. |
| 4313 | */ | 4359 | */ |
| 4314 | void cfg80211_disconnected(struct net_device *dev, u16 reason, | 4360 | void cfg80211_disconnected(struct net_device *dev, u16 reason, |
| 4315 | u8 *ie, size_t ie_len, gfp_t gfp); | 4361 | const u8 *ie, size_t ie_len, gfp_t gfp); |
| 4316 | 4362 | ||
| 4317 | /** | 4363 | /** |
| 4318 | * cfg80211_ready_on_channel - notification of remain_on_channel start | 4364 | * cfg80211_ready_on_channel - notification of remain_on_channel start |
| @@ -4768,6 +4814,35 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, | |||
| 4768 | void *data), | 4814 | void *data), |
| 4769 | void *data); | 4815 | void *data); |
| 4770 | 4816 | ||
| 4817 | /* | ||
| 4818 | * cfg80211_stop_iface - trigger interface disconnection | ||
| 4819 | * | ||
| 4820 | * @wiphy: the wiphy | ||
| 4821 | * @wdev: wireless device | ||
| 4822 | * @gfp: context flags | ||
| 4823 | * | ||
| 4824 | * Trigger interface to be stopped as if AP was stopped, IBSS/mesh left, STA | ||
| 4825 | * disconnected. | ||
| 4826 | * | ||
| 4827 | * Note: This doesn't need any locks and is asynchronous. | ||
| 4828 | */ | ||
| 4829 | void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, | ||
| 4830 | gfp_t gfp); | ||
| 4831 | |||
| 4832 | /** | ||
| 4833 | * cfg80211_shutdown_all_interfaces - shut down all interfaces for a wiphy | ||
| 4834 | * @wiphy: the wiphy to shut down | ||
| 4835 | * | ||
| 4836 | * This function shuts down all interfaces belonging to this wiphy by | ||
| 4837 | * calling dev_close() (and treating non-netdev interfaces as needed). | ||
| 4838 | * It shouldn't really be used unless there are some fatal device errors | ||
| 4839 | * that really can't be recovered in any other way. | ||
| 4840 | * | ||
| 4841 | * Callers must hold the RTNL and be able to deal with callbacks into | ||
| 4842 | * the driver while the function is running. | ||
| 4843 | */ | ||
| 4844 | void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy); | ||
| 4845 | |||
| 4771 | /* Logging, debugging and troubleshooting/diagnostic helpers. */ | 4846 | /* Logging, debugging and troubleshooting/diagnostic helpers. */ |
| 4772 | 4847 | ||
| 4773 | /* wiphy_printk helpers, similar to dev_printk */ | 4848 | /* wiphy_printk helpers, similar to dev_printk */ |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 451c1bf00df9..2c78997bc48d 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
| @@ -1113,7 +1113,9 @@ enum ieee80211_vif_flags { | |||
| 1113 | * @addr: address of this interface | 1113 | * @addr: address of this interface |
| 1114 | * @p2p: indicates whether this AP or STA interface is a p2p | 1114 | * @p2p: indicates whether this AP or STA interface is a p2p |
| 1115 | * interface, i.e. a GO or p2p-sta respectively | 1115 | * interface, i.e. a GO or p2p-sta respectively |
| 1116 | * @csa_active: marks whether a channel switch is going on | 1116 | * @csa_active: marks whether a channel switch is going on. Internally it is |
| 1117 | * write-protected by sdata_lock and local->mtx so holding either is fine | ||
| 1118 | * for read access. | ||
| 1117 | * @driver_flags: flags/capabilities the driver has for this interface, | 1119 | * @driver_flags: flags/capabilities the driver has for this interface, |
| 1118 | * these need to be set (or cleared) when the interface is added | 1120 | * these need to be set (or cleared) when the interface is added |
| 1119 | * or, if supported by the driver, the interface type is changed | 1121 | * or, if supported by the driver, the interface type is changed |
| @@ -1374,6 +1376,7 @@ struct ieee80211_sta_rates { | |||
| 1374 | * the station moves to associated state. | 1376 | * the station moves to associated state. |
| 1375 | * @smps_mode: current SMPS mode (off, static or dynamic) | 1377 | * @smps_mode: current SMPS mode (off, static or dynamic) |
| 1376 | * @rates: rate control selection table | 1378 | * @rates: rate control selection table |
| 1379 | * @tdls: indicates whether the STA is a TDLS peer | ||
| 1377 | */ | 1380 | */ |
| 1378 | struct ieee80211_sta { | 1381 | struct ieee80211_sta { |
| 1379 | u32 supp_rates[IEEE80211_NUM_BANDS]; | 1382 | u32 supp_rates[IEEE80211_NUM_BANDS]; |
| @@ -1388,6 +1391,7 @@ struct ieee80211_sta { | |||
| 1388 | enum ieee80211_sta_rx_bandwidth bandwidth; | 1391 | enum ieee80211_sta_rx_bandwidth bandwidth; |
| 1389 | enum ieee80211_smps_mode smps_mode; | 1392 | enum ieee80211_smps_mode smps_mode; |
| 1390 | struct ieee80211_sta_rates __rcu *rates; | 1393 | struct ieee80211_sta_rates __rcu *rates; |
| 1394 | bool tdls; | ||
| 1391 | 1395 | ||
| 1392 | /* must be last */ | 1396 | /* must be last */ |
| 1393 | u8 drv_priv[0] __aligned(sizeof(void *)); | 1397 | u8 drv_priv[0] __aligned(sizeof(void *)); |
| @@ -2765,6 +2769,10 @@ enum ieee80211_roc_type { | |||
| 2765 | * information in bss_conf is set up and the beacon can be retrieved. A | 2769 | * information in bss_conf is set up and the beacon can be retrieved. A |
| 2766 | * channel context is bound before this is called. | 2770 | * channel context is bound before this is called. |
| 2767 | * @leave_ibss: Leave the IBSS again. | 2771 | * @leave_ibss: Leave the IBSS again. |
| 2772 | * | ||
| 2773 | * @get_expected_throughput: extract the expected throughput towards the | ||
| 2774 | * specified station. The returned value is expressed in Kbps. It returns 0 | ||
| 2775 | * if the RC algorithm does not have proper data to provide. | ||
| 2768 | */ | 2776 | */ |
| 2769 | struct ieee80211_ops { | 2777 | struct ieee80211_ops { |
| 2770 | void (*tx)(struct ieee80211_hw *hw, | 2778 | void (*tx)(struct ieee80211_hw *hw, |
| @@ -2958,6 +2966,7 @@ struct ieee80211_ops { | |||
| 2958 | 2966 | ||
| 2959 | int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | 2967 | int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
| 2960 | void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | 2968 | void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
| 2969 | u32 (*get_expected_throughput)(struct ieee80211_sta *sta); | ||
| 2961 | }; | 2970 | }; |
| 2962 | 2971 | ||
| 2963 | /** | 2972 | /** |
| @@ -3407,6 +3416,47 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | |||
| 3407 | */ | 3416 | */ |
| 3408 | void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets); | 3417 | void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets); |
| 3409 | 3418 | ||
| 3419 | #define IEEE80211_MAX_CSA_COUNTERS_NUM 2 | ||
| 3420 | |||
| 3421 | /** | ||
| 3422 | * struct ieee80211_mutable_offsets - mutable beacon offsets | ||
| 3423 | * @tim_offset: position of TIM element | ||
| 3424 | * @tim_length: size of TIM element | ||
| 3425 | * @csa_counter_offs: array of IEEE80211_MAX_CSA_COUNTERS_NUM offsets | ||
| 3426 | * to CSA counters. This array can contain zero values which | ||
| 3427 | * should be ignored. | ||
| 3428 | */ | ||
| 3429 | struct ieee80211_mutable_offsets { | ||
| 3430 | u16 tim_offset; | ||
| 3431 | u16 tim_length; | ||
| 3432 | |||
| 3433 | u16 csa_counter_offs[IEEE80211_MAX_CSA_COUNTERS_NUM]; | ||
| 3434 | }; | ||
| 3435 | |||
| 3436 | /** | ||
| 3437 | * ieee80211_beacon_get_template - beacon template generation function | ||
| 3438 | * @hw: pointer obtained from ieee80211_alloc_hw(). | ||
| 3439 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | ||
| 3440 | * @offs: &struct ieee80211_mutable_offsets pointer to struct that will | ||
| 3441 | * receive the offsets that may be updated by the driver. | ||
| 3442 | * | ||
| 3443 | * If the driver implements beaconing modes, it must use this function to | ||
| 3444 | * obtain the beacon template. | ||
| 3445 | * | ||
| 3446 | * This function should be used if the beacon frames are generated by the | ||
| 3447 | * device, and then the driver must use the returned beacon as the template | ||
| 3448 | * The driver or the device are responsible to update the DTIM and, when | ||
| 3449 | * applicable, the CSA count. | ||
| 3450 | * | ||
| 3451 | * The driver is responsible for freeing the returned skb. | ||
| 3452 | * | ||
| 3453 | * Return: The beacon template. %NULL on error. | ||
| 3454 | */ | ||
| 3455 | struct sk_buff * | ||
| 3456 | ieee80211_beacon_get_template(struct ieee80211_hw *hw, | ||
| 3457 | struct ieee80211_vif *vif, | ||
| 3458 | struct ieee80211_mutable_offsets *offs); | ||
| 3459 | |||
| 3410 | /** | 3460 | /** |
| 3411 | * ieee80211_beacon_get_tim - beacon generation function | 3461 | * ieee80211_beacon_get_tim - beacon generation function |
| 3412 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 3462 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
| @@ -3418,16 +3468,12 @@ void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets); | |||
| 3418 | * Set to 0 if invalid (in non-AP modes). | 3468 | * Set to 0 if invalid (in non-AP modes). |
| 3419 | * | 3469 | * |
| 3420 | * If the driver implements beaconing modes, it must use this function to | 3470 | * If the driver implements beaconing modes, it must use this function to |
| 3421 | * obtain the beacon frame/template. | 3471 | * obtain the beacon frame. |
| 3422 | * | 3472 | * |
| 3423 | * If the beacon frames are generated by the host system (i.e., not in | 3473 | * If the beacon frames are generated by the host system (i.e., not in |
| 3424 | * hardware/firmware), the driver uses this function to get each beacon | 3474 | * hardware/firmware), the driver uses this function to get each beacon |
| 3425 | * frame from mac80211 -- it is responsible for calling this function | 3475 | * frame from mac80211 -- it is responsible for calling this function exactly |
| 3426 | * before the beacon is needed (e.g. based on hardware interrupt). | 3476 | * once before the beacon is needed (e.g. based on hardware interrupt). |
| 3427 | * | ||
| 3428 | * If the beacon frames are generated by the device, then the driver | ||
| 3429 | * must use the returned beacon as the template and change the TIM IE | ||
| 3430 | * according to the current DTIM parameters/TIM bitmap. | ||
| 3431 | * | 3477 | * |
| 3432 | * The driver is responsible for freeing the returned skb. | 3478 | * The driver is responsible for freeing the returned skb. |
| 3433 | * | 3479 | * |
| @@ -3453,6 +3499,20 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
| 3453 | } | 3499 | } |
| 3454 | 3500 | ||
| 3455 | /** | 3501 | /** |
| 3502 | * ieee80211_csa_update_counter - request mac80211 to decrement the csa counter | ||
| 3503 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | ||
| 3504 | * | ||
| 3505 | * The csa counter should be updated after each beacon transmission. | ||
| 3506 | * This function is called implicitly when | ||
| 3507 | * ieee80211_beacon_get/ieee80211_beacon_get_tim are called, however if the | ||
| 3508 | * beacon frames are generated by the device, the driver should call this | ||
| 3509 | * function after each beacon transmission to sync mac80211's csa counters. | ||
| 3510 | * | ||
| 3511 | * Return: new csa counter value | ||
| 3512 | */ | ||
| 3513 | u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif); | ||
| 3514 | |||
| 3515 | /** | ||
| 3456 | * ieee80211_csa_finish - notify mac80211 about channel switch | 3516 | * ieee80211_csa_finish - notify mac80211 about channel switch |
| 3457 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | 3517 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
| 3458 | * | 3518 | * |
| @@ -4480,6 +4540,8 @@ struct rate_control_ops { | |||
| 4480 | void (*add_sta_debugfs)(void *priv, void *priv_sta, | 4540 | void (*add_sta_debugfs)(void *priv, void *priv_sta, |
| 4481 | struct dentry *dir); | 4541 | struct dentry *dir); |
| 4482 | void (*remove_sta_debugfs)(void *priv, void *priv_sta); | 4542 | void (*remove_sta_debugfs)(void *priv, void *priv_sta); |
| 4543 | |||
| 4544 | u32 (*get_expected_throughput)(void *priv_sta); | ||
| 4483 | }; | 4545 | }; |
| 4484 | 4546 | ||
| 4485 | static inline int rate_supported(struct ieee80211_sta *sta, | 4547 | static inline int rate_supported(struct ieee80211_sta *sta, |
diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h index 7655cfe27c34..bdf55c3b7a19 100644 --- a/include/net/nfc/digital.h +++ b/include/net/nfc/digital.h | |||
| @@ -36,6 +36,7 @@ enum { | |||
| 36 | NFC_DIGITAL_RF_TECH_212F, | 36 | NFC_DIGITAL_RF_TECH_212F, |
| 37 | NFC_DIGITAL_RF_TECH_424F, | 37 | NFC_DIGITAL_RF_TECH_424F, |
| 38 | NFC_DIGITAL_RF_TECH_ISO15693, | 38 | NFC_DIGITAL_RF_TECH_ISO15693, |
| 39 | NFC_DIGITAL_RF_TECH_106B, | ||
| 39 | 40 | ||
| 40 | NFC_DIGITAL_RF_TECH_LAST, | 41 | NFC_DIGITAL_RF_TECH_LAST, |
| 41 | }; | 42 | }; |
| @@ -62,6 +63,9 @@ enum { | |||
| 62 | NFC_DIGITAL_FRAMING_ISO15693_INVENTORY, | 63 | NFC_DIGITAL_FRAMING_ISO15693_INVENTORY, |
| 63 | NFC_DIGITAL_FRAMING_ISO15693_T5T, | 64 | NFC_DIGITAL_FRAMING_ISO15693_T5T, |
| 64 | 65 | ||
| 66 | NFC_DIGITAL_FRAMING_NFCB, | ||
| 67 | NFC_DIGITAL_FRAMING_NFCB_T4T, | ||
| 68 | |||
| 65 | NFC_DIGITAL_FRAMING_LAST, | 69 | NFC_DIGITAL_FRAMING_LAST, |
| 66 | }; | 70 | }; |
| 67 | 71 | ||
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index 03c4650b548c..61286db54388 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h | |||
| @@ -27,6 +27,7 @@ struct nfc_hci_dev; | |||
| 27 | struct nfc_hci_ops { | 27 | struct nfc_hci_ops { |
| 28 | int (*open) (struct nfc_hci_dev *hdev); | 28 | int (*open) (struct nfc_hci_dev *hdev); |
| 29 | void (*close) (struct nfc_hci_dev *hdev); | 29 | void (*close) (struct nfc_hci_dev *hdev); |
| 30 | int (*load_session) (struct nfc_hci_dev *hdev); | ||
| 30 | int (*hci_ready) (struct nfc_hci_dev *hdev); | 31 | int (*hci_ready) (struct nfc_hci_dev *hdev); |
| 31 | /* | 32 | /* |
| 32 | * xmit must always send the complete buffer before | 33 | * xmit must always send the complete buffer before |
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index 2e8b40c16274..6c583e244de2 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h | |||
| @@ -264,4 +264,7 @@ int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type); | |||
| 264 | int nfc_remove_se(struct nfc_dev *dev, u32 se_idx); | 264 | int nfc_remove_se(struct nfc_dev *dev, u32 se_idx); |
| 265 | struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx); | 265 | struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx); |
| 266 | 266 | ||
| 267 | void nfc_send_to_raw_sock(struct nfc_dev *dev, struct sk_buff *skb, | ||
| 268 | u8 payload_type, u8 direction); | ||
| 269 | |||
| 267 | #endif /* __NET_NFC_H */ | 270 | #endif /* __NET_NFC_H */ |
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index 9789dc95b6a8..9b19b4461928 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h | |||
| @@ -273,11 +273,19 @@ struct sockaddr_nfc_llcp { | |||
| 273 | * First byte is the adapter index | 273 | * First byte is the adapter index |
| 274 | * Second byte contains flags | 274 | * Second byte contains flags |
| 275 | * - 0x01 - Direction (0=RX, 1=TX) | 275 | * - 0x01 - Direction (0=RX, 1=TX) |
| 276 | * - 0x02-0x80 - Reserved | 276 | * - 0x02-0x04 - Payload type (000=LLCP, 001=NCI, 010=HCI, 011=Digital, |
| 277 | * 100=Proprietary) | ||
| 278 | * - 0x05-0x80 - Reserved | ||
| 277 | **/ | 279 | **/ |
| 278 | #define NFC_LLCP_RAW_HEADER_SIZE 2 | 280 | #define NFC_RAW_HEADER_SIZE 2 |
| 279 | #define NFC_LLCP_DIRECTION_RX 0x00 | 281 | #define NFC_DIRECTION_RX 0x00 |
| 280 | #define NFC_LLCP_DIRECTION_TX 0x01 | 282 | #define NFC_DIRECTION_TX 0x01 |
| 283 | |||
| 284 | #define RAW_PAYLOAD_LLCP 0 | ||
| 285 | #define RAW_PAYLOAD_NCI 1 | ||
| 286 | #define RAW_PAYLOAD_HCI 2 | ||
| 287 | #define RAW_PAYLOAD_DIGITAL 3 | ||
| 288 | #define RAW_PAYLOAD_PROPRIETARY 4 | ||
| 281 | 289 | ||
| 282 | /* socket option names */ | 290 | /* socket option names */ |
| 283 | #define NFC_LLCP_RW 0 | 291 | #define NFC_LLCP_RW 0 |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 9922b9b828a2..be9519b52bb1 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
| @@ -503,6 +503,9 @@ | |||
| 503 | * TX status event pertaining to the TX request. | 503 | * TX status event pertaining to the TX request. |
| 504 | * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the | 504 | * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the |
| 505 | * management frames at CCK rate or not in 2GHz band. | 505 | * management frames at CCK rate or not in 2GHz band. |
| 506 | * %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA | ||
| 507 | * counters which will be updated to the current value. This attribute | ||
| 508 | * is used during CSA period. | ||
| 506 | * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this | 509 | * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this |
| 507 | * command may be used with the corresponding cookie to cancel the wait | 510 | * command may be used with the corresponding cookie to cancel the wait |
| 508 | * time if it is known that it is no longer necessary. | 511 | * time if it is known that it is no longer necessary. |
| @@ -1525,10 +1528,10 @@ enum nl80211_commands { | |||
| 1525 | * operation). | 1528 | * operation). |
| 1526 | * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information | 1529 | * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information |
| 1527 | * for the time while performing a channel switch. | 1530 | * for the time while performing a channel switch. |
| 1528 | * @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter | 1531 | * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel |
| 1529 | * field in the beacons tail (%NL80211_ATTR_BEACON_TAIL). | 1532 | * switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). |
| 1530 | * @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter | 1533 | * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel |
| 1531 | * field in the probe response (%NL80211_ATTR_PROBE_RESP). | 1534 | * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP). |
| 1532 | * | 1535 | * |
| 1533 | * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. | 1536 | * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. |
| 1534 | * As specified in the &enum nl80211_rxmgmt_flags. | 1537 | * As specified in the &enum nl80211_rxmgmt_flags. |
| @@ -1576,6 +1579,11 @@ enum nl80211_commands { | |||
| 1576 | * advertise values that cannot always be met. In such cases, an attempt | 1579 | * advertise values that cannot always be met. In such cases, an attempt |
| 1577 | * to add a new station entry with @NL80211_CMD_NEW_STATION may fail. | 1580 | * to add a new station entry with @NL80211_CMD_NEW_STATION may fail. |
| 1578 | * | 1581 | * |
| 1582 | * @NL80211_ATTR_CSA_C_OFFSETS_TX: An array of csa counter offsets (u16) which | ||
| 1583 | * should be updated when the frame is transmitted. | ||
| 1584 | * @NL80211_ATTR_MAX_CSA_COUNTERS: U8 attribute used to advertise the maximum | ||
| 1585 | * supported number of csa counters. | ||
| 1586 | * | ||
| 1579 | * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32. | 1587 | * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32. |
| 1580 | * As specified in the &enum nl80211_tdls_peer_capability. | 1588 | * As specified in the &enum nl80211_tdls_peer_capability. |
| 1581 | * | 1589 | * |
| @@ -1920,6 +1928,9 @@ enum nl80211_attrs { | |||
| 1920 | 1928 | ||
| 1921 | NL80211_ATTR_IFACE_SOCKET_OWNER, | 1929 | NL80211_ATTR_IFACE_SOCKET_OWNER, |
| 1922 | 1930 | ||
| 1931 | NL80211_ATTR_CSA_C_OFFSETS_TX, | ||
| 1932 | NL80211_ATTR_MAX_CSA_COUNTERS, | ||
| 1933 | |||
| 1923 | /* add attributes here, update the policy in nl80211.c */ | 1934 | /* add attributes here, update the policy in nl80211.c */ |
| 1924 | 1935 | ||
| 1925 | __NL80211_ATTR_AFTER_LAST, | 1936 | __NL80211_ATTR_AFTER_LAST, |
| @@ -2188,6 +2199,8 @@ enum nl80211_sta_bss_param { | |||
| 2188 | * Contains a nested array of signal strength attributes (u8, dBm) | 2199 | * Contains a nested array of signal strength attributes (u8, dBm) |
| 2189 | * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average | 2200 | * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average |
| 2190 | * Same format as NL80211_STA_INFO_CHAIN_SIGNAL. | 2201 | * Same format as NL80211_STA_INFO_CHAIN_SIGNAL. |
| 2202 | * @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the | ||
| 2203 | * 802.11 header (u32, kbps) | ||
| 2191 | * @__NL80211_STA_INFO_AFTER_LAST: internal | 2204 | * @__NL80211_STA_INFO_AFTER_LAST: internal |
| 2192 | * @NL80211_STA_INFO_MAX: highest possible station info attribute | 2205 | * @NL80211_STA_INFO_MAX: highest possible station info attribute |
| 2193 | */ | 2206 | */ |
| @@ -2219,6 +2232,7 @@ enum nl80211_sta_info { | |||
| 2219 | NL80211_STA_INFO_TX_BYTES64, | 2232 | NL80211_STA_INFO_TX_BYTES64, |
| 2220 | NL80211_STA_INFO_CHAIN_SIGNAL, | 2233 | NL80211_STA_INFO_CHAIN_SIGNAL, |
| 2221 | NL80211_STA_INFO_CHAIN_SIGNAL_AVG, | 2234 | NL80211_STA_INFO_CHAIN_SIGNAL_AVG, |
| 2235 | NL80211_STA_INFO_EXPECTED_THROUGHPUT, | ||
| 2222 | 2236 | ||
| 2223 | /* keep last */ | 2237 | /* keep last */ |
| 2224 | __NL80211_STA_INFO_AFTER_LAST, | 2238 | __NL80211_STA_INFO_AFTER_LAST, |
| @@ -3688,6 +3702,8 @@ enum nl80211_iface_limit_attrs { | |||
| 3688 | * different channels may be used within this group. | 3702 | * different channels may be used within this group. |
| 3689 | * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap | 3703 | * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap |
| 3690 | * of supported channel widths for radar detection. | 3704 | * of supported channel widths for radar detection. |
| 3705 | * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap | ||
| 3706 | * of supported regulatory regions for radar detection. | ||
| 3691 | * @NUM_NL80211_IFACE_COMB: number of attributes | 3707 | * @NUM_NL80211_IFACE_COMB: number of attributes |
| 3692 | * @MAX_NL80211_IFACE_COMB: highest attribute number | 3708 | * @MAX_NL80211_IFACE_COMB: highest attribute number |
| 3693 | * | 3709 | * |
| @@ -3721,6 +3737,7 @@ enum nl80211_if_combination_attrs { | |||
| 3721 | NL80211_IFACE_COMB_STA_AP_BI_MATCH, | 3737 | NL80211_IFACE_COMB_STA_AP_BI_MATCH, |
| 3722 | NL80211_IFACE_COMB_NUM_CHANNELS, | 3738 | NL80211_IFACE_COMB_NUM_CHANNELS, |
| 3723 | NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, | 3739 | NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, |
| 3740 | NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, | ||
| 3724 | 3741 | ||
| 3725 | /* keep last */ | 3742 | /* keep last */ |
| 3726 | NUM_NL80211_IFACE_COMB, | 3743 | NUM_NL80211_IFACE_COMB, |
diff --git a/lib/crc7.c b/lib/crc7.c index f1c3a144cec1..bf6255e23919 100644 --- a/lib/crc7.c +++ b/lib/crc7.c | |||
| @@ -10,42 +10,47 @@ | |||
| 10 | #include <linux/crc7.h> | 10 | #include <linux/crc7.h> |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | /* Table for CRC-7 (polynomial x^7 + x^3 + 1) */ | 13 | /* |
| 14 | const u8 crc7_syndrome_table[256] = { | 14 | * Table for CRC-7 (polynomial x^7 + x^3 + 1). |
| 15 | 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, | 15 | * This is a big-endian CRC (msbit is highest power of x), |
| 16 | 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, | 16 | * aligned so the msbit of the byte is the x^6 coefficient |
| 17 | 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, | 17 | * and the lsbit is not used. |
| 18 | 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, | 18 | */ |
| 19 | 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d, | 19 | const u8 crc7_be_syndrome_table[256] = { |
| 20 | 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, | 20 | 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, |
| 21 | 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, | 21 | 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee, |
| 22 | 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c, | 22 | 0x32, 0x20, 0x16, 0x04, 0x7a, 0x68, 0x5e, 0x4c, |
| 23 | 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, | 23 | 0xa2, 0xb0, 0x86, 0x94, 0xea, 0xf8, 0xce, 0xdc, |
| 24 | 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, | 24 | 0x64, 0x76, 0x40, 0x52, 0x2c, 0x3e, 0x08, 0x1a, |
| 25 | 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42, | 25 | 0xf4, 0xe6, 0xd0, 0xc2, 0xbc, 0xae, 0x98, 0x8a, |
| 26 | 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a, | 26 | 0x56, 0x44, 0x72, 0x60, 0x1e, 0x0c, 0x3a, 0x28, |
| 27 | 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, | 27 | 0xc6, 0xd4, 0xe2, 0xf0, 0x8e, 0x9c, 0xaa, 0xb8, |
| 28 | 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21, | 28 | 0xc8, 0xda, 0xec, 0xfe, 0x80, 0x92, 0xa4, 0xb6, |
| 29 | 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, | 29 | 0x58, 0x4a, 0x7c, 0x6e, 0x10, 0x02, 0x34, 0x26, |
| 30 | 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, | 30 | 0xfa, 0xe8, 0xde, 0xcc, 0xb2, 0xa0, 0x96, 0x84, |
| 31 | 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e, | 31 | 0x6a, 0x78, 0x4e, 0x5c, 0x22, 0x30, 0x06, 0x14, |
| 32 | 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36, | 32 | 0xac, 0xbe, 0x88, 0x9a, 0xe4, 0xf6, 0xc0, 0xd2, |
| 33 | 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, | 33 | 0x3c, 0x2e, 0x18, 0x0a, 0x74, 0x66, 0x50, 0x42, |
| 34 | 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f, | 34 | 0x9e, 0x8c, 0xba, 0xa8, 0xd6, 0xc4, 0xf2, 0xe0, |
| 35 | 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, | 35 | 0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62, 0x70, |
| 36 | 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, | 36 | 0x82, 0x90, 0xa6, 0xb4, 0xca, 0xd8, 0xee, 0xfc, |
| 37 | 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55, | 37 | 0x12, 0x00, 0x36, 0x24, 0x5a, 0x48, 0x7e, 0x6c, |
| 38 | 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d, | 38 | 0xb0, 0xa2, 0x94, 0x86, 0xf8, 0xea, 0xdc, 0xce, |
| 39 | 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, | 39 | 0x20, 0x32, 0x04, 0x16, 0x68, 0x7a, 0x4c, 0x5e, |
| 40 | 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52, | 40 | 0xe6, 0xf4, 0xc2, 0xd0, 0xae, 0xbc, 0x8a, 0x98, |
| 41 | 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, | 41 | 0x76, 0x64, 0x52, 0x40, 0x3e, 0x2c, 0x1a, 0x08, |
| 42 | 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, | 42 | 0xd4, 0xc6, 0xf0, 0xe2, 0x9c, 0x8e, 0xb8, 0xaa, |
| 43 | 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28, | 43 | 0x44, 0x56, 0x60, 0x72, 0x0c, 0x1e, 0x28, 0x3a, |
| 44 | 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60, | 44 | 0x4a, 0x58, 0x6e, 0x7c, 0x02, 0x10, 0x26, 0x34, |
| 45 | 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, | 45 | 0xda, 0xc8, 0xfe, 0xec, 0x92, 0x80, 0xb6, 0xa4, |
| 46 | 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79 | 46 | 0x78, 0x6a, 0x5c, 0x4e, 0x30, 0x22, 0x14, 0x06, |
| 47 | 0xe8, 0xfa, 0xcc, 0xde, 0xa0, 0xb2, 0x84, 0x96, | ||
| 48 | 0x2e, 0x3c, 0x0a, 0x18, 0x66, 0x74, 0x42, 0x50, | ||
| 49 | 0xbe, 0xac, 0x9a, 0x88, 0xf6, 0xe4, 0xd2, 0xc0, | ||
| 50 | 0x1c, 0x0e, 0x38, 0x2a, 0x54, 0x46, 0x70, 0x62, | ||
| 51 | 0x8c, 0x9e, 0xa8, 0xba, 0xc4, 0xd6, 0xe0, 0xf2 | ||
| 47 | }; | 52 | }; |
| 48 | EXPORT_SYMBOL(crc7_syndrome_table); | 53 | EXPORT_SYMBOL(crc7_be_syndrome_table); |
| 49 | 54 | ||
| 50 | /** | 55 | /** |
| 51 | * crc7 - update the CRC7 for the data buffer | 56 | * crc7 - update the CRC7 for the data buffer |
| @@ -55,14 +60,17 @@ EXPORT_SYMBOL(crc7_syndrome_table); | |||
| 55 | * Context: any | 60 | * Context: any |
| 56 | * | 61 | * |
| 57 | * Returns the updated CRC7 value. | 62 | * Returns the updated CRC7 value. |
| 63 | * The CRC7 is left-aligned in the byte (the lsbit is always 0), as that | ||
| 64 | * makes the computation easier, and all callers want it in that form. | ||
| 65 | * | ||
| 58 | */ | 66 | */ |
| 59 | u8 crc7(u8 crc, const u8 *buffer, size_t len) | 67 | u8 crc7_be(u8 crc, const u8 *buffer, size_t len) |
| 60 | { | 68 | { |
| 61 | while (len--) | 69 | while (len--) |
| 62 | crc = crc7_byte(crc, *buffer++); | 70 | crc = crc7_be_byte(crc, *buffer++); |
| 63 | return crc; | 71 | return crc; |
| 64 | } | 72 | } |
| 65 | EXPORT_SYMBOL(crc7); | 73 | EXPORT_SYMBOL(crc7_be); |
| 66 | 74 | ||
| 67 | MODULE_DESCRIPTION("CRC7 calculations"); | 75 | MODULE_DESCRIPTION("CRC7 calculations"); |
| 68 | MODULE_LICENSE("GPL"); | 76 | MODULE_LICENSE("GPL"); |
diff --git a/lib/test_bpf.c b/lib/test_bpf.c index af677cb718f5..3c4a1e3e1f50 100644 --- a/lib/test_bpf.c +++ b/lib/test_bpf.c | |||
| @@ -560,30 +560,30 @@ static struct bpf_test tests[] = { | |||
| 560 | { | 560 | { |
| 561 | "tcpdump port 22", | 561 | "tcpdump port 22", |
| 562 | .u.insns = { | 562 | .u.insns = { |
| 563 | { 0x28, 0, 0, 0x0000000c }, | 563 | BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 12), |
| 564 | { 0x15, 0, 8, 0x000086dd }, | 564 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x86dd, 0, 8), /* IPv6 */ |
| 565 | { 0x30, 0, 0, 0x00000014 }, | 565 | BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 20), |
| 566 | { 0x15, 2, 0, 0x00000084 }, | 566 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x84, 2, 0), |
| 567 | { 0x15, 1, 0, 0x00000006 }, | 567 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x6, 1, 0), |
| 568 | { 0x15, 0, 17, 0x00000011 }, | 568 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x11, 0, 17), |
| 569 | { 0x28, 0, 0, 0x00000036 }, | 569 | BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 54), |
| 570 | { 0x15, 14, 0, 0x00000016 }, | 570 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 22, 14, 0), |
| 571 | { 0x28, 0, 0, 0x00000038 }, | 571 | BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 56), |
| 572 | { 0x15, 12, 13, 0x00000016 }, | 572 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 22, 12, 13), |
| 573 | { 0x15, 0, 12, 0x00000800 }, | 573 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0800, 0, 12), /* IPv4 */ |
| 574 | { 0x30, 0, 0, 0x00000017 }, | 574 | BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 23), |
| 575 | { 0x15, 2, 0, 0x00000084 }, | 575 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x84, 2, 0), |
| 576 | { 0x15, 1, 0, 0x00000006 }, | 576 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x6, 1, 0), |
| 577 | { 0x15, 0, 8, 0x00000011 }, | 577 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x11, 0, 8), |
| 578 | { 0x28, 0, 0, 0x00000014 }, | 578 | BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 20), |
| 579 | { 0x45, 6, 0, 0x00001fff }, | 579 | BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K, 0x1fff, 6, 0), |
| 580 | { 0xb1, 0, 0, 0x0000000e }, | 580 | BPF_STMT(BPF_LDX | BPF_B | BPF_MSH, 14), |
| 581 | { 0x48, 0, 0, 0x0000000e }, | 581 | BPF_STMT(BPF_LD | BPF_H | BPF_IND, 14), |
| 582 | { 0x15, 2, 0, 0x00000016 }, | 582 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 22, 2, 0), |
| 583 | { 0x48, 0, 0, 0x00000010 }, | 583 | BPF_STMT(BPF_LD | BPF_H | BPF_IND, 16), |
| 584 | { 0x15, 0, 1, 0x00000016 }, | 584 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 22, 0, 1), |
| 585 | { 0x06, 0, 0, 0x0000ffff }, | 585 | BPF_STMT(BPF_RET | BPF_K, 0xffff), |
| 586 | { 0x06, 0, 0, 0x00000000 }, | 586 | BPF_STMT(BPF_RET | BPF_K, 0), |
| 587 | }, | 587 | }, |
| 588 | CLASSIC, | 588 | CLASSIC, |
| 589 | /* 3c:07:54:43:e5:76 > 10:bf:48:d6:43:d6, ethertype IPv4(0x0800) | 589 | /* 3c:07:54:43:e5:76 > 10:bf:48:d6:43:d6, ethertype IPv4(0x0800) |
| @@ -609,39 +609,39 @@ static struct bpf_test tests[] = { | |||
| 609 | * ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0) and | 609 | * ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0) and |
| 610 | * (len > 115 or len < 30000000000)' -d | 610 | * (len > 115 or len < 30000000000)' -d |
| 611 | */ | 611 | */ |
| 612 | { 0x28, 0, 0, 0x0000000c }, | 612 | BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 12), |
| 613 | { 0x15, 30, 0, 0x000086dd }, | 613 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x86dd, 30, 0), |
| 614 | { 0x15, 0, 29, 0x00000800 }, | 614 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x800, 0, 29), |
| 615 | { 0x30, 0, 0, 0x00000017 }, | 615 | BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 23), |
| 616 | { 0x15, 0, 27, 0x00000006 }, | 616 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x6, 0, 27), |
| 617 | { 0x28, 0, 0, 0x00000014 }, | 617 | BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 20), |
| 618 | { 0x45, 25, 0, 0x00001fff }, | 618 | BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K, 0x1fff, 25, 0), |
| 619 | { 0xb1, 0, 0, 0x0000000e }, | 619 | BPF_STMT(BPF_LDX | BPF_B | BPF_MSH, 14), |
| 620 | { 0x48, 0, 0, 0x0000000e }, | 620 | BPF_STMT(BPF_LD | BPF_H | BPF_IND, 14), |
| 621 | { 0x15, 2, 0, 0x00000016 }, | 621 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 22, 2, 0), |
| 622 | { 0x48, 0, 0, 0x00000010 }, | 622 | BPF_STMT(BPF_LD | BPF_H | BPF_IND, 16), |
| 623 | { 0x15, 0, 20, 0x00000016 }, | 623 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 22, 0, 20), |
| 624 | { 0x28, 0, 0, 0x00000010 }, | 624 | BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 16), |
| 625 | { 0x02, 0, 0, 0x00000001 }, | 625 | BPF_STMT(BPF_ST, 1), |
| 626 | { 0x30, 0, 0, 0x0000000e }, | 626 | BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 14), |
| 627 | { 0x54, 0, 0, 0x0000000f }, | 627 | BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xf), |
| 628 | { 0x64, 0, 0, 0x00000002 }, | 628 | BPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 2), |
| 629 | { 0x07, 0, 0, 0x00000005 }, | 629 | BPF_STMT(BPF_MISC | BPF_TAX, 0x5), /* libpcap emits K on TAX */ |
| 630 | { 0x60, 0, 0, 0x00000001 }, | 630 | BPF_STMT(BPF_LD | BPF_MEM, 1), |
| 631 | { 0x1c, 0, 0, 0x00000000 }, | 631 | BPF_STMT(BPF_ALU | BPF_SUB | BPF_X, 0), |
| 632 | { 0x02, 0, 0, 0x00000005 }, | 632 | BPF_STMT(BPF_ST, 5), |
| 633 | { 0xb1, 0, 0, 0x0000000e }, | 633 | BPF_STMT(BPF_LDX | BPF_B | BPF_MSH, 14), |
| 634 | { 0x50, 0, 0, 0x0000001a }, | 634 | BPF_STMT(BPF_LD | BPF_B | BPF_IND, 26), |
| 635 | { 0x54, 0, 0, 0x000000f0 }, | 635 | BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xf0), |
| 636 | { 0x74, 0, 0, 0x00000002 }, | 636 | BPF_STMT(BPF_ALU | BPF_RSH | BPF_K, 2), |
| 637 | { 0x07, 0, 0, 0x00000009 }, | 637 | BPF_STMT(BPF_MISC | BPF_TAX, 0x9), /* libpcap emits K on TAX */ |
| 638 | { 0x60, 0, 0, 0x00000005 }, | 638 | BPF_STMT(BPF_LD | BPF_MEM, 5), |
| 639 | { 0x1d, 4, 0, 0x00000000 }, | 639 | BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0, 4, 0), |
| 640 | { 0x80, 0, 0, 0x00000000 }, | 640 | BPF_STMT(BPF_LD | BPF_LEN, 0), |
| 641 | { 0x25, 1, 0, 0x00000073 }, | 641 | BPF_JUMP(BPF_JMP | BPF_JGT | BPF_K, 0x73, 1, 0), |
| 642 | { 0x35, 1, 0, 0xfc23ac00 }, | 642 | BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 0xfc23ac00, 1, 0), |
| 643 | { 0x06, 0, 0, 0x0000ffff }, | 643 | BPF_STMT(BPF_RET | BPF_K, 0xffff), |
| 644 | { 0x06, 0, 0, 0x00000000 }, | 644 | BPF_STMT(BPF_RET | BPF_K, 0), |
| 645 | }, | 645 | }, |
| 646 | CLASSIC, | 646 | CLASSIC, |
| 647 | { 0x10, 0xbf, 0x48, 0xd6, 0x43, 0xd6, | 647 | { 0x10, 0xbf, 0x48, 0xd6, 0x43, 0xd6, |
| @@ -1453,17 +1453,24 @@ static struct bpf_test tests[] = { | |||
| 1453 | BPF_STMT(BPF_RET | BPF_A, 0), | 1453 | BPF_STMT(BPF_RET | BPF_A, 0), |
| 1454 | }, | 1454 | }, |
| 1455 | CLASSIC, | 1455 | CLASSIC, |
| 1456 | { 0x00, 0x1b, 0x21, 0x3c, 0x9d, 0xf8, 0x90, 0xe2, | 1456 | { 0x00, 0x1b, 0x21, 0x3c, 0x9d, 0xf8, |
| 1457 | 0xba, 0x0a, 0x56, 0xb4, 0x08, 0x00, 0x45, 0x00, | 1457 | 0x90, 0xe2, 0xba, 0x0a, 0x56, 0xb4, |
| 1458 | 0x00, 0x28, 0x00, 0x00, 0x20, 0x00, 0x40, 0x11, | 1458 | 0x08, 0x00, |
| 1459 | 0x00, 0x00, 0xc0, 0xa8, 0x33, 0x01, 0xc0, 0xa8, | 1459 | 0x45, 0x00, 0x00, 0x28, 0x00, 0x00, |
| 1460 | 0x33, 0x02, 0xbb, 0xb6, 0xa9, 0xfa, 0x00, 0x14, | 1460 | 0x20, 0x00, 0x40, 0x11, 0x00, 0x00, /* IP header */ |
| 1461 | 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | 1461 | 0xc0, 0xa8, 0x33, 0x01, |
| 1462 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | 1462 | 0xc0, 0xa8, 0x33, 0x02, |
| 1463 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | 1463 | 0xbb, 0xb6, |
| 1464 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | 1464 | 0xa9, 0xfa, |
| 1465 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | 1465 | 0x00, 0x14, 0x00, 0x00, |
| 1466 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc }, | 1466 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, |
| 1467 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | ||
| 1468 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | ||
| 1469 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | ||
| 1470 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | ||
| 1471 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | ||
| 1472 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | ||
| 1473 | 0xcc, 0xcc, 0xcc, 0xcc }, | ||
| 1467 | { { 88, 0x001b } } | 1474 | { { 88, 0x001b } } |
| 1468 | }, | 1475 | }, |
| 1469 | { | 1476 | { |
| @@ -1485,6 +1492,96 @@ static struct bpf_test tests[] = { | |||
| 1485 | { }, | 1492 | { }, |
| 1486 | { }, | 1493 | { }, |
| 1487 | }, | 1494 | }, |
| 1495 | { /* Mainly checking JIT here. */ | ||
| 1496 | "M[]: STX + LDX", | ||
| 1497 | .u.insns = { | ||
| 1498 | BPF_STMT(BPF_LDX | BPF_IMM, 100), | ||
| 1499 | BPF_STMT(BPF_STX, 0), | ||
| 1500 | BPF_STMT(BPF_LDX | BPF_MEM, 0), | ||
| 1501 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1502 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1503 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1504 | BPF_STMT(BPF_STX, 1), | ||
| 1505 | BPF_STMT(BPF_LDX | BPF_MEM, 1), | ||
| 1506 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1507 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1508 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1509 | BPF_STMT(BPF_STX, 2), | ||
| 1510 | BPF_STMT(BPF_LDX | BPF_MEM, 2), | ||
| 1511 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1512 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1513 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1514 | BPF_STMT(BPF_STX, 3), | ||
| 1515 | BPF_STMT(BPF_LDX | BPF_MEM, 3), | ||
| 1516 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1517 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1518 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1519 | BPF_STMT(BPF_STX, 4), | ||
| 1520 | BPF_STMT(BPF_LDX | BPF_MEM, 4), | ||
| 1521 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1522 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1523 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1524 | BPF_STMT(BPF_STX, 5), | ||
| 1525 | BPF_STMT(BPF_LDX | BPF_MEM, 5), | ||
| 1526 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1527 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1528 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1529 | BPF_STMT(BPF_STX, 6), | ||
| 1530 | BPF_STMT(BPF_LDX | BPF_MEM, 6), | ||
| 1531 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1532 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1533 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1534 | BPF_STMT(BPF_STX, 7), | ||
| 1535 | BPF_STMT(BPF_LDX | BPF_MEM, 7), | ||
| 1536 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1537 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1538 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1539 | BPF_STMT(BPF_STX, 8), | ||
| 1540 | BPF_STMT(BPF_LDX | BPF_MEM, 8), | ||
| 1541 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1542 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1543 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1544 | BPF_STMT(BPF_STX, 9), | ||
| 1545 | BPF_STMT(BPF_LDX | BPF_MEM, 9), | ||
| 1546 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1547 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1548 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1549 | BPF_STMT(BPF_STX, 10), | ||
| 1550 | BPF_STMT(BPF_LDX | BPF_MEM, 10), | ||
| 1551 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1552 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1553 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1554 | BPF_STMT(BPF_STX, 11), | ||
| 1555 | BPF_STMT(BPF_LDX | BPF_MEM, 11), | ||
| 1556 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1557 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1558 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1559 | BPF_STMT(BPF_STX, 12), | ||
| 1560 | BPF_STMT(BPF_LDX | BPF_MEM, 12), | ||
| 1561 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1562 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1563 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1564 | BPF_STMT(BPF_STX, 13), | ||
| 1565 | BPF_STMT(BPF_LDX | BPF_MEM, 13), | ||
| 1566 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1567 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1568 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1569 | BPF_STMT(BPF_STX, 14), | ||
| 1570 | BPF_STMT(BPF_LDX | BPF_MEM, 14), | ||
| 1571 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1572 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1573 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1574 | BPF_STMT(BPF_STX, 15), | ||
| 1575 | BPF_STMT(BPF_LDX | BPF_MEM, 15), | ||
| 1576 | BPF_STMT(BPF_MISC | BPF_TXA, 0), | ||
| 1577 | BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), | ||
| 1578 | BPF_STMT(BPF_MISC | BPF_TAX, 0), | ||
| 1579 | BPF_STMT(BPF_RET | BPF_A, 0), | ||
| 1580 | }, | ||
| 1581 | CLASSIC | FLAG_NO_DATA, | ||
| 1582 | { }, | ||
| 1583 | { { 0, 116 } }, | ||
| 1584 | }, | ||
| 1488 | }; | 1585 | }; |
| 1489 | 1586 | ||
| 1490 | static struct net_device dev; | 1587 | static struct net_device dev; |
diff --git a/net/atm/svc.c b/net/atm/svc.c index 1281049c135f..d8e5d0c2ebbc 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c | |||
| @@ -263,17 +263,11 @@ static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, | |||
| 263 | goto out; | 263 | goto out; |
| 264 | } | 264 | } |
| 265 | } | 265 | } |
| 266 | /* | 266 | |
| 267 | * Not supported yet | ||
| 268 | * | ||
| 269 | * #ifndef CONFIG_SINGLE_SIGITF | ||
| 270 | */ | ||
| 271 | vcc->qos.txtp.max_pcr = SELECT_TOP_PCR(vcc->qos.txtp); | 267 | vcc->qos.txtp.max_pcr = SELECT_TOP_PCR(vcc->qos.txtp); |
| 272 | vcc->qos.txtp.pcr = 0; | 268 | vcc->qos.txtp.pcr = 0; |
| 273 | vcc->qos.txtp.min_pcr = 0; | 269 | vcc->qos.txtp.min_pcr = 0; |
| 274 | /* | 270 | |
| 275 | * #endif | ||
| 276 | */ | ||
| 277 | error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci); | 271 | error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci); |
| 278 | if (!error) | 272 | if (!error) |
| 279 | sock->state = SS_CONNECTED; | 273 | sock->state = SS_CONNECTED; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a1e5bb7d06e8..dc4d301d3a72 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
| @@ -7519,9 +7519,9 @@ int __init l2cap_init(void) | |||
| 7519 | l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, | 7519 | l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, |
| 7520 | NULL, &l2cap_debugfs_fops); | 7520 | NULL, &l2cap_debugfs_fops); |
| 7521 | 7521 | ||
| 7522 | debugfs_create_u16("l2cap_le_max_credits", 0466, bt_debugfs, | 7522 | debugfs_create_u16("l2cap_le_max_credits", 0644, bt_debugfs, |
| 7523 | &le_max_credits); | 7523 | &le_max_credits); |
| 7524 | debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs, | 7524 | debugfs_create_u16("l2cap_le_default_mps", 0644, bt_debugfs, |
| 7525 | &le_default_mps); | 7525 | &le_default_mps); |
| 7526 | 7526 | ||
| 7527 | bt_6lowpan_init(); | 7527 | bt_6lowpan_init(); |
diff --git a/net/core/tso.c b/net/core/tso.c index 097821dd3a8c..8c3203c585b0 100644 --- a/net/core/tso.c +++ b/net/core/tso.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | #include <linux/export.h> | ||
| 1 | #include <net/ip.h> | 2 | #include <net/ip.h> |
| 2 | #include <net/tso.h> | 3 | #include <net/tso.h> |
| 3 | 4 | ||
| @@ -7,6 +8,7 @@ int tso_count_descs(struct sk_buff *skb) | |||
| 7 | /* The Marvell Way */ | 8 | /* The Marvell Way */ |
| 8 | return skb_shinfo(skb)->gso_segs * 2 + skb_shinfo(skb)->nr_frags; | 9 | return skb_shinfo(skb)->gso_segs * 2 + skb_shinfo(skb)->nr_frags; |
| 9 | } | 10 | } |
| 11 | EXPORT_SYMBOL(tso_count_descs); | ||
| 10 | 12 | ||
| 11 | void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso, | 13 | void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso, |
| 12 | int size, bool is_last) | 14 | int size, bool is_last) |
| @@ -31,6 +33,7 @@ void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso, | |||
| 31 | tcph->rst = 0; | 33 | tcph->rst = 0; |
| 32 | } | 34 | } |
| 33 | } | 35 | } |
| 36 | EXPORT_SYMBOL(tso_build_hdr); | ||
| 34 | 37 | ||
| 35 | void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size) | 38 | void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size) |
| 36 | { | 39 | { |
| @@ -48,6 +51,7 @@ void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size) | |||
| 48 | tso->next_frag_idx++; | 51 | tso->next_frag_idx++; |
| 49 | } | 52 | } |
| 50 | } | 53 | } |
| 54 | EXPORT_SYMBOL(tso_build_data); | ||
| 51 | 55 | ||
| 52 | void tso_start(struct sk_buff *skb, struct tso_t *tso) | 56 | void tso_start(struct sk_buff *skb, struct tso_t *tso) |
| 53 | { | 57 | { |
| @@ -70,3 +74,4 @@ void tso_start(struct sk_buff *skb, struct tso_t *tso) | |||
| 70 | tso->next_frag_idx++; | 74 | tso->next_frag_idx++; |
| 71 | } | 75 | } |
| 72 | } | 76 | } |
| 77 | EXPORT_SYMBOL(tso_start); | ||
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index d84dc8d4c916..2bc9cc47f246 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
| @@ -484,7 +484,7 @@ static void reg_vif_setup(struct net_device *dev) | |||
| 484 | dev->type = ARPHRD_PIMREG; | 484 | dev->type = ARPHRD_PIMREG; |
| 485 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 8; | 485 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 8; |
| 486 | dev->flags = IFF_NOARP; | 486 | dev->flags = IFF_NOARP; |
| 487 | dev->netdev_ops = ®_vif_netdev_ops, | 487 | dev->netdev_ops = ®_vif_netdev_ops; |
| 488 | dev->destructor = free_netdev; | 488 | dev->destructor = free_netdev; |
| 489 | dev->features |= NETIF_F_NETNS_LOCAL; | 489 | dev->features |= NETIF_F_NETNS_LOCAL; |
| 490 | } | 490 | } |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 8c9d7302c846..7a95fa4a3de1 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
| @@ -682,6 +682,18 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock) | |||
| 682 | return NULL; | 682 | return NULL; |
| 683 | } | 683 | } |
| 684 | 684 | ||
| 685 | static void __iucv_auto_name(struct iucv_sock *iucv) | ||
| 686 | { | ||
| 687 | char name[12]; | ||
| 688 | |||
| 689 | sprintf(name, "%08x", atomic_inc_return(&iucv_sk_list.autobind_name)); | ||
| 690 | while (__iucv_get_sock_by_name(name)) { | ||
| 691 | sprintf(name, "%08x", | ||
| 692 | atomic_inc_return(&iucv_sk_list.autobind_name)); | ||
| 693 | } | ||
| 694 | memcpy(iucv->src_name, name, 8); | ||
| 695 | } | ||
| 696 | |||
| 685 | /* Bind an unbound socket */ | 697 | /* Bind an unbound socket */ |
| 686 | static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr, | 698 | static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr, |
| 687 | int addr_len) | 699 | int addr_len) |
| @@ -724,8 +736,12 @@ static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr, | |||
| 724 | rcu_read_lock(); | 736 | rcu_read_lock(); |
| 725 | for_each_netdev_rcu(&init_net, dev) { | 737 | for_each_netdev_rcu(&init_net, dev) { |
| 726 | if (!memcmp(dev->perm_addr, uid, 8)) { | 738 | if (!memcmp(dev->perm_addr, uid, 8)) { |
| 727 | memcpy(iucv->src_name, sa->siucv_name, 8); | ||
| 728 | memcpy(iucv->src_user_id, sa->siucv_user_id, 8); | 739 | memcpy(iucv->src_user_id, sa->siucv_user_id, 8); |
| 740 | /* Check for unitialized siucv_name */ | ||
| 741 | if (strncmp(sa->siucv_name, " ", 8) == 0) | ||
| 742 | __iucv_auto_name(iucv); | ||
| 743 | else | ||
| 744 | memcpy(iucv->src_name, sa->siucv_name, 8); | ||
| 729 | sk->sk_bound_dev_if = dev->ifindex; | 745 | sk->sk_bound_dev_if = dev->ifindex; |
| 730 | iucv->hs_dev = dev; | 746 | iucv->hs_dev = dev; |
| 731 | dev_hold(dev); | 747 | dev_hold(dev); |
| @@ -763,7 +779,6 @@ done: | |||
| 763 | static int iucv_sock_autobind(struct sock *sk) | 779 | static int iucv_sock_autobind(struct sock *sk) |
| 764 | { | 780 | { |
| 765 | struct iucv_sock *iucv = iucv_sk(sk); | 781 | struct iucv_sock *iucv = iucv_sk(sk); |
| 766 | char name[12]; | ||
| 767 | int err = 0; | 782 | int err = 0; |
| 768 | 783 | ||
| 769 | if (unlikely(!pr_iucv)) | 784 | if (unlikely(!pr_iucv)) |
| @@ -772,17 +787,9 @@ static int iucv_sock_autobind(struct sock *sk) | |||
| 772 | memcpy(iucv->src_user_id, iucv_userid, 8); | 787 | memcpy(iucv->src_user_id, iucv_userid, 8); |
| 773 | 788 | ||
| 774 | write_lock_bh(&iucv_sk_list.lock); | 789 | write_lock_bh(&iucv_sk_list.lock); |
| 775 | 790 | __iucv_auto_name(iucv); | |
| 776 | sprintf(name, "%08x", atomic_inc_return(&iucv_sk_list.autobind_name)); | ||
| 777 | while (__iucv_get_sock_by_name(name)) { | ||
| 778 | sprintf(name, "%08x", | ||
| 779 | atomic_inc_return(&iucv_sk_list.autobind_name)); | ||
| 780 | } | ||
| 781 | |||
| 782 | write_unlock_bh(&iucv_sk_list.lock); | 791 | write_unlock_bh(&iucv_sk_list.lock); |
| 783 | 792 | ||
| 784 | memcpy(&iucv->src_name, name, 8); | ||
| 785 | |||
| 786 | if (!iucv->msglimit) | 793 | if (!iucv->msglimit) |
| 787 | iucv->msglimit = IUCV_QUEUELEN_DEFAULT; | 794 | iucv->msglimit = IUCV_QUEUELEN_DEFAULT; |
| 788 | 795 | ||
| @@ -1936,11 +1943,10 @@ static int afiucv_hs_callback_syn(struct sock *sk, struct sk_buff *skb) | |||
| 1936 | sk_acceptq_is_full(sk) || | 1943 | sk_acceptq_is_full(sk) || |
| 1937 | !nsk) { | 1944 | !nsk) { |
| 1938 | /* error on server socket - connection refused */ | 1945 | /* error on server socket - connection refused */ |
| 1939 | if (nsk) | ||
| 1940 | sk_free(nsk); | ||
| 1941 | afiucv_swap_src_dest(skb); | 1946 | afiucv_swap_src_dest(skb); |
| 1942 | trans_hdr->flags = AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_FIN; | 1947 | trans_hdr->flags = AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_FIN; |
| 1943 | err = dev_queue_xmit(skb); | 1948 | err = dev_queue_xmit(skb); |
| 1949 | iucv_sock_kill(nsk); | ||
| 1944 | bh_unlock_sock(sk); | 1950 | bh_unlock_sock(sk); |
| 1945 | goto out; | 1951 | goto out; |
| 1946 | } | 1952 | } |
diff --git a/net/key/af_key.c b/net/key/af_key.c index b47f8e542aae..ba2a2f95911c 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -2541,7 +2541,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb, | |||
| 2541 | sel.sport_mask = htons(0xffff); | 2541 | sel.sport_mask = htons(0xffff); |
| 2542 | 2542 | ||
| 2543 | /* set destination address info of selector */ | 2543 | /* set destination address info of selector */ |
| 2544 | sa = ext_hdrs[SADB_EXT_ADDRESS_DST - 1], | 2544 | sa = ext_hdrs[SADB_EXT_ADDRESS_DST - 1]; |
| 2545 | pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr); | 2545 | pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr); |
| 2546 | sel.prefixlen_d = sa->sadb_address_prefixlen; | 2546 | sel.prefixlen_d = sa->sadb_address_prefixlen; |
| 2547 | sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto); | 2547 | sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto); |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 9d7d840aac6d..1e46ffa69167 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
| @@ -25,7 +25,8 @@ mac80211-y := \ | |||
| 25 | wme.o \ | 25 | wme.o \ |
| 26 | event.o \ | 26 | event.o \ |
| 27 | chan.o \ | 27 | chan.o \ |
| 28 | trace.o mlme.o | 28 | trace.o mlme.o \ |
| 29 | tdls.o | ||
| 29 | 30 | ||
| 30 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o | 31 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o |
| 31 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ | 32 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 7b8d3cf89574..d7513a503be1 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -472,8 +472,10 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
| 472 | { | 472 | { |
| 473 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 473 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
| 474 | struct ieee80211_local *local = sdata->local; | 474 | struct ieee80211_local *local = sdata->local; |
| 475 | struct rate_control_ref *ref = local->rate_ctrl; | ||
| 475 | struct timespec uptime; | 476 | struct timespec uptime; |
| 476 | u64 packets = 0; | 477 | u64 packets = 0; |
| 478 | u32 thr = 0; | ||
| 477 | int i, ac; | 479 | int i, ac; |
| 478 | 480 | ||
| 479 | sinfo->generation = sdata->local->sta_generation; | 481 | sinfo->generation = sdata->local->sta_generation; |
| @@ -587,6 +589,17 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
| 587 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED); | 589 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED); |
| 588 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | 590 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) |
| 589 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); | 591 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); |
| 592 | |||
| 593 | /* check if the driver has a SW RC implementation */ | ||
| 594 | if (ref && ref->ops->get_expected_throughput) | ||
| 595 | thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv); | ||
| 596 | else | ||
| 597 | thr = drv_get_expected_throughput(local, &sta->sta); | ||
| 598 | |||
| 599 | if (thr != 0) { | ||
| 600 | sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT; | ||
| 601 | sinfo->expected_throughput = thr; | ||
| 602 | } | ||
| 590 | } | 603 | } |
| 591 | 604 | ||
| 592 | static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = { | 605 | static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = { |
| @@ -777,7 +790,7 @@ static void ieee80211_get_et_strings(struct wiphy *wiphy, | |||
| 777 | } | 790 | } |
| 778 | 791 | ||
| 779 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | 792 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, |
| 780 | int idx, u8 *mac, struct station_info *sinfo) | 793 | int idx, u8 *mac, struct station_info *sinfo) |
| 781 | { | 794 | { |
| 782 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 795 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 783 | struct ieee80211_local *local = sdata->local; | 796 | struct ieee80211_local *local = sdata->local; |
| @@ -807,7 +820,7 @@ static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, | |||
| 807 | } | 820 | } |
| 808 | 821 | ||
| 809 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 822 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, |
| 810 | u8 *mac, struct station_info *sinfo) | 823 | const u8 *mac, struct station_info *sinfo) |
| 811 | { | 824 | { |
| 812 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 825 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 813 | struct ieee80211_local *local = sdata->local; | 826 | struct ieee80211_local *local = sdata->local; |
| @@ -1084,6 +1097,31 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
| 1084 | return 0; | 1097 | return 0; |
| 1085 | } | 1098 | } |
| 1086 | 1099 | ||
| 1100 | bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local) | ||
| 1101 | { | ||
| 1102 | struct ieee80211_sub_if_data *sdata; | ||
| 1103 | |||
| 1104 | lockdep_assert_held(&local->mtx); | ||
| 1105 | |||
| 1106 | rcu_read_lock(); | ||
| 1107 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
| 1108 | if (!ieee80211_sdata_running(sdata)) | ||
| 1109 | continue; | ||
| 1110 | |||
| 1111 | if (!sdata->vif.csa_active) | ||
| 1112 | continue; | ||
| 1113 | |||
| 1114 | if (!sdata->csa_block_tx) | ||
| 1115 | continue; | ||
| 1116 | |||
| 1117 | rcu_read_unlock(); | ||
| 1118 | return true; | ||
| 1119 | } | ||
| 1120 | rcu_read_unlock(); | ||
| 1121 | |||
| 1122 | return false; | ||
| 1123 | } | ||
| 1124 | |||
| 1087 | static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | 1125 | static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) |
| 1088 | { | 1126 | { |
| 1089 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1127 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| @@ -1101,7 +1139,14 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
| 1101 | old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata); | 1139 | old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata); |
| 1102 | 1140 | ||
| 1103 | /* abort any running channel switch */ | 1141 | /* abort any running channel switch */ |
| 1142 | mutex_lock(&local->mtx); | ||
| 1104 | sdata->vif.csa_active = false; | 1143 | sdata->vif.csa_active = false; |
| 1144 | if (!ieee80211_csa_needs_block_tx(local)) | ||
| 1145 | ieee80211_wake_queues_by_reason(&local->hw, | ||
| 1146 | IEEE80211_MAX_QUEUE_MAP, | ||
| 1147 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
| 1148 | mutex_unlock(&local->mtx); | ||
| 1149 | |||
| 1105 | kfree(sdata->u.ap.next_beacon); | 1150 | kfree(sdata->u.ap.next_beacon); |
| 1106 | sdata->u.ap.next_beacon = NULL; | 1151 | sdata->u.ap.next_beacon = NULL; |
| 1107 | 1152 | ||
| @@ -1425,7 +1470,8 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
| 1425 | } | 1470 | } |
| 1426 | 1471 | ||
| 1427 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | 1472 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, |
| 1428 | u8 *mac, struct station_parameters *params) | 1473 | const u8 *mac, |
| 1474 | struct station_parameters *params) | ||
| 1429 | { | 1475 | { |
| 1430 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1476 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 1431 | struct sta_info *sta; | 1477 | struct sta_info *sta; |
| @@ -1459,6 +1505,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 1459 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { | 1505 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { |
| 1460 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 1506 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
| 1461 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | 1507 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
| 1508 | } else { | ||
| 1509 | sta->sta.tdls = true; | ||
| 1462 | } | 1510 | } |
| 1463 | 1511 | ||
| 1464 | err = sta_apply_parameters(local, sta, params); | 1512 | err = sta_apply_parameters(local, sta, params); |
| @@ -1492,7 +1540,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 1492 | } | 1540 | } |
| 1493 | 1541 | ||
| 1494 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | 1542 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, |
| 1495 | u8 *mac) | 1543 | const u8 *mac) |
| 1496 | { | 1544 | { |
| 1497 | struct ieee80211_sub_if_data *sdata; | 1545 | struct ieee80211_sub_if_data *sdata; |
| 1498 | 1546 | ||
| @@ -1506,7 +1554,7 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 1506 | } | 1554 | } |
| 1507 | 1555 | ||
| 1508 | static int ieee80211_change_station(struct wiphy *wiphy, | 1556 | static int ieee80211_change_station(struct wiphy *wiphy, |
| 1509 | struct net_device *dev, u8 *mac, | 1557 | struct net_device *dev, const u8 *mac, |
| 1510 | struct station_parameters *params) | 1558 | struct station_parameters *params) |
| 1511 | { | 1559 | { |
| 1512 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1560 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| @@ -1631,7 +1679,7 @@ out_err: | |||
| 1631 | 1679 | ||
| 1632 | #ifdef CONFIG_MAC80211_MESH | 1680 | #ifdef CONFIG_MAC80211_MESH |
| 1633 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | 1681 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, |
| 1634 | u8 *dst, u8 *next_hop) | 1682 | const u8 *dst, const u8 *next_hop) |
| 1635 | { | 1683 | { |
| 1636 | struct ieee80211_sub_if_data *sdata; | 1684 | struct ieee80211_sub_if_data *sdata; |
| 1637 | struct mesh_path *mpath; | 1685 | struct mesh_path *mpath; |
| @@ -1659,7 +1707,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
| 1659 | } | 1707 | } |
| 1660 | 1708 | ||
| 1661 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, | 1709 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, |
| 1662 | u8 *dst) | 1710 | const u8 *dst) |
| 1663 | { | 1711 | { |
| 1664 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1712 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 1665 | 1713 | ||
| @@ -1670,9 +1718,8 @@ static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
| 1670 | return 0; | 1718 | return 0; |
| 1671 | } | 1719 | } |
| 1672 | 1720 | ||
| 1673 | static int ieee80211_change_mpath(struct wiphy *wiphy, | 1721 | static int ieee80211_change_mpath(struct wiphy *wiphy, struct net_device *dev, |
| 1674 | struct net_device *dev, | 1722 | const u8 *dst, const u8 *next_hop) |
| 1675 | u8 *dst, u8 *next_hop) | ||
| 1676 | { | 1723 | { |
| 1677 | struct ieee80211_sub_if_data *sdata; | 1724 | struct ieee80211_sub_if_data *sdata; |
| 1678 | struct mesh_path *mpath; | 1725 | struct mesh_path *mpath; |
| @@ -1764,8 +1811,8 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
| 1764 | } | 1811 | } |
| 1765 | 1812 | ||
| 1766 | static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | 1813 | static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, |
| 1767 | int idx, u8 *dst, u8 *next_hop, | 1814 | int idx, u8 *dst, u8 *next_hop, |
| 1768 | struct mpath_info *pinfo) | 1815 | struct mpath_info *pinfo) |
| 1769 | { | 1816 | { |
| 1770 | struct ieee80211_sub_if_data *sdata; | 1817 | struct ieee80211_sub_if_data *sdata; |
| 1771 | struct mesh_path *mpath; | 1818 | struct mesh_path *mpath; |
| @@ -3019,26 +3066,11 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif) | |||
| 3019 | } | 3066 | } |
| 3020 | EXPORT_SYMBOL(ieee80211_csa_finish); | 3067 | EXPORT_SYMBOL(ieee80211_csa_finish); |
| 3021 | 3068 | ||
| 3022 | static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) | 3069 | static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata, |
| 3070 | u32 *changed) | ||
| 3023 | { | 3071 | { |
| 3024 | struct ieee80211_local *local = sdata->local; | 3072 | int err; |
| 3025 | int err, changed = 0; | ||
| 3026 | |||
| 3027 | sdata_assert_lock(sdata); | ||
| 3028 | |||
| 3029 | mutex_lock(&local->mtx); | ||
| 3030 | sdata->radar_required = sdata->csa_radar_required; | ||
| 3031 | err = ieee80211_vif_change_channel(sdata, &changed); | ||
| 3032 | mutex_unlock(&local->mtx); | ||
| 3033 | if (WARN_ON(err < 0)) | ||
| 3034 | return; | ||
| 3035 | |||
| 3036 | if (!local->use_chanctx) { | ||
| 3037 | local->_oper_chandef = sdata->csa_chandef; | ||
| 3038 | ieee80211_hw_config(local, 0); | ||
| 3039 | } | ||
| 3040 | 3073 | ||
| 3041 | sdata->vif.csa_active = false; | ||
| 3042 | switch (sdata->vif.type) { | 3074 | switch (sdata->vif.type) { |
| 3043 | case NL80211_IFTYPE_AP: | 3075 | case NL80211_IFTYPE_AP: |
| 3044 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); | 3076 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); |
| @@ -3046,35 +3078,74 @@ static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) | |||
| 3046 | sdata->u.ap.next_beacon = NULL; | 3078 | sdata->u.ap.next_beacon = NULL; |
| 3047 | 3079 | ||
| 3048 | if (err < 0) | 3080 | if (err < 0) |
| 3049 | return; | 3081 | return err; |
| 3050 | changed |= err; | 3082 | *changed |= err; |
| 3051 | break; | 3083 | break; |
| 3052 | case NL80211_IFTYPE_ADHOC: | 3084 | case NL80211_IFTYPE_ADHOC: |
| 3053 | err = ieee80211_ibss_finish_csa(sdata); | 3085 | err = ieee80211_ibss_finish_csa(sdata); |
| 3054 | if (err < 0) | 3086 | if (err < 0) |
| 3055 | return; | 3087 | return err; |
| 3056 | changed |= err; | 3088 | *changed |= err; |
| 3057 | break; | 3089 | break; |
| 3058 | #ifdef CONFIG_MAC80211_MESH | 3090 | #ifdef CONFIG_MAC80211_MESH |
| 3059 | case NL80211_IFTYPE_MESH_POINT: | 3091 | case NL80211_IFTYPE_MESH_POINT: |
| 3060 | err = ieee80211_mesh_finish_csa(sdata); | 3092 | err = ieee80211_mesh_finish_csa(sdata); |
| 3061 | if (err < 0) | 3093 | if (err < 0) |
| 3062 | return; | 3094 | return err; |
| 3063 | changed |= err; | 3095 | *changed |= err; |
| 3064 | break; | 3096 | break; |
| 3065 | #endif | 3097 | #endif |
| 3066 | default: | 3098 | default: |
| 3067 | WARN_ON(1); | 3099 | WARN_ON(1); |
| 3068 | return; | 3100 | return -EINVAL; |
| 3101 | } | ||
| 3102 | |||
| 3103 | return 0; | ||
| 3104 | } | ||
| 3105 | |||
| 3106 | static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) | ||
| 3107 | { | ||
| 3108 | struct ieee80211_local *local = sdata->local; | ||
| 3109 | u32 changed = 0; | ||
| 3110 | int err; | ||
| 3111 | |||
| 3112 | sdata_assert_lock(sdata); | ||
| 3113 | lockdep_assert_held(&local->mtx); | ||
| 3114 | |||
| 3115 | sdata->radar_required = sdata->csa_radar_required; | ||
| 3116 | err = ieee80211_vif_change_channel(sdata, &changed); | ||
| 3117 | if (err < 0) | ||
| 3118 | return err; | ||
| 3119 | |||
| 3120 | if (!local->use_chanctx) { | ||
| 3121 | local->_oper_chandef = sdata->csa_chandef; | ||
| 3122 | ieee80211_hw_config(local, 0); | ||
| 3069 | } | 3123 | } |
| 3070 | 3124 | ||
| 3125 | sdata->vif.csa_active = false; | ||
| 3126 | |||
| 3127 | err = ieee80211_set_after_csa_beacon(sdata, &changed); | ||
| 3128 | if (err) | ||
| 3129 | return err; | ||
| 3130 | |||
| 3071 | ieee80211_bss_info_change_notify(sdata, changed); | 3131 | ieee80211_bss_info_change_notify(sdata, changed); |
| 3132 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); | ||
| 3072 | 3133 | ||
| 3073 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 3134 | if (!ieee80211_csa_needs_block_tx(local)) |
| 3135 | ieee80211_wake_queues_by_reason(&local->hw, | ||
| 3074 | IEEE80211_MAX_QUEUE_MAP, | 3136 | IEEE80211_MAX_QUEUE_MAP, |
| 3075 | IEEE80211_QUEUE_STOP_REASON_CSA); | 3137 | IEEE80211_QUEUE_STOP_REASON_CSA); |
| 3076 | 3138 | ||
| 3077 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); | 3139 | return 0; |
| 3140 | } | ||
| 3141 | |||
| 3142 | static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) | ||
| 3143 | { | ||
| 3144 | if (__ieee80211_csa_finalize(sdata)) { | ||
| 3145 | sdata_info(sdata, "failed to finalize CSA, disconnecting\n"); | ||
| 3146 | cfg80211_stop_iface(sdata->local->hw.wiphy, &sdata->wdev, | ||
| 3147 | GFP_KERNEL); | ||
| 3148 | } | ||
| 3078 | } | 3149 | } |
| 3079 | 3150 | ||
| 3080 | void ieee80211_csa_finalize_work(struct work_struct *work) | 3151 | void ieee80211_csa_finalize_work(struct work_struct *work) |
| @@ -3082,8 +3153,11 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
| 3082 | struct ieee80211_sub_if_data *sdata = | 3153 | struct ieee80211_sub_if_data *sdata = |
| 3083 | container_of(work, struct ieee80211_sub_if_data, | 3154 | container_of(work, struct ieee80211_sub_if_data, |
| 3084 | csa_finalize_work); | 3155 | csa_finalize_work); |
| 3156 | struct ieee80211_local *local = sdata->local; | ||
| 3085 | 3157 | ||
| 3086 | sdata_lock(sdata); | 3158 | sdata_lock(sdata); |
| 3159 | mutex_lock(&local->mtx); | ||
| 3160 | |||
| 3087 | /* AP might have been stopped while waiting for the lock. */ | 3161 | /* AP might have been stopped while waiting for the lock. */ |
| 3088 | if (!sdata->vif.csa_active) | 3162 | if (!sdata->vif.csa_active) |
| 3089 | goto unlock; | 3163 | goto unlock; |
| @@ -3094,6 +3168,7 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
| 3094 | ieee80211_csa_finalize(sdata); | 3168 | ieee80211_csa_finalize(sdata); |
| 3095 | 3169 | ||
| 3096 | unlock: | 3170 | unlock: |
| 3171 | mutex_unlock(&local->mtx); | ||
| 3097 | sdata_unlock(sdata); | 3172 | sdata_unlock(sdata); |
| 3098 | } | 3173 | } |
| 3099 | 3174 | ||
| @@ -3129,9 +3204,25 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
| 3129 | if (params->count <= 1) | 3204 | if (params->count <= 1) |
| 3130 | break; | 3205 | break; |
| 3131 | 3206 | ||
| 3132 | sdata->csa_counter_offset_beacon = | 3207 | if ((params->n_counter_offsets_beacon > |
| 3133 | params->counter_offset_beacon; | 3208 | IEEE80211_MAX_CSA_COUNTERS_NUM) || |
| 3134 | sdata->csa_counter_offset_presp = params->counter_offset_presp; | 3209 | (params->n_counter_offsets_presp > |
| 3210 | IEEE80211_MAX_CSA_COUNTERS_NUM)) | ||
| 3211 | return -EINVAL; | ||
| 3212 | |||
| 3213 | /* make sure we don't have garbage in other counters */ | ||
| 3214 | memset(sdata->csa_counter_offset_beacon, 0, | ||
| 3215 | sizeof(sdata->csa_counter_offset_beacon)); | ||
| 3216 | memset(sdata->csa_counter_offset_presp, 0, | ||
| 3217 | sizeof(sdata->csa_counter_offset_presp)); | ||
| 3218 | |||
| 3219 | memcpy(sdata->csa_counter_offset_beacon, | ||
| 3220 | params->counter_offsets_beacon, | ||
| 3221 | params->n_counter_offsets_beacon * sizeof(u16)); | ||
| 3222 | memcpy(sdata->csa_counter_offset_presp, | ||
| 3223 | params->counter_offsets_presp, | ||
| 3224 | params->n_counter_offsets_presp * sizeof(u16)); | ||
| 3225 | |||
| 3135 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); | 3226 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); |
| 3136 | if (err < 0) { | 3227 | if (err < 0) { |
| 3137 | kfree(sdata->u.ap.next_beacon); | 3228 | kfree(sdata->u.ap.next_beacon); |
| @@ -3220,8 +3311,9 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
| 3220 | return 0; | 3311 | return 0; |
| 3221 | } | 3312 | } |
| 3222 | 3313 | ||
| 3223 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 3314 | static int |
| 3224 | struct cfg80211_csa_settings *params) | 3315 | __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, |
| 3316 | struct cfg80211_csa_settings *params) | ||
| 3225 | { | 3317 | { |
| 3226 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3318 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 3227 | struct ieee80211_local *local = sdata->local; | 3319 | struct ieee80211_local *local = sdata->local; |
| @@ -3230,6 +3322,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
| 3230 | int err, num_chanctx, changed = 0; | 3322 | int err, num_chanctx, changed = 0; |
| 3231 | 3323 | ||
| 3232 | sdata_assert_lock(sdata); | 3324 | sdata_assert_lock(sdata); |
| 3325 | lockdep_assert_held(&local->mtx); | ||
| 3233 | 3326 | ||
| 3234 | if (!list_empty(&local->roc_list) || local->scanning) | 3327 | if (!list_empty(&local->roc_list) || local->scanning) |
| 3235 | return -EBUSY; | 3328 | return -EBUSY; |
| @@ -3272,15 +3365,16 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
| 3272 | return err; | 3365 | return err; |
| 3273 | 3366 | ||
| 3274 | sdata->csa_radar_required = params->radar_required; | 3367 | sdata->csa_radar_required = params->radar_required; |
| 3275 | |||
| 3276 | if (params->block_tx) | ||
| 3277 | ieee80211_stop_queues_by_reason(&local->hw, | ||
| 3278 | IEEE80211_MAX_QUEUE_MAP, | ||
| 3279 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
| 3280 | |||
| 3281 | sdata->csa_chandef = params->chandef; | 3368 | sdata->csa_chandef = params->chandef; |
| 3369 | sdata->csa_block_tx = params->block_tx; | ||
| 3370 | sdata->csa_current_counter = params->count; | ||
| 3282 | sdata->vif.csa_active = true; | 3371 | sdata->vif.csa_active = true; |
| 3283 | 3372 | ||
| 3373 | if (sdata->csa_block_tx) | ||
| 3374 | ieee80211_stop_queues_by_reason(&local->hw, | ||
| 3375 | IEEE80211_MAX_QUEUE_MAP, | ||
| 3376 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
| 3377 | |||
| 3284 | if (changed) { | 3378 | if (changed) { |
| 3285 | ieee80211_bss_info_change_notify(sdata, changed); | 3379 | ieee80211_bss_info_change_notify(sdata, changed); |
| 3286 | drv_channel_switch_beacon(sdata, ¶ms->chandef); | 3380 | drv_channel_switch_beacon(sdata, ¶ms->chandef); |
| @@ -3292,6 +3386,20 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
| 3292 | return 0; | 3386 | return 0; |
| 3293 | } | 3387 | } |
| 3294 | 3388 | ||
| 3389 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | ||
| 3390 | struct cfg80211_csa_settings *params) | ||
| 3391 | { | ||
| 3392 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 3393 | struct ieee80211_local *local = sdata->local; | ||
| 3394 | int err; | ||
| 3395 | |||
| 3396 | mutex_lock(&local->mtx); | ||
| 3397 | err = __ieee80211_channel_switch(wiphy, dev, params); | ||
| 3398 | mutex_unlock(&local->mtx); | ||
| 3399 | |||
| 3400 | return err; | ||
| 3401 | } | ||
| 3402 | |||
| 3295 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 3403 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
| 3296 | struct cfg80211_mgmt_tx_params *params, | 3404 | struct cfg80211_mgmt_tx_params *params, |
| 3297 | u64 *cookie) | 3405 | u64 *cookie) |
| @@ -3304,6 +3412,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
| 3304 | bool need_offchan = false; | 3412 | bool need_offchan = false; |
| 3305 | u32 flags; | 3413 | u32 flags; |
| 3306 | int ret; | 3414 | int ret; |
| 3415 | u8 *data; | ||
| 3307 | 3416 | ||
| 3308 | if (params->dont_wait_for_ack) | 3417 | if (params->dont_wait_for_ack) |
| 3309 | flags = IEEE80211_TX_CTL_NO_ACK; | 3418 | flags = IEEE80211_TX_CTL_NO_ACK; |
| @@ -3397,7 +3506,20 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
| 3397 | } | 3506 | } |
| 3398 | skb_reserve(skb, local->hw.extra_tx_headroom); | 3507 | skb_reserve(skb, local->hw.extra_tx_headroom); |
| 3399 | 3508 | ||
| 3400 | memcpy(skb_put(skb, params->len), params->buf, params->len); | 3509 | data = skb_put(skb, params->len); |
| 3510 | memcpy(data, params->buf, params->len); | ||
| 3511 | |||
| 3512 | /* Update CSA counters */ | ||
| 3513 | if (sdata->vif.csa_active && | ||
| 3514 | (sdata->vif.type == NL80211_IFTYPE_AP || | ||
| 3515 | sdata->vif.type == NL80211_IFTYPE_ADHOC) && | ||
| 3516 | params->n_csa_offsets) { | ||
| 3517 | int i; | ||
| 3518 | u8 c = sdata->csa_current_counter; | ||
| 3519 | |||
| 3520 | for (i = 0; i < params->n_csa_offsets; i++) | ||
| 3521 | data[params->csa_offsets[i]] = c; | ||
| 3522 | } | ||
| 3401 | 3523 | ||
| 3402 | IEEE80211_SKB_CB(skb)->flags = flags; | 3524 | IEEE80211_SKB_CB(skb)->flags = flags; |
| 3403 | 3525 | ||
| @@ -3506,320 +3628,6 @@ static int ieee80211_set_rekey_data(struct wiphy *wiphy, | |||
| 3506 | return 0; | 3628 | return 0; |
| 3507 | } | 3629 | } |
| 3508 | 3630 | ||
| 3509 | static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) | ||
| 3510 | { | ||
| 3511 | u8 *pos = (void *)skb_put(skb, 7); | ||
| 3512 | |||
| 3513 | *pos++ = WLAN_EID_EXT_CAPABILITY; | ||
| 3514 | *pos++ = 5; /* len */ | ||
| 3515 | *pos++ = 0x0; | ||
| 3516 | *pos++ = 0x0; | ||
| 3517 | *pos++ = 0x0; | ||
| 3518 | *pos++ = 0x0; | ||
| 3519 | *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; | ||
| 3520 | } | ||
| 3521 | |||
| 3522 | static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) | ||
| 3523 | { | ||
| 3524 | struct ieee80211_local *local = sdata->local; | ||
| 3525 | u16 capab; | ||
| 3526 | |||
| 3527 | capab = 0; | ||
| 3528 | if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) | ||
| 3529 | return capab; | ||
| 3530 | |||
| 3531 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) | ||
| 3532 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; | ||
| 3533 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) | ||
| 3534 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
| 3535 | |||
| 3536 | return capab; | ||
| 3537 | } | ||
| 3538 | |||
| 3539 | static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, | ||
| 3540 | u8 *peer, u8 *bssid) | ||
| 3541 | { | ||
| 3542 | struct ieee80211_tdls_lnkie *lnkid; | ||
| 3543 | |||
| 3544 | lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); | ||
| 3545 | |||
| 3546 | lnkid->ie_type = WLAN_EID_LINK_ID; | ||
| 3547 | lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; | ||
| 3548 | |||
| 3549 | memcpy(lnkid->bssid, bssid, ETH_ALEN); | ||
| 3550 | memcpy(lnkid->init_sta, src_addr, ETH_ALEN); | ||
| 3551 | memcpy(lnkid->resp_sta, peer, ETH_ALEN); | ||
| 3552 | } | ||
| 3553 | |||
| 3554 | static int | ||
| 3555 | ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | ||
| 3556 | u8 *peer, u8 action_code, u8 dialog_token, | ||
| 3557 | u16 status_code, struct sk_buff *skb) | ||
| 3558 | { | ||
| 3559 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 3560 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
| 3561 | struct ieee80211_tdls_data *tf; | ||
| 3562 | |||
| 3563 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | ||
| 3564 | |||
| 3565 | memcpy(tf->da, peer, ETH_ALEN); | ||
| 3566 | memcpy(tf->sa, sdata->vif.addr, ETH_ALEN); | ||
| 3567 | tf->ether_type = cpu_to_be16(ETH_P_TDLS); | ||
| 3568 | tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; | ||
| 3569 | |||
| 3570 | switch (action_code) { | ||
| 3571 | case WLAN_TDLS_SETUP_REQUEST: | ||
| 3572 | tf->category = WLAN_CATEGORY_TDLS; | ||
| 3573 | tf->action_code = WLAN_TDLS_SETUP_REQUEST; | ||
| 3574 | |||
| 3575 | skb_put(skb, sizeof(tf->u.setup_req)); | ||
| 3576 | tf->u.setup_req.dialog_token = dialog_token; | ||
| 3577 | tf->u.setup_req.capability = | ||
| 3578 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | ||
| 3579 | |||
| 3580 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
| 3581 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
| 3582 | ieee80211_tdls_add_ext_capab(skb); | ||
| 3583 | break; | ||
| 3584 | case WLAN_TDLS_SETUP_RESPONSE: | ||
| 3585 | tf->category = WLAN_CATEGORY_TDLS; | ||
| 3586 | tf->action_code = WLAN_TDLS_SETUP_RESPONSE; | ||
| 3587 | |||
| 3588 | skb_put(skb, sizeof(tf->u.setup_resp)); | ||
| 3589 | tf->u.setup_resp.status_code = cpu_to_le16(status_code); | ||
| 3590 | tf->u.setup_resp.dialog_token = dialog_token; | ||
| 3591 | tf->u.setup_resp.capability = | ||
| 3592 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | ||
| 3593 | |||
| 3594 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
| 3595 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
| 3596 | ieee80211_tdls_add_ext_capab(skb); | ||
| 3597 | break; | ||
| 3598 | case WLAN_TDLS_SETUP_CONFIRM: | ||
| 3599 | tf->category = WLAN_CATEGORY_TDLS; | ||
| 3600 | tf->action_code = WLAN_TDLS_SETUP_CONFIRM; | ||
| 3601 | |||
| 3602 | skb_put(skb, sizeof(tf->u.setup_cfm)); | ||
| 3603 | tf->u.setup_cfm.status_code = cpu_to_le16(status_code); | ||
| 3604 | tf->u.setup_cfm.dialog_token = dialog_token; | ||
| 3605 | break; | ||
| 3606 | case WLAN_TDLS_TEARDOWN: | ||
| 3607 | tf->category = WLAN_CATEGORY_TDLS; | ||
| 3608 | tf->action_code = WLAN_TDLS_TEARDOWN; | ||
| 3609 | |||
| 3610 | skb_put(skb, sizeof(tf->u.teardown)); | ||
| 3611 | tf->u.teardown.reason_code = cpu_to_le16(status_code); | ||
| 3612 | break; | ||
| 3613 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
| 3614 | tf->category = WLAN_CATEGORY_TDLS; | ||
| 3615 | tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; | ||
| 3616 | |||
| 3617 | skb_put(skb, sizeof(tf->u.discover_req)); | ||
| 3618 | tf->u.discover_req.dialog_token = dialog_token; | ||
| 3619 | break; | ||
| 3620 | default: | ||
| 3621 | return -EINVAL; | ||
| 3622 | } | ||
| 3623 | |||
| 3624 | return 0; | ||
| 3625 | } | ||
| 3626 | |||
| 3627 | static int | ||
| 3628 | ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | ||
| 3629 | u8 *peer, u8 action_code, u8 dialog_token, | ||
| 3630 | u16 status_code, struct sk_buff *skb) | ||
| 3631 | { | ||
| 3632 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 3633 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
| 3634 | struct ieee80211_mgmt *mgmt; | ||
| 3635 | |||
| 3636 | mgmt = (void *)skb_put(skb, 24); | ||
| 3637 | memset(mgmt, 0, 24); | ||
| 3638 | memcpy(mgmt->da, peer, ETH_ALEN); | ||
| 3639 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
| 3640 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | ||
| 3641 | |||
| 3642 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
| 3643 | IEEE80211_STYPE_ACTION); | ||
| 3644 | |||
| 3645 | switch (action_code) { | ||
| 3646 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
| 3647 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); | ||
| 3648 | mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; | ||
| 3649 | mgmt->u.action.u.tdls_discover_resp.action_code = | ||
| 3650 | WLAN_PUB_ACTION_TDLS_DISCOVER_RES; | ||
| 3651 | mgmt->u.action.u.tdls_discover_resp.dialog_token = | ||
| 3652 | dialog_token; | ||
| 3653 | mgmt->u.action.u.tdls_discover_resp.capability = | ||
| 3654 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | ||
| 3655 | |||
| 3656 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
| 3657 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
| 3658 | ieee80211_tdls_add_ext_capab(skb); | ||
| 3659 | break; | ||
| 3660 | default: | ||
| 3661 | return -EINVAL; | ||
| 3662 | } | ||
| 3663 | |||
| 3664 | return 0; | ||
| 3665 | } | ||
| 3666 | |||
| 3667 | static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | ||
| 3668 | u8 *peer, u8 action_code, u8 dialog_token, | ||
| 3669 | u16 status_code, u32 peer_capability, | ||
| 3670 | const u8 *extra_ies, size_t extra_ies_len) | ||
| 3671 | { | ||
| 3672 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 3673 | struct ieee80211_local *local = sdata->local; | ||
| 3674 | struct sk_buff *skb = NULL; | ||
| 3675 | bool send_direct; | ||
| 3676 | int ret; | ||
| 3677 | |||
| 3678 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
| 3679 | return -ENOTSUPP; | ||
| 3680 | |||
| 3681 | /* make sure we are in managed mode, and associated */ | ||
| 3682 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | ||
| 3683 | !sdata->u.mgd.associated) | ||
| 3684 | return -EINVAL; | ||
| 3685 | |||
| 3686 | tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n", | ||
| 3687 | action_code, peer); | ||
| 3688 | |||
| 3689 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
| 3690 | max(sizeof(struct ieee80211_mgmt), | ||
| 3691 | sizeof(struct ieee80211_tdls_data)) + | ||
| 3692 | 50 + /* supported rates */ | ||
| 3693 | 7 + /* ext capab */ | ||
| 3694 | extra_ies_len + | ||
| 3695 | sizeof(struct ieee80211_tdls_lnkie)); | ||
| 3696 | if (!skb) | ||
| 3697 | return -ENOMEM; | ||
| 3698 | |||
| 3699 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
| 3700 | |||
| 3701 | switch (action_code) { | ||
| 3702 | case WLAN_TDLS_SETUP_REQUEST: | ||
| 3703 | case WLAN_TDLS_SETUP_RESPONSE: | ||
| 3704 | case WLAN_TDLS_SETUP_CONFIRM: | ||
| 3705 | case WLAN_TDLS_TEARDOWN: | ||
| 3706 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
| 3707 | ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer, | ||
| 3708 | action_code, dialog_token, | ||
| 3709 | status_code, skb); | ||
| 3710 | send_direct = false; | ||
| 3711 | break; | ||
| 3712 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
| 3713 | ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code, | ||
| 3714 | dialog_token, status_code, | ||
| 3715 | skb); | ||
| 3716 | send_direct = true; | ||
| 3717 | break; | ||
| 3718 | default: | ||
| 3719 | ret = -ENOTSUPP; | ||
| 3720 | break; | ||
| 3721 | } | ||
| 3722 | |||
| 3723 | if (ret < 0) | ||
| 3724 | goto fail; | ||
| 3725 | |||
| 3726 | if (extra_ies_len) | ||
| 3727 | memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); | ||
| 3728 | |||
| 3729 | /* the TDLS link IE is always added last */ | ||
| 3730 | switch (action_code) { | ||
| 3731 | case WLAN_TDLS_SETUP_REQUEST: | ||
| 3732 | case WLAN_TDLS_SETUP_CONFIRM: | ||
| 3733 | case WLAN_TDLS_TEARDOWN: | ||
| 3734 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
| 3735 | /* we are the initiator */ | ||
| 3736 | ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer, | ||
| 3737 | sdata->u.mgd.bssid); | ||
| 3738 | break; | ||
| 3739 | case WLAN_TDLS_SETUP_RESPONSE: | ||
| 3740 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
| 3741 | /* we are the responder */ | ||
| 3742 | ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr, | ||
| 3743 | sdata->u.mgd.bssid); | ||
| 3744 | break; | ||
| 3745 | default: | ||
| 3746 | ret = -ENOTSUPP; | ||
| 3747 | goto fail; | ||
| 3748 | } | ||
| 3749 | |||
| 3750 | if (send_direct) { | ||
| 3751 | ieee80211_tx_skb(sdata, skb); | ||
| 3752 | return 0; | ||
| 3753 | } | ||
| 3754 | |||
| 3755 | /* | ||
| 3756 | * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise | ||
| 3757 | * we should default to AC_VI. | ||
| 3758 | */ | ||
| 3759 | switch (action_code) { | ||
| 3760 | case WLAN_TDLS_SETUP_REQUEST: | ||
| 3761 | case WLAN_TDLS_SETUP_RESPONSE: | ||
| 3762 | skb_set_queue_mapping(skb, IEEE80211_AC_BK); | ||
| 3763 | skb->priority = 2; | ||
| 3764 | break; | ||
| 3765 | default: | ||
| 3766 | skb_set_queue_mapping(skb, IEEE80211_AC_VI); | ||
| 3767 | skb->priority = 5; | ||
| 3768 | break; | ||
| 3769 | } | ||
| 3770 | |||
| 3771 | /* disable bottom halves when entering the Tx path */ | ||
| 3772 | local_bh_disable(); | ||
| 3773 | ret = ieee80211_subif_start_xmit(skb, dev); | ||
| 3774 | local_bh_enable(); | ||
| 3775 | |||
| 3776 | return ret; | ||
| 3777 | |||
| 3778 | fail: | ||
| 3779 | dev_kfree_skb(skb); | ||
| 3780 | return ret; | ||
| 3781 | } | ||
| 3782 | |||
| 3783 | static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | ||
| 3784 | u8 *peer, enum nl80211_tdls_operation oper) | ||
| 3785 | { | ||
| 3786 | struct sta_info *sta; | ||
| 3787 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 3788 | |||
| 3789 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
| 3790 | return -ENOTSUPP; | ||
| 3791 | |||
| 3792 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
| 3793 | return -EINVAL; | ||
| 3794 | |||
| 3795 | tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer); | ||
| 3796 | |||
| 3797 | switch (oper) { | ||
| 3798 | case NL80211_TDLS_ENABLE_LINK: | ||
| 3799 | rcu_read_lock(); | ||
| 3800 | sta = sta_info_get(sdata, peer); | ||
| 3801 | if (!sta) { | ||
| 3802 | rcu_read_unlock(); | ||
| 3803 | return -ENOLINK; | ||
| 3804 | } | ||
| 3805 | |||
| 3806 | set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); | ||
| 3807 | rcu_read_unlock(); | ||
| 3808 | break; | ||
| 3809 | case NL80211_TDLS_DISABLE_LINK: | ||
| 3810 | return sta_info_destroy_addr(sdata, peer); | ||
| 3811 | case NL80211_TDLS_TEARDOWN: | ||
| 3812 | case NL80211_TDLS_SETUP: | ||
| 3813 | case NL80211_TDLS_DISCOVERY_REQ: | ||
| 3814 | /* We don't support in-driver setup/teardown/discovery */ | ||
| 3815 | return -ENOTSUPP; | ||
| 3816 | default: | ||
| 3817 | return -ENOTSUPP; | ||
| 3818 | } | ||
| 3819 | |||
| 3820 | return 0; | ||
| 3821 | } | ||
| 3822 | |||
| 3823 | static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | 3631 | static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, |
| 3824 | const u8 *peer, u64 *cookie) | 3632 | const u8 *peer, u64 *cookie) |
| 3825 | { | 3633 | { |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 48e6d6f010cd..a310e33972de 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
| @@ -855,7 +855,7 @@ static void | |||
| 855 | __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, | 855 | __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, |
| 856 | bool clear) | 856 | bool clear) |
| 857 | { | 857 | { |
| 858 | struct ieee80211_local *local = sdata->local; | 858 | struct ieee80211_local *local __maybe_unused = sdata->local; |
| 859 | struct ieee80211_sub_if_data *vlan; | 859 | struct ieee80211_sub_if_data *vlan; |
| 860 | struct ieee80211_chanctx_conf *conf; | 860 | struct ieee80211_chanctx_conf *conf; |
| 861 | 861 | ||
| @@ -871,7 +871,7 @@ __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, | |||
| 871 | * to a channel context that has already been freed. | 871 | * to a channel context that has already been freed. |
| 872 | */ | 872 | */ |
| 873 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | 873 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, |
| 874 | lockdep_is_held(&local->chanctx_mtx)); | 874 | lockdep_is_held(&local->chanctx_mtx)); |
| 875 | WARN_ON(!conf); | 875 | WARN_ON(!conf); |
| 876 | 876 | ||
| 877 | if (clear) | 877 | if (clear) |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 5331582a2c81..696ef78b1fb7 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
| @@ -5,11 +5,11 @@ | |||
| 5 | #include "ieee80211_i.h" | 5 | #include "ieee80211_i.h" |
| 6 | #include "trace.h" | 6 | #include "trace.h" |
| 7 | 7 | ||
| 8 | static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) | 8 | static inline bool check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) |
| 9 | { | 9 | { |
| 10 | WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), | 10 | return !WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), |
| 11 | "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", | 11 | "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", |
| 12 | sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); | 12 | sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | static inline struct ieee80211_sub_if_data * | 15 | static inline struct ieee80211_sub_if_data * |
| @@ -168,7 +168,8 @@ static inline int drv_change_interface(struct ieee80211_local *local, | |||
| 168 | 168 | ||
| 169 | might_sleep(); | 169 | might_sleep(); |
| 170 | 170 | ||
| 171 | check_sdata_in_driver(sdata); | 171 | if (!check_sdata_in_driver(sdata)) |
| 172 | return -EIO; | ||
| 172 | 173 | ||
| 173 | trace_drv_change_interface(local, sdata, type, p2p); | 174 | trace_drv_change_interface(local, sdata, type, p2p); |
| 174 | ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); | 175 | ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); |
| @@ -181,7 +182,8 @@ static inline void drv_remove_interface(struct ieee80211_local *local, | |||
| 181 | { | 182 | { |
| 182 | might_sleep(); | 183 | might_sleep(); |
| 183 | 184 | ||
| 184 | check_sdata_in_driver(sdata); | 185 | if (!check_sdata_in_driver(sdata)) |
| 186 | return; | ||
| 185 | 187 | ||
| 186 | trace_drv_remove_interface(local, sdata); | 188 | trace_drv_remove_interface(local, sdata); |
| 187 | local->ops->remove_interface(&local->hw, &sdata->vif); | 189 | local->ops->remove_interface(&local->hw, &sdata->vif); |
| @@ -219,7 +221,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
| 219 | sdata->vif.type == NL80211_IFTYPE_MONITOR)) | 221 | sdata->vif.type == NL80211_IFTYPE_MONITOR)) |
| 220 | return; | 222 | return; |
| 221 | 223 | ||
| 222 | check_sdata_in_driver(sdata); | 224 | if (!check_sdata_in_driver(sdata)) |
| 225 | return; | ||
| 223 | 226 | ||
| 224 | trace_drv_bss_info_changed(local, sdata, info, changed); | 227 | trace_drv_bss_info_changed(local, sdata, info, changed); |
| 225 | if (local->ops->bss_info_changed) | 228 | if (local->ops->bss_info_changed) |
| @@ -278,7 +281,8 @@ static inline int drv_set_key(struct ieee80211_local *local, | |||
| 278 | might_sleep(); | 281 | might_sleep(); |
| 279 | 282 | ||
| 280 | sdata = get_bss_sdata(sdata); | 283 | sdata = get_bss_sdata(sdata); |
| 281 | check_sdata_in_driver(sdata); | 284 | if (!check_sdata_in_driver(sdata)) |
| 285 | return -EIO; | ||
| 282 | 286 | ||
| 283 | trace_drv_set_key(local, cmd, sdata, sta, key); | 287 | trace_drv_set_key(local, cmd, sdata, sta, key); |
| 284 | ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); | 288 | ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); |
| @@ -298,7 +302,8 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
| 298 | ista = &sta->sta; | 302 | ista = &sta->sta; |
| 299 | 303 | ||
| 300 | sdata = get_bss_sdata(sdata); | 304 | sdata = get_bss_sdata(sdata); |
| 301 | check_sdata_in_driver(sdata); | 305 | if (!check_sdata_in_driver(sdata)) |
| 306 | return; | ||
| 302 | 307 | ||
| 303 | trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); | 308 | trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); |
| 304 | if (local->ops->update_tkip_key) | 309 | if (local->ops->update_tkip_key) |
| @@ -315,7 +320,8 @@ static inline int drv_hw_scan(struct ieee80211_local *local, | |||
| 315 | 320 | ||
| 316 | might_sleep(); | 321 | might_sleep(); |
| 317 | 322 | ||
| 318 | check_sdata_in_driver(sdata); | 323 | if (!check_sdata_in_driver(sdata)) |
| 324 | return -EIO; | ||
| 319 | 325 | ||
| 320 | trace_drv_hw_scan(local, sdata); | 326 | trace_drv_hw_scan(local, sdata); |
| 321 | ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); | 327 | ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); |
| @@ -328,7 +334,8 @@ static inline void drv_cancel_hw_scan(struct ieee80211_local *local, | |||
| 328 | { | 334 | { |
| 329 | might_sleep(); | 335 | might_sleep(); |
| 330 | 336 | ||
| 331 | check_sdata_in_driver(sdata); | 337 | if (!check_sdata_in_driver(sdata)) |
| 338 | return; | ||
| 332 | 339 | ||
| 333 | trace_drv_cancel_hw_scan(local, sdata); | 340 | trace_drv_cancel_hw_scan(local, sdata); |
| 334 | local->ops->cancel_hw_scan(&local->hw, &sdata->vif); | 341 | local->ops->cancel_hw_scan(&local->hw, &sdata->vif); |
| @@ -345,7 +352,8 @@ drv_sched_scan_start(struct ieee80211_local *local, | |||
| 345 | 352 | ||
| 346 | might_sleep(); | 353 | might_sleep(); |
| 347 | 354 | ||
| 348 | check_sdata_in_driver(sdata); | 355 | if (!check_sdata_in_driver(sdata)) |
| 356 | return -EIO; | ||
| 349 | 357 | ||
| 350 | trace_drv_sched_scan_start(local, sdata); | 358 | trace_drv_sched_scan_start(local, sdata); |
| 351 | ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, | 359 | ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, |
| @@ -361,7 +369,8 @@ static inline int drv_sched_scan_stop(struct ieee80211_local *local, | |||
| 361 | 369 | ||
| 362 | might_sleep(); | 370 | might_sleep(); |
| 363 | 371 | ||
| 364 | check_sdata_in_driver(sdata); | 372 | if (!check_sdata_in_driver(sdata)) |
| 373 | return -EIO; | ||
| 365 | 374 | ||
| 366 | trace_drv_sched_scan_stop(local, sdata); | 375 | trace_drv_sched_scan_stop(local, sdata); |
| 367 | ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif); | 376 | ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif); |
| @@ -462,7 +471,8 @@ static inline void drv_sta_notify(struct ieee80211_local *local, | |||
| 462 | struct ieee80211_sta *sta) | 471 | struct ieee80211_sta *sta) |
| 463 | { | 472 | { |
| 464 | sdata = get_bss_sdata(sdata); | 473 | sdata = get_bss_sdata(sdata); |
| 465 | check_sdata_in_driver(sdata); | 474 | if (!check_sdata_in_driver(sdata)) |
| 475 | return; | ||
| 466 | 476 | ||
| 467 | trace_drv_sta_notify(local, sdata, cmd, sta); | 477 | trace_drv_sta_notify(local, sdata, cmd, sta); |
| 468 | if (local->ops->sta_notify) | 478 | if (local->ops->sta_notify) |
| @@ -479,7 +489,8 @@ static inline int drv_sta_add(struct ieee80211_local *local, | |||
| 479 | might_sleep(); | 489 | might_sleep(); |
| 480 | 490 | ||
| 481 | sdata = get_bss_sdata(sdata); | 491 | sdata = get_bss_sdata(sdata); |
| 482 | check_sdata_in_driver(sdata); | 492 | if (!check_sdata_in_driver(sdata)) |
| 493 | return -EIO; | ||
| 483 | 494 | ||
| 484 | trace_drv_sta_add(local, sdata, sta); | 495 | trace_drv_sta_add(local, sdata, sta); |
| 485 | if (local->ops->sta_add) | 496 | if (local->ops->sta_add) |
| @@ -497,7 +508,8 @@ static inline void drv_sta_remove(struct ieee80211_local *local, | |||
| 497 | might_sleep(); | 508 | might_sleep(); |
| 498 | 509 | ||
| 499 | sdata = get_bss_sdata(sdata); | 510 | sdata = get_bss_sdata(sdata); |
| 500 | check_sdata_in_driver(sdata); | 511 | if (!check_sdata_in_driver(sdata)) |
| 512 | return; | ||
| 501 | 513 | ||
| 502 | trace_drv_sta_remove(local, sdata, sta); | 514 | trace_drv_sta_remove(local, sdata, sta); |
| 503 | if (local->ops->sta_remove) | 515 | if (local->ops->sta_remove) |
| @@ -515,7 +527,8 @@ static inline void drv_sta_add_debugfs(struct ieee80211_local *local, | |||
| 515 | might_sleep(); | 527 | might_sleep(); |
| 516 | 528 | ||
| 517 | sdata = get_bss_sdata(sdata); | 529 | sdata = get_bss_sdata(sdata); |
| 518 | check_sdata_in_driver(sdata); | 530 | if (!check_sdata_in_driver(sdata)) |
| 531 | return; | ||
| 519 | 532 | ||
| 520 | if (local->ops->sta_add_debugfs) | 533 | if (local->ops->sta_add_debugfs) |
| 521 | local->ops->sta_add_debugfs(&local->hw, &sdata->vif, | 534 | local->ops->sta_add_debugfs(&local->hw, &sdata->vif, |
| @@ -545,7 +558,8 @@ static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local, | |||
| 545 | might_sleep(); | 558 | might_sleep(); |
| 546 | 559 | ||
| 547 | sdata = get_bss_sdata(sdata); | 560 | sdata = get_bss_sdata(sdata); |
| 548 | check_sdata_in_driver(sdata); | 561 | if (!check_sdata_in_driver(sdata)) |
| 562 | return; | ||
| 549 | 563 | ||
| 550 | trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta); | 564 | trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta); |
| 551 | if (local->ops->sta_pre_rcu_remove) | 565 | if (local->ops->sta_pre_rcu_remove) |
| @@ -566,7 +580,8 @@ int drv_sta_state(struct ieee80211_local *local, | |||
| 566 | might_sleep(); | 580 | might_sleep(); |
| 567 | 581 | ||
| 568 | sdata = get_bss_sdata(sdata); | 582 | sdata = get_bss_sdata(sdata); |
| 569 | check_sdata_in_driver(sdata); | 583 | if (!check_sdata_in_driver(sdata)) |
| 584 | return -EIO; | ||
| 570 | 585 | ||
| 571 | trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); | 586 | trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); |
| 572 | if (local->ops->sta_state) { | 587 | if (local->ops->sta_state) { |
| @@ -590,7 +605,8 @@ static inline void drv_sta_rc_update(struct ieee80211_local *local, | |||
| 590 | struct ieee80211_sta *sta, u32 changed) | 605 | struct ieee80211_sta *sta, u32 changed) |
| 591 | { | 606 | { |
| 592 | sdata = get_bss_sdata(sdata); | 607 | sdata = get_bss_sdata(sdata); |
| 593 | check_sdata_in_driver(sdata); | 608 | if (!check_sdata_in_driver(sdata)) |
| 609 | return; | ||
| 594 | 610 | ||
| 595 | WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && | 611 | WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && |
| 596 | (sdata->vif.type != NL80211_IFTYPE_ADHOC && | 612 | (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
| @@ -612,7 +628,8 @@ static inline int drv_conf_tx(struct ieee80211_local *local, | |||
| 612 | 628 | ||
| 613 | might_sleep(); | 629 | might_sleep(); |
| 614 | 630 | ||
| 615 | check_sdata_in_driver(sdata); | 631 | if (!check_sdata_in_driver(sdata)) |
| 632 | return -EIO; | ||
| 616 | 633 | ||
| 617 | trace_drv_conf_tx(local, sdata, ac, params); | 634 | trace_drv_conf_tx(local, sdata, ac, params); |
| 618 | if (local->ops->conf_tx) | 635 | if (local->ops->conf_tx) |
| @@ -629,7 +646,8 @@ static inline u64 drv_get_tsf(struct ieee80211_local *local, | |||
| 629 | 646 | ||
| 630 | might_sleep(); | 647 | might_sleep(); |
| 631 | 648 | ||
| 632 | check_sdata_in_driver(sdata); | 649 | if (!check_sdata_in_driver(sdata)) |
| 650 | return ret; | ||
| 633 | 651 | ||
| 634 | trace_drv_get_tsf(local, sdata); | 652 | trace_drv_get_tsf(local, sdata); |
| 635 | if (local->ops->get_tsf) | 653 | if (local->ops->get_tsf) |
| @@ -644,7 +662,8 @@ static inline void drv_set_tsf(struct ieee80211_local *local, | |||
| 644 | { | 662 | { |
| 645 | might_sleep(); | 663 | might_sleep(); |
| 646 | 664 | ||
| 647 | check_sdata_in_driver(sdata); | 665 | if (!check_sdata_in_driver(sdata)) |
| 666 | return; | ||
| 648 | 667 | ||
| 649 | trace_drv_set_tsf(local, sdata, tsf); | 668 | trace_drv_set_tsf(local, sdata, tsf); |
| 650 | if (local->ops->set_tsf) | 669 | if (local->ops->set_tsf) |
| @@ -657,7 +676,8 @@ static inline void drv_reset_tsf(struct ieee80211_local *local, | |||
| 657 | { | 676 | { |
| 658 | might_sleep(); | 677 | might_sleep(); |
| 659 | 678 | ||
| 660 | check_sdata_in_driver(sdata); | 679 | if (!check_sdata_in_driver(sdata)) |
| 680 | return; | ||
| 661 | 681 | ||
| 662 | trace_drv_reset_tsf(local, sdata); | 682 | trace_drv_reset_tsf(local, sdata); |
| 663 | if (local->ops->reset_tsf) | 683 | if (local->ops->reset_tsf) |
| @@ -689,7 +709,8 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, | |||
| 689 | might_sleep(); | 709 | might_sleep(); |
| 690 | 710 | ||
| 691 | sdata = get_bss_sdata(sdata); | 711 | sdata = get_bss_sdata(sdata); |
| 692 | check_sdata_in_driver(sdata); | 712 | if (!check_sdata_in_driver(sdata)) |
| 713 | return -EIO; | ||
| 693 | 714 | ||
| 694 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); | 715 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); |
| 695 | 716 | ||
| @@ -733,8 +754,8 @@ static inline void drv_flush(struct ieee80211_local *local, | |||
| 733 | 754 | ||
| 734 | might_sleep(); | 755 | might_sleep(); |
| 735 | 756 | ||
| 736 | if (sdata) | 757 | if (sdata && !check_sdata_in_driver(sdata)) |
| 737 | check_sdata_in_driver(sdata); | 758 | return; |
| 738 | 759 | ||
| 739 | trace_drv_flush(local, queues, drop); | 760 | trace_drv_flush(local, queues, drop); |
| 740 | if (local->ops->flush) | 761 | if (local->ops->flush) |
| @@ -854,7 +875,8 @@ static inline int drv_set_bitrate_mask(struct ieee80211_local *local, | |||
| 854 | 875 | ||
| 855 | might_sleep(); | 876 | might_sleep(); |
| 856 | 877 | ||
| 857 | check_sdata_in_driver(sdata); | 878 | if (!check_sdata_in_driver(sdata)) |
| 879 | return -EIO; | ||
| 858 | 880 | ||
| 859 | trace_drv_set_bitrate_mask(local, sdata, mask); | 881 | trace_drv_set_bitrate_mask(local, sdata, mask); |
| 860 | if (local->ops->set_bitrate_mask) | 882 | if (local->ops->set_bitrate_mask) |
| @@ -869,7 +891,8 @@ static inline void drv_set_rekey_data(struct ieee80211_local *local, | |||
| 869 | struct ieee80211_sub_if_data *sdata, | 891 | struct ieee80211_sub_if_data *sdata, |
| 870 | struct cfg80211_gtk_rekey_data *data) | 892 | struct cfg80211_gtk_rekey_data *data) |
| 871 | { | 893 | { |
| 872 | check_sdata_in_driver(sdata); | 894 | if (!check_sdata_in_driver(sdata)) |
| 895 | return; | ||
| 873 | 896 | ||
| 874 | trace_drv_set_rekey_data(local, sdata, data); | 897 | trace_drv_set_rekey_data(local, sdata, data); |
| 875 | if (local->ops->set_rekey_data) | 898 | if (local->ops->set_rekey_data) |
| @@ -937,7 +960,8 @@ static inline void drv_mgd_prepare_tx(struct ieee80211_local *local, | |||
| 937 | { | 960 | { |
| 938 | might_sleep(); | 961 | might_sleep(); |
| 939 | 962 | ||
| 940 | check_sdata_in_driver(sdata); | 963 | if (!check_sdata_in_driver(sdata)) |
| 964 | return; | ||
| 941 | WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); | 965 | WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); |
| 942 | 966 | ||
| 943 | trace_drv_mgd_prepare_tx(local, sdata); | 967 | trace_drv_mgd_prepare_tx(local, sdata); |
| @@ -964,6 +988,9 @@ static inline int drv_add_chanctx(struct ieee80211_local *local, | |||
| 964 | static inline void drv_remove_chanctx(struct ieee80211_local *local, | 988 | static inline void drv_remove_chanctx(struct ieee80211_local *local, |
| 965 | struct ieee80211_chanctx *ctx) | 989 | struct ieee80211_chanctx *ctx) |
| 966 | { | 990 | { |
| 991 | if (WARN_ON(!ctx->driver_present)) | ||
| 992 | return; | ||
| 993 | |||
| 967 | trace_drv_remove_chanctx(local, ctx); | 994 | trace_drv_remove_chanctx(local, ctx); |
| 968 | if (local->ops->remove_chanctx) | 995 | if (local->ops->remove_chanctx) |
| 969 | local->ops->remove_chanctx(&local->hw, &ctx->conf); | 996 | local->ops->remove_chanctx(&local->hw, &ctx->conf); |
| @@ -989,7 +1016,8 @@ static inline int drv_assign_vif_chanctx(struct ieee80211_local *local, | |||
| 989 | { | 1016 | { |
| 990 | int ret = 0; | 1017 | int ret = 0; |
| 991 | 1018 | ||
| 992 | check_sdata_in_driver(sdata); | 1019 | if (!check_sdata_in_driver(sdata)) |
| 1020 | return -EIO; | ||
| 993 | 1021 | ||
| 994 | trace_drv_assign_vif_chanctx(local, sdata, ctx); | 1022 | trace_drv_assign_vif_chanctx(local, sdata, ctx); |
| 995 | if (local->ops->assign_vif_chanctx) { | 1023 | if (local->ops->assign_vif_chanctx) { |
| @@ -1007,7 +1035,8 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local, | |||
| 1007 | struct ieee80211_sub_if_data *sdata, | 1035 | struct ieee80211_sub_if_data *sdata, |
| 1008 | struct ieee80211_chanctx *ctx) | 1036 | struct ieee80211_chanctx *ctx) |
| 1009 | { | 1037 | { |
| 1010 | check_sdata_in_driver(sdata); | 1038 | if (!check_sdata_in_driver(sdata)) |
| 1039 | return; | ||
| 1011 | 1040 | ||
| 1012 | trace_drv_unassign_vif_chanctx(local, sdata, ctx); | 1041 | trace_drv_unassign_vif_chanctx(local, sdata, ctx); |
| 1013 | if (local->ops->unassign_vif_chanctx) { | 1042 | if (local->ops->unassign_vif_chanctx) { |
| @@ -1024,7 +1053,8 @@ static inline int drv_start_ap(struct ieee80211_local *local, | |||
| 1024 | { | 1053 | { |
| 1025 | int ret = 0; | 1054 | int ret = 0; |
| 1026 | 1055 | ||
| 1027 | check_sdata_in_driver(sdata); | 1056 | if (!check_sdata_in_driver(sdata)) |
| 1057 | return -EIO; | ||
| 1028 | 1058 | ||
| 1029 | trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf); | 1059 | trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf); |
| 1030 | if (local->ops->start_ap) | 1060 | if (local->ops->start_ap) |
| @@ -1036,7 +1066,8 @@ static inline int drv_start_ap(struct ieee80211_local *local, | |||
| 1036 | static inline void drv_stop_ap(struct ieee80211_local *local, | 1066 | static inline void drv_stop_ap(struct ieee80211_local *local, |
| 1037 | struct ieee80211_sub_if_data *sdata) | 1067 | struct ieee80211_sub_if_data *sdata) |
| 1038 | { | 1068 | { |
| 1039 | check_sdata_in_driver(sdata); | 1069 | if (!check_sdata_in_driver(sdata)) |
| 1070 | return; | ||
| 1040 | 1071 | ||
| 1041 | trace_drv_stop_ap(local, sdata); | 1072 | trace_drv_stop_ap(local, sdata); |
| 1042 | if (local->ops->stop_ap) | 1073 | if (local->ops->stop_ap) |
| @@ -1059,7 +1090,8 @@ drv_set_default_unicast_key(struct ieee80211_local *local, | |||
| 1059 | struct ieee80211_sub_if_data *sdata, | 1090 | struct ieee80211_sub_if_data *sdata, |
| 1060 | int key_idx) | 1091 | int key_idx) |
| 1061 | { | 1092 | { |
| 1062 | check_sdata_in_driver(sdata); | 1093 | if (!check_sdata_in_driver(sdata)) |
| 1094 | return; | ||
| 1063 | 1095 | ||
| 1064 | WARN_ON_ONCE(key_idx < -1 || key_idx > 3); | 1096 | WARN_ON_ONCE(key_idx < -1 || key_idx > 3); |
| 1065 | 1097 | ||
| @@ -1101,7 +1133,8 @@ static inline int drv_join_ibss(struct ieee80211_local *local, | |||
| 1101 | int ret = 0; | 1133 | int ret = 0; |
| 1102 | 1134 | ||
| 1103 | might_sleep(); | 1135 | might_sleep(); |
| 1104 | check_sdata_in_driver(sdata); | 1136 | if (!check_sdata_in_driver(sdata)) |
| 1137 | return -EIO; | ||
| 1105 | 1138 | ||
| 1106 | trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf); | 1139 | trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf); |
| 1107 | if (local->ops->join_ibss) | 1140 | if (local->ops->join_ibss) |
| @@ -1114,7 +1147,8 @@ static inline void drv_leave_ibss(struct ieee80211_local *local, | |||
| 1114 | struct ieee80211_sub_if_data *sdata) | 1147 | struct ieee80211_sub_if_data *sdata) |
| 1115 | { | 1148 | { |
| 1116 | might_sleep(); | 1149 | might_sleep(); |
| 1117 | check_sdata_in_driver(sdata); | 1150 | if (!check_sdata_in_driver(sdata)) |
| 1151 | return; | ||
| 1118 | 1152 | ||
| 1119 | trace_drv_leave_ibss(local, sdata); | 1153 | trace_drv_leave_ibss(local, sdata); |
| 1120 | if (local->ops->leave_ibss) | 1154 | if (local->ops->leave_ibss) |
| @@ -1122,4 +1156,17 @@ static inline void drv_leave_ibss(struct ieee80211_local *local, | |||
| 1122 | trace_drv_return_void(local); | 1156 | trace_drv_return_void(local); |
| 1123 | } | 1157 | } |
| 1124 | 1158 | ||
| 1159 | static inline u32 drv_get_expected_throughput(struct ieee80211_local *local, | ||
| 1160 | struct ieee80211_sta *sta) | ||
| 1161 | { | ||
| 1162 | u32 ret = 0; | ||
| 1163 | |||
| 1164 | trace_drv_get_expected_throughput(sta); | ||
| 1165 | if (local->ops->get_expected_throughput) | ||
| 1166 | ret = local->ops->get_expected_throughput(sta); | ||
| 1167 | trace_drv_return_u32(local, ret); | ||
| 1168 | |||
| 1169 | return ret; | ||
| 1170 | } | ||
| 1171 | |||
| 1125 | #endif /* __MAC80211_DRIVER_OPS */ | 1172 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index ff4d4155a84d..1bbac94da58d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
| @@ -143,7 +143,7 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, | |||
| 143 | *pos++ = csa_settings->block_tx ? 1 : 0; | 143 | *pos++ = csa_settings->block_tx ? 1 : 0; |
| 144 | *pos++ = ieee80211_frequency_to_channel( | 144 | *pos++ = ieee80211_frequency_to_channel( |
| 145 | csa_settings->chandef.chan->center_freq); | 145 | csa_settings->chandef.chan->center_freq); |
| 146 | sdata->csa_counter_offset_beacon = (pos - presp->head); | 146 | sdata->csa_counter_offset_beacon[0] = (pos - presp->head); |
| 147 | *pos++ = csa_settings->count; | 147 | *pos++ = csa_settings->count; |
| 148 | } | 148 | } |
| 149 | 149 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 487c2ef0982a..ac9836e0aab3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -754,9 +754,10 @@ struct ieee80211_sub_if_data { | |||
| 754 | struct mac80211_qos_map __rcu *qos_map; | 754 | struct mac80211_qos_map __rcu *qos_map; |
| 755 | 755 | ||
| 756 | struct work_struct csa_finalize_work; | 756 | struct work_struct csa_finalize_work; |
| 757 | int csa_counter_offset_beacon; | 757 | u16 csa_counter_offset_beacon[IEEE80211_MAX_CSA_COUNTERS_NUM]; |
| 758 | int csa_counter_offset_presp; | 758 | u16 csa_counter_offset_presp[IEEE80211_MAX_CSA_COUNTERS_NUM]; |
| 759 | bool csa_radar_required; | 759 | bool csa_radar_required; |
| 760 | bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */ | ||
| 760 | struct cfg80211_chan_def csa_chandef; | 761 | struct cfg80211_chan_def csa_chandef; |
| 761 | 762 | ||
| 762 | struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */ | 763 | struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */ |
| @@ -766,6 +767,7 @@ struct ieee80211_sub_if_data { | |||
| 766 | struct ieee80211_chanctx *reserved_chanctx; | 767 | struct ieee80211_chanctx *reserved_chanctx; |
| 767 | struct cfg80211_chan_def reserved_chandef; | 768 | struct cfg80211_chan_def reserved_chandef; |
| 768 | bool reserved_radar_required; | 769 | bool reserved_radar_required; |
| 770 | u8 csa_current_counter; | ||
| 769 | 771 | ||
| 770 | /* used to reconfigure hardware SM PS */ | 772 | /* used to reconfigure hardware SM PS */ |
| 771 | struct work_struct recalc_smps; | 773 | struct work_struct recalc_smps; |
| @@ -1459,6 +1461,7 @@ __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
| 1459 | int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | 1461 | int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, |
| 1460 | struct cfg80211_sched_scan_request *req); | 1462 | struct cfg80211_sched_scan_request *req); |
| 1461 | int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); | 1463 | int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); |
| 1464 | void ieee80211_sched_scan_end(struct ieee80211_local *local); | ||
| 1462 | void ieee80211_sched_scan_stopped_work(struct work_struct *work); | 1465 | void ieee80211_sched_scan_stopped_work(struct work_struct *work); |
| 1463 | 1466 | ||
| 1464 | /* off-channel helpers */ | 1467 | /* off-channel helpers */ |
| @@ -1473,6 +1476,7 @@ void ieee80211_sw_roc_work(struct work_struct *work); | |||
| 1473 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); | 1476 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); |
| 1474 | 1477 | ||
| 1475 | /* channel switch handling */ | 1478 | /* channel switch handling */ |
| 1479 | bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local); | ||
| 1476 | void ieee80211_csa_finalize_work(struct work_struct *work); | 1480 | void ieee80211_csa_finalize_work(struct work_struct *work); |
| 1477 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 1481 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, |
| 1478 | struct cfg80211_csa_settings *params); | 1482 | struct cfg80211_csa_settings *params); |
| @@ -1834,6 +1838,15 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, | |||
| 1834 | u8 radar_detect); | 1838 | u8 radar_detect); |
| 1835 | int ieee80211_max_num_channels(struct ieee80211_local *local); | 1839 | int ieee80211_max_num_channels(struct ieee80211_local *local); |
| 1836 | 1840 | ||
| 1841 | /* TDLS */ | ||
| 1842 | int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | ||
| 1843 | const u8 *peer, u8 action_code, u8 dialog_token, | ||
| 1844 | u16 status_code, u32 peer_capability, | ||
| 1845 | const u8 *extra_ies, size_t extra_ies_len); | ||
| 1846 | int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | ||
| 1847 | const u8 *peer, enum nl80211_tdls_operation oper); | ||
| 1848 | |||
| 1849 | |||
| 1837 | #ifdef CONFIG_MAC80211_NOINLINE | 1850 | #ifdef CONFIG_MAC80211_NOINLINE |
| 1838 | #define debug_noinline noinline | 1851 | #define debug_noinline noinline |
| 1839 | #else | 1852 | #else |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 7fff3dcaac43..79fc98815da8 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -838,8 +838,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
| 838 | 838 | ||
| 839 | cancel_work_sync(&sdata->recalc_smps); | 839 | cancel_work_sync(&sdata->recalc_smps); |
| 840 | sdata_lock(sdata); | 840 | sdata_lock(sdata); |
| 841 | mutex_lock(&local->mtx); | ||
| 841 | sdata->vif.csa_active = false; | 842 | sdata->vif.csa_active = false; |
| 843 | if (!ieee80211_csa_needs_block_tx(local)) | ||
| 844 | ieee80211_wake_queues_by_reason(&local->hw, | ||
| 845 | IEEE80211_MAX_QUEUE_MAP, | ||
| 846 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
| 847 | mutex_unlock(&local->mtx); | ||
| 842 | sdata_unlock(sdata); | 848 | sdata_unlock(sdata); |
| 849 | |||
| 843 | cancel_work_sync(&sdata->csa_finalize_work); | 850 | cancel_work_sync(&sdata->csa_finalize_work); |
| 844 | 851 | ||
| 845 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 852 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 6ff65a1ebaa9..16d97f044a20 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
| @@ -325,7 +325,8 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
| 325 | struct ieee80211_key *key; | 325 | struct ieee80211_key *key; |
| 326 | int i, j, err; | 326 | int i, j, err; |
| 327 | 327 | ||
| 328 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); | 328 | if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)) |
| 329 | return ERR_PTR(-EINVAL); | ||
| 329 | 330 | ||
| 330 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); | 331 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); |
| 331 | if (!key) | 332 | if (!key) |
| @@ -481,8 +482,8 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
| 481 | int idx, ret; | 482 | int idx, ret; |
| 482 | bool pairwise; | 483 | bool pairwise; |
| 483 | 484 | ||
| 484 | BUG_ON(!sdata); | 485 | if (WARN_ON(!sdata || !key)) |
| 485 | BUG_ON(!key); | 486 | return -EINVAL; |
| 486 | 487 | ||
| 487 | pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; | 488 | pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; |
| 488 | idx = key->conf.keyidx; | 489 | idx = key->conf.keyidx; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 27b9364cdf17..d17c26d6e369 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -956,6 +956,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 956 | if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) | 956 | if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) |
| 957 | local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; | 957 | local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; |
| 958 | 958 | ||
| 959 | local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM; | ||
| 960 | |||
| 959 | result = wiphy_register(local->hw.wiphy); | 961 | result = wiphy_register(local->hw.wiphy); |
| 960 | if (result < 0) | 962 | if (result < 0) |
| 961 | goto fail_wiphy_register; | 963 | goto fail_wiphy_register; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index b06ddc9519ce..6495a3f0428d 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
| @@ -679,7 +679,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
| 679 | *pos++ = 0x0; | 679 | *pos++ = 0x0; |
| 680 | *pos++ = ieee80211_frequency_to_channel( | 680 | *pos++ = ieee80211_frequency_to_channel( |
| 681 | csa->settings.chandef.chan->center_freq); | 681 | csa->settings.chandef.chan->center_freq); |
| 682 | sdata->csa_counter_offset_beacon = hdr_len + 6; | 682 | sdata->csa_counter_offset_beacon[0] = hdr_len + 6; |
| 683 | *pos++ = csa->settings.count; | 683 | *pos++ = csa->settings.count; |
| 684 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; | 684 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; |
| 685 | *pos++ = 6; | 685 | *pos++ = 6; |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 7d050ed6fe5a..cf032a8db9d7 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
| @@ -287,8 +287,10 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, | |||
| 287 | struct sk_buff_head failq; | 287 | struct sk_buff_head failq; |
| 288 | unsigned long flags; | 288 | unsigned long flags; |
| 289 | 289 | ||
| 290 | BUG_ON(gate_mpath == from_mpath); | 290 | if (WARN_ON(gate_mpath == from_mpath)) |
| 291 | BUG_ON(!gate_mpath->next_hop); | 291 | return; |
| 292 | if (WARN_ON(!gate_mpath->next_hop)) | ||
| 293 | return; | ||
| 292 | 294 | ||
| 293 | __skb_queue_head_init(&failq); | 295 | __skb_queue_head_init(&failq); |
| 294 | 296 | ||
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index 2bc5dc25d5ad..09625d6205c3 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
| @@ -171,7 +171,7 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata, | |||
| 171 | u8 cap; | 171 | u8 cap; |
| 172 | 172 | ||
| 173 | WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); | 173 | WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); |
| 174 | BUG_ON(!rcu_read_lock_held()); | 174 | WARN_ON(!rcu_read_lock_held()); |
| 175 | cap = beacon->meshconf->meshconf_cap; | 175 | cap = beacon->meshconf->meshconf_cap; |
| 176 | 176 | ||
| 177 | spin_lock_bh(&ifmsh->sync_offset_lock); | 177 | spin_lock_bh(&ifmsh->sync_offset_lock); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index bfb5e20796b6..3345401be1b3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -975,16 +975,23 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
| 975 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 975 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
| 976 | ifmgd->associated->channel = sdata->csa_chandef.chan; | 976 | ifmgd->associated->channel = sdata->csa_chandef.chan; |
| 977 | 977 | ||
| 978 | ieee80211_bss_info_change_notify(sdata, changed); | ||
| 979 | |||
| 980 | mutex_lock(&local->mtx); | ||
| 981 | sdata->vif.csa_active = false; | ||
| 978 | /* XXX: wait for a beacon first? */ | 982 | /* XXX: wait for a beacon first? */ |
| 979 | ieee80211_wake_queues_by_reason(&local->hw, | 983 | if (!ieee80211_csa_needs_block_tx(local)) |
| 984 | ieee80211_wake_queues_by_reason(&local->hw, | ||
| 980 | IEEE80211_MAX_QUEUE_MAP, | 985 | IEEE80211_MAX_QUEUE_MAP, |
| 981 | IEEE80211_QUEUE_STOP_REASON_CSA); | 986 | IEEE80211_QUEUE_STOP_REASON_CSA); |
| 987 | mutex_unlock(&local->mtx); | ||
| 982 | 988 | ||
| 983 | ieee80211_bss_info_change_notify(sdata, changed); | ||
| 984 | |||
| 985 | out: | ||
| 986 | sdata->vif.csa_active = false; | ||
| 987 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | 989 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; |
| 990 | |||
| 991 | ieee80211_sta_reset_beacon_monitor(sdata); | ||
| 992 | ieee80211_sta_reset_conn_monitor(sdata); | ||
| 993 | |||
| 994 | out: | ||
| 988 | sdata_unlock(sdata); | 995 | sdata_unlock(sdata); |
| 989 | } | 996 | } |
| 990 | 997 | ||
| @@ -1100,12 +1107,16 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
| 1100 | mutex_unlock(&local->chanctx_mtx); | 1107 | mutex_unlock(&local->chanctx_mtx); |
| 1101 | 1108 | ||
| 1102 | sdata->csa_chandef = csa_ie.chandef; | 1109 | sdata->csa_chandef = csa_ie.chandef; |
| 1110 | |||
| 1111 | mutex_lock(&local->mtx); | ||
| 1103 | sdata->vif.csa_active = true; | 1112 | sdata->vif.csa_active = true; |
| 1113 | sdata->csa_block_tx = csa_ie.mode; | ||
| 1104 | 1114 | ||
| 1105 | if (csa_ie.mode) | 1115 | if (sdata->csa_block_tx) |
| 1106 | ieee80211_stop_queues_by_reason(&local->hw, | 1116 | ieee80211_stop_queues_by_reason(&local->hw, |
| 1107 | IEEE80211_MAX_QUEUE_MAP, | 1117 | IEEE80211_MAX_QUEUE_MAP, |
| 1108 | IEEE80211_QUEUE_STOP_REASON_CSA); | 1118 | IEEE80211_QUEUE_STOP_REASON_CSA); |
| 1119 | mutex_unlock(&local->mtx); | ||
| 1109 | 1120 | ||
| 1110 | if (local->ops->channel_switch) { | 1121 | if (local->ops->channel_switch) { |
| 1111 | /* use driver's channel switch callback */ | 1122 | /* use driver's channel switch callback */ |
| @@ -1817,6 +1828,12 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
| 1817 | ifmgd->flags = 0; | 1828 | ifmgd->flags = 0; |
| 1818 | mutex_lock(&local->mtx); | 1829 | mutex_lock(&local->mtx); |
| 1819 | ieee80211_vif_release_channel(sdata); | 1830 | ieee80211_vif_release_channel(sdata); |
| 1831 | |||
| 1832 | sdata->vif.csa_active = false; | ||
| 1833 | if (!ieee80211_csa_needs_block_tx(local)) | ||
| 1834 | ieee80211_wake_queues_by_reason(&local->hw, | ||
| 1835 | IEEE80211_MAX_QUEUE_MAP, | ||
| 1836 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
| 1820 | mutex_unlock(&local->mtx); | 1837 | mutex_unlock(&local->mtx); |
| 1821 | 1838 | ||
| 1822 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; | 1839 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; |
| @@ -2045,6 +2062,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get); | |||
| 2045 | 2062 | ||
| 2046 | static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) | 2063 | static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) |
| 2047 | { | 2064 | { |
| 2065 | struct ieee80211_local *local = sdata->local; | ||
| 2048 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2066 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 2049 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | 2067 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
| 2050 | 2068 | ||
| @@ -2058,10 +2076,14 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) | |||
| 2058 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 2076 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
| 2059 | true, frame_buf); | 2077 | true, frame_buf); |
| 2060 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | 2078 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; |
| 2079 | |||
| 2080 | mutex_lock(&local->mtx); | ||
| 2061 | sdata->vif.csa_active = false; | 2081 | sdata->vif.csa_active = false; |
| 2062 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 2082 | if (!ieee80211_csa_needs_block_tx(local)) |
| 2083 | ieee80211_wake_queues_by_reason(&local->hw, | ||
| 2063 | IEEE80211_MAX_QUEUE_MAP, | 2084 | IEEE80211_MAX_QUEUE_MAP, |
| 2064 | IEEE80211_QUEUE_STOP_REASON_CSA); | 2085 | IEEE80211_QUEUE_STOP_REASON_CSA); |
| 2086 | mutex_unlock(&local->mtx); | ||
| 2065 | 2087 | ||
| 2066 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, | 2088 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, |
| 2067 | IEEE80211_DEAUTH_FRAME_LEN); | 2089 | IEEE80211_DEAUTH_FRAME_LEN); |
| @@ -3546,6 +3568,9 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data) | |||
| 3546 | if (local->quiescing) | 3568 | if (local->quiescing) |
| 3547 | return; | 3569 | return; |
| 3548 | 3570 | ||
| 3571 | if (sdata->vif.csa_active) | ||
| 3572 | return; | ||
| 3573 | |||
| 3549 | sdata->u.mgd.connection_loss = false; | 3574 | sdata->u.mgd.connection_loss = false; |
| 3550 | ieee80211_queue_work(&sdata->local->hw, | 3575 | ieee80211_queue_work(&sdata->local->hw, |
| 3551 | &sdata->u.mgd.beacon_connection_loss_work); | 3576 | &sdata->u.mgd.beacon_connection_loss_work); |
| @@ -3561,6 +3586,9 @@ static void ieee80211_sta_conn_mon_timer(unsigned long data) | |||
| 3561 | if (local->quiescing) | 3586 | if (local->quiescing) |
| 3562 | return; | 3587 | return; |
| 3563 | 3588 | ||
| 3589 | if (sdata->vif.csa_active) | ||
| 3590 | return; | ||
| 3591 | |||
| 3564 | ieee80211_queue_work(&local->hw, &ifmgd->monitor_work); | 3592 | ieee80211_queue_work(&local->hw, &ifmgd->monitor_work); |
| 3565 | } | 3593 | } |
| 3566 | 3594 | ||
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 26fd94fa0aed..1c1469c36dca 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
| @@ -657,6 +657,17 @@ minstrel_free(void *priv) | |||
| 657 | kfree(priv); | 657 | kfree(priv); |
| 658 | } | 658 | } |
| 659 | 659 | ||
| 660 | static u32 minstrel_get_expected_throughput(void *priv_sta) | ||
| 661 | { | ||
| 662 | struct minstrel_sta_info *mi = priv_sta; | ||
| 663 | int idx = mi->max_tp_rate[0]; | ||
| 664 | |||
| 665 | /* convert pkt per sec in kbps (1200 is the average pkt size used for | ||
| 666 | * computing cur_tp | ||
| 667 | */ | ||
| 668 | return MINSTREL_TRUNC(mi->r[idx].cur_tp) * 1200 * 8 / 1024; | ||
| 669 | } | ||
| 670 | |||
| 660 | const struct rate_control_ops mac80211_minstrel = { | 671 | const struct rate_control_ops mac80211_minstrel = { |
| 661 | .name = "minstrel", | 672 | .name = "minstrel", |
| 662 | .tx_status = minstrel_tx_status, | 673 | .tx_status = minstrel_tx_status, |
| @@ -670,6 +681,7 @@ const struct rate_control_ops mac80211_minstrel = { | |||
| 670 | .add_sta_debugfs = minstrel_add_sta_debugfs, | 681 | .add_sta_debugfs = minstrel_add_sta_debugfs, |
| 671 | .remove_sta_debugfs = minstrel_remove_sta_debugfs, | 682 | .remove_sta_debugfs = minstrel_remove_sta_debugfs, |
| 672 | #endif | 683 | #endif |
| 684 | .get_expected_throughput = minstrel_get_expected_throughput, | ||
| 673 | }; | 685 | }; |
| 674 | 686 | ||
| 675 | int __init | 687 | int __init |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index bccaf854a309..85c1e74b7714 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #define MCS_NBITS (AVG_PKT_SIZE << 3) | 22 | #define MCS_NBITS (AVG_PKT_SIZE << 3) |
| 23 | 23 | ||
| 24 | /* Number of symbols for a packet with (bps) bits per symbol */ | 24 | /* Number of symbols for a packet with (bps) bits per symbol */ |
| 25 | #define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps)) | 25 | #define MCS_NSYMS(bps) DIV_ROUND_UP(MCS_NBITS, (bps)) |
| 26 | 26 | ||
| 27 | /* Transmission time (nanoseconds) for a packet containing (syms) symbols */ | 27 | /* Transmission time (nanoseconds) for a packet containing (syms) symbols */ |
| 28 | #define MCS_SYMBOL_TIME(sgi, syms) \ | 28 | #define MCS_SYMBOL_TIME(sgi, syms) \ |
| @@ -226,8 +226,9 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) | |||
| 226 | nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); | 226 | nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); |
| 227 | 227 | ||
| 228 | nsecs += minstrel_mcs_groups[group].duration[rate]; | 228 | nsecs += minstrel_mcs_groups[group].duration[rate]; |
| 229 | tp = 1000000 * ((prob * 1000) / nsecs); | ||
| 230 | 229 | ||
| 230 | /* prob is scaled - see MINSTREL_FRAC above */ | ||
| 231 | tp = 1000000 * ((prob * 1000) / nsecs); | ||
| 231 | mr->cur_tp = MINSTREL_TRUNC(tp); | 232 | mr->cur_tp = MINSTREL_TRUNC(tp); |
| 232 | } | 233 | } |
| 233 | 234 | ||
| @@ -1031,6 +1032,22 @@ minstrel_ht_free(void *priv) | |||
| 1031 | mac80211_minstrel.free(priv); | 1032 | mac80211_minstrel.free(priv); |
| 1032 | } | 1033 | } |
| 1033 | 1034 | ||
| 1035 | static u32 minstrel_ht_get_expected_throughput(void *priv_sta) | ||
| 1036 | { | ||
| 1037 | struct minstrel_ht_sta_priv *msp = priv_sta; | ||
| 1038 | struct minstrel_ht_sta *mi = &msp->ht; | ||
| 1039 | int i, j; | ||
| 1040 | |||
| 1041 | if (!msp->is_ht) | ||
| 1042 | return mac80211_minstrel.get_expected_throughput(priv_sta); | ||
| 1043 | |||
| 1044 | i = mi->max_tp_rate / MCS_GROUP_RATES; | ||
| 1045 | j = mi->max_tp_rate % MCS_GROUP_RATES; | ||
| 1046 | |||
| 1047 | /* convert cur_tp from pkt per second in kbps */ | ||
| 1048 | return mi->groups[i].rates[j].cur_tp * AVG_PKT_SIZE * 8 / 1024; | ||
| 1049 | } | ||
| 1050 | |||
| 1034 | static const struct rate_control_ops mac80211_minstrel_ht = { | 1051 | static const struct rate_control_ops mac80211_minstrel_ht = { |
| 1035 | .name = "minstrel_ht", | 1052 | .name = "minstrel_ht", |
| 1036 | .tx_status = minstrel_ht_tx_status, | 1053 | .tx_status = minstrel_ht_tx_status, |
| @@ -1045,6 +1062,7 @@ static const struct rate_control_ops mac80211_minstrel_ht = { | |||
| 1045 | .add_sta_debugfs = minstrel_ht_add_sta_debugfs, | 1062 | .add_sta_debugfs = minstrel_ht_add_sta_debugfs, |
| 1046 | .remove_sta_debugfs = minstrel_ht_remove_sta_debugfs, | 1063 | .remove_sta_debugfs = minstrel_ht_remove_sta_debugfs, |
| 1047 | #endif | 1064 | #endif |
| 1065 | .get_expected_throughput = minstrel_ht_get_expected_throughput, | ||
| 1048 | }; | 1066 | }; |
| 1049 | 1067 | ||
| 1050 | 1068 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 28185c8dc19a..f40661eb75b5 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
| @@ -1076,12 +1076,8 @@ void ieee80211_sched_scan_results(struct ieee80211_hw *hw) | |||
| 1076 | } | 1076 | } |
| 1077 | EXPORT_SYMBOL(ieee80211_sched_scan_results); | 1077 | EXPORT_SYMBOL(ieee80211_sched_scan_results); |
| 1078 | 1078 | ||
| 1079 | void ieee80211_sched_scan_stopped_work(struct work_struct *work) | 1079 | void ieee80211_sched_scan_end(struct ieee80211_local *local) |
| 1080 | { | 1080 | { |
| 1081 | struct ieee80211_local *local = | ||
| 1082 | container_of(work, struct ieee80211_local, | ||
| 1083 | sched_scan_stopped_work); | ||
| 1084 | |||
| 1085 | mutex_lock(&local->mtx); | 1081 | mutex_lock(&local->mtx); |
| 1086 | 1082 | ||
| 1087 | if (!rcu_access_pointer(local->sched_scan_sdata)) { | 1083 | if (!rcu_access_pointer(local->sched_scan_sdata)) { |
| @@ -1099,6 +1095,15 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work) | |||
| 1099 | cfg80211_sched_scan_stopped(local->hw.wiphy); | 1095 | cfg80211_sched_scan_stopped(local->hw.wiphy); |
| 1100 | } | 1096 | } |
| 1101 | 1097 | ||
| 1098 | void ieee80211_sched_scan_stopped_work(struct work_struct *work) | ||
| 1099 | { | ||
| 1100 | struct ieee80211_local *local = | ||
| 1101 | container_of(work, struct ieee80211_local, | ||
| 1102 | sched_scan_stopped_work); | ||
| 1103 | |||
| 1104 | ieee80211_sched_scan_end(local); | ||
| 1105 | } | ||
| 1106 | |||
| 1102 | void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) | 1107 | void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) |
| 1103 | { | 1108 | { |
| 1104 | struct ieee80211_local *local = hw_to_local(hw); | 1109 | struct ieee80211_local *local = hw_to_local(hw); |
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c new file mode 100644 index 000000000000..652813b2d3df --- /dev/null +++ b/net/mac80211/tdls.c | |||
| @@ -0,0 +1,325 @@ | |||
| 1 | /* | ||
| 2 | * mac80211 TDLS handling code | ||
| 3 | * | ||
| 4 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> | ||
| 5 | * Copyright 2014, Intel Corporation | ||
| 6 | * | ||
| 7 | * This file is GPLv2 as found in COPYING. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/ieee80211.h> | ||
| 11 | #include "ieee80211_i.h" | ||
| 12 | |||
| 13 | static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) | ||
| 14 | { | ||
| 15 | u8 *pos = (void *)skb_put(skb, 7); | ||
| 16 | |||
| 17 | *pos++ = WLAN_EID_EXT_CAPABILITY; | ||
| 18 | *pos++ = 5; /* len */ | ||
| 19 | *pos++ = 0x0; | ||
| 20 | *pos++ = 0x0; | ||
| 21 | *pos++ = 0x0; | ||
| 22 | *pos++ = 0x0; | ||
| 23 | *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; | ||
| 24 | } | ||
| 25 | |||
| 26 | static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) | ||
| 27 | { | ||
| 28 | struct ieee80211_local *local = sdata->local; | ||
| 29 | u16 capab; | ||
| 30 | |||
| 31 | capab = 0; | ||
| 32 | if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) | ||
| 33 | return capab; | ||
| 34 | |||
| 35 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) | ||
| 36 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; | ||
| 37 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) | ||
| 38 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
| 39 | |||
| 40 | return capab; | ||
| 41 | } | ||
| 42 | |||
| 43 | static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr, | ||
| 44 | const u8 *peer, const u8 *bssid) | ||
| 45 | { | ||
| 46 | struct ieee80211_tdls_lnkie *lnkid; | ||
| 47 | |||
| 48 | lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); | ||
| 49 | |||
| 50 | lnkid->ie_type = WLAN_EID_LINK_ID; | ||
| 51 | lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; | ||
| 52 | |||
| 53 | memcpy(lnkid->bssid, bssid, ETH_ALEN); | ||
| 54 | memcpy(lnkid->init_sta, src_addr, ETH_ALEN); | ||
| 55 | memcpy(lnkid->resp_sta, peer, ETH_ALEN); | ||
| 56 | } | ||
| 57 | |||
| 58 | static int | ||
| 59 | ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | ||
| 60 | const u8 *peer, u8 action_code, u8 dialog_token, | ||
| 61 | u16 status_code, struct sk_buff *skb) | ||
| 62 | { | ||
| 63 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 64 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
| 65 | struct ieee80211_tdls_data *tf; | ||
| 66 | |||
| 67 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | ||
| 68 | |||
| 69 | memcpy(tf->da, peer, ETH_ALEN); | ||
| 70 | memcpy(tf->sa, sdata->vif.addr, ETH_ALEN); | ||
| 71 | tf->ether_type = cpu_to_be16(ETH_P_TDLS); | ||
| 72 | tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; | ||
| 73 | |||
| 74 | switch (action_code) { | ||
| 75 | case WLAN_TDLS_SETUP_REQUEST: | ||
| 76 | tf->category = WLAN_CATEGORY_TDLS; | ||
| 77 | tf->action_code = WLAN_TDLS_SETUP_REQUEST; | ||
| 78 | |||
| 79 | skb_put(skb, sizeof(tf->u.setup_req)); | ||
| 80 | tf->u.setup_req.dialog_token = dialog_token; | ||
| 81 | tf->u.setup_req.capability = | ||
| 82 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | ||
| 83 | |||
| 84 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
| 85 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
| 86 | ieee80211_tdls_add_ext_capab(skb); | ||
| 87 | break; | ||
| 88 | case WLAN_TDLS_SETUP_RESPONSE: | ||
| 89 | tf->category = WLAN_CATEGORY_TDLS; | ||
| 90 | tf->action_code = WLAN_TDLS_SETUP_RESPONSE; | ||
| 91 | |||
| 92 | skb_put(skb, sizeof(tf->u.setup_resp)); | ||
| 93 | tf->u.setup_resp.status_code = cpu_to_le16(status_code); | ||
| 94 | tf->u.setup_resp.dialog_token = dialog_token; | ||
| 95 | tf->u.setup_resp.capability = | ||
| 96 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | ||
| 97 | |||
| 98 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
| 99 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
| 100 | ieee80211_tdls_add_ext_capab(skb); | ||
| 101 | break; | ||
| 102 | case WLAN_TDLS_SETUP_CONFIRM: | ||
| 103 | tf->category = WLAN_CATEGORY_TDLS; | ||
| 104 | tf->action_code = WLAN_TDLS_SETUP_CONFIRM; | ||
| 105 | |||
| 106 | skb_put(skb, sizeof(tf->u.setup_cfm)); | ||
| 107 | tf->u.setup_cfm.status_code = cpu_to_le16(status_code); | ||
| 108 | tf->u.setup_cfm.dialog_token = dialog_token; | ||
| 109 | break; | ||
| 110 | case WLAN_TDLS_TEARDOWN: | ||
| 111 | tf->category = WLAN_CATEGORY_TDLS; | ||
| 112 | tf->action_code = WLAN_TDLS_TEARDOWN; | ||
| 113 | |||
| 114 | skb_put(skb, sizeof(tf->u.teardown)); | ||
| 115 | tf->u.teardown.reason_code = cpu_to_le16(status_code); | ||
| 116 | break; | ||
| 117 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
| 118 | tf->category = WLAN_CATEGORY_TDLS; | ||
| 119 | tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; | ||
| 120 | |||
| 121 | skb_put(skb, sizeof(tf->u.discover_req)); | ||
| 122 | tf->u.discover_req.dialog_token = dialog_token; | ||
| 123 | break; | ||
| 124 | default: | ||
| 125 | return -EINVAL; | ||
| 126 | } | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int | ||
| 132 | ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | ||
| 133 | const u8 *peer, u8 action_code, u8 dialog_token, | ||
| 134 | u16 status_code, struct sk_buff *skb) | ||
| 135 | { | ||
| 136 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 137 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
| 138 | struct ieee80211_mgmt *mgmt; | ||
| 139 | |||
| 140 | mgmt = (void *)skb_put(skb, 24); | ||
| 141 | memset(mgmt, 0, 24); | ||
| 142 | memcpy(mgmt->da, peer, ETH_ALEN); | ||
| 143 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
| 144 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | ||
| 145 | |||
| 146 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
| 147 | IEEE80211_STYPE_ACTION); | ||
| 148 | |||
| 149 | switch (action_code) { | ||
| 150 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
| 151 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); | ||
| 152 | mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; | ||
| 153 | mgmt->u.action.u.tdls_discover_resp.action_code = | ||
| 154 | WLAN_PUB_ACTION_TDLS_DISCOVER_RES; | ||
| 155 | mgmt->u.action.u.tdls_discover_resp.dialog_token = | ||
| 156 | dialog_token; | ||
| 157 | mgmt->u.action.u.tdls_discover_resp.capability = | ||
| 158 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | ||
| 159 | |||
| 160 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
| 161 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
| 162 | ieee80211_tdls_add_ext_capab(skb); | ||
| 163 | break; | ||
| 164 | default: | ||
| 165 | return -EINVAL; | ||
| 166 | } | ||
| 167 | |||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | ||
| 172 | const u8 *peer, u8 action_code, u8 dialog_token, | ||
| 173 | u16 status_code, u32 peer_capability, | ||
| 174 | const u8 *extra_ies, size_t extra_ies_len) | ||
| 175 | { | ||
| 176 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 177 | struct ieee80211_local *local = sdata->local; | ||
| 178 | struct sk_buff *skb = NULL; | ||
| 179 | bool send_direct; | ||
| 180 | int ret; | ||
| 181 | |||
| 182 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
| 183 | return -ENOTSUPP; | ||
| 184 | |||
| 185 | /* make sure we are in managed mode, and associated */ | ||
| 186 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | ||
| 187 | !sdata->u.mgd.associated) | ||
| 188 | return -EINVAL; | ||
| 189 | |||
| 190 | tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n", | ||
| 191 | action_code, peer); | ||
| 192 | |||
| 193 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
| 194 | max(sizeof(struct ieee80211_mgmt), | ||
| 195 | sizeof(struct ieee80211_tdls_data)) + | ||
| 196 | 50 + /* supported rates */ | ||
| 197 | 7 + /* ext capab */ | ||
| 198 | extra_ies_len + | ||
| 199 | sizeof(struct ieee80211_tdls_lnkie)); | ||
| 200 | if (!skb) | ||
| 201 | return -ENOMEM; | ||
| 202 | |||
| 203 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
| 204 | |||
| 205 | switch (action_code) { | ||
| 206 | case WLAN_TDLS_SETUP_REQUEST: | ||
| 207 | case WLAN_TDLS_SETUP_RESPONSE: | ||
| 208 | case WLAN_TDLS_SETUP_CONFIRM: | ||
| 209 | case WLAN_TDLS_TEARDOWN: | ||
| 210 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
| 211 | ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer, | ||
| 212 | action_code, dialog_token, | ||
| 213 | status_code, skb); | ||
| 214 | send_direct = false; | ||
| 215 | break; | ||
| 216 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
| 217 | ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code, | ||
| 218 | dialog_token, status_code, | ||
| 219 | skb); | ||
| 220 | send_direct = true; | ||
| 221 | break; | ||
| 222 | default: | ||
| 223 | ret = -ENOTSUPP; | ||
| 224 | break; | ||
| 225 | } | ||
| 226 | |||
| 227 | if (ret < 0) | ||
| 228 | goto fail; | ||
| 229 | |||
| 230 | if (extra_ies_len) | ||
| 231 | memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); | ||
| 232 | |||
| 233 | /* the TDLS link IE is always added last */ | ||
| 234 | switch (action_code) { | ||
| 235 | case WLAN_TDLS_SETUP_REQUEST: | ||
| 236 | case WLAN_TDLS_SETUP_CONFIRM: | ||
| 237 | case WLAN_TDLS_TEARDOWN: | ||
| 238 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
| 239 | /* we are the initiator */ | ||
| 240 | ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer, | ||
| 241 | sdata->u.mgd.bssid); | ||
| 242 | break; | ||
| 243 | case WLAN_TDLS_SETUP_RESPONSE: | ||
| 244 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
| 245 | /* we are the responder */ | ||
| 246 | ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr, | ||
| 247 | sdata->u.mgd.bssid); | ||
| 248 | break; | ||
| 249 | default: | ||
| 250 | ret = -ENOTSUPP; | ||
| 251 | goto fail; | ||
| 252 | } | ||
| 253 | |||
| 254 | if (send_direct) { | ||
| 255 | ieee80211_tx_skb(sdata, skb); | ||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | /* | ||
| 260 | * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise | ||
| 261 | * we should default to AC_VI. | ||
| 262 | */ | ||
| 263 | switch (action_code) { | ||
| 264 | case WLAN_TDLS_SETUP_REQUEST: | ||
| 265 | case WLAN_TDLS_SETUP_RESPONSE: | ||
| 266 | skb_set_queue_mapping(skb, IEEE80211_AC_BK); | ||
| 267 | skb->priority = 2; | ||
| 268 | break; | ||
| 269 | default: | ||
| 270 | skb_set_queue_mapping(skb, IEEE80211_AC_VI); | ||
| 271 | skb->priority = 5; | ||
| 272 | break; | ||
| 273 | } | ||
| 274 | |||
| 275 | /* disable bottom halves when entering the Tx path */ | ||
| 276 | local_bh_disable(); | ||
| 277 | ret = ieee80211_subif_start_xmit(skb, dev); | ||
| 278 | local_bh_enable(); | ||
| 279 | |||
| 280 | return ret; | ||
| 281 | |||
| 282 | fail: | ||
| 283 | dev_kfree_skb(skb); | ||
| 284 | return ret; | ||
| 285 | } | ||
| 286 | |||
| 287 | int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | ||
| 288 | const u8 *peer, enum nl80211_tdls_operation oper) | ||
| 289 | { | ||
| 290 | struct sta_info *sta; | ||
| 291 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 292 | |||
| 293 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
| 294 | return -ENOTSUPP; | ||
| 295 | |||
| 296 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
| 297 | return -EINVAL; | ||
| 298 | |||
| 299 | tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer); | ||
| 300 | |||
| 301 | switch (oper) { | ||
| 302 | case NL80211_TDLS_ENABLE_LINK: | ||
| 303 | rcu_read_lock(); | ||
| 304 | sta = sta_info_get(sdata, peer); | ||
| 305 | if (!sta) { | ||
| 306 | rcu_read_unlock(); | ||
| 307 | return -ENOLINK; | ||
| 308 | } | ||
| 309 | |||
| 310 | set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); | ||
| 311 | rcu_read_unlock(); | ||
| 312 | break; | ||
| 313 | case NL80211_TDLS_DISABLE_LINK: | ||
| 314 | return sta_info_destroy_addr(sdata, peer); | ||
| 315 | case NL80211_TDLS_TEARDOWN: | ||
| 316 | case NL80211_TDLS_SETUP: | ||
| 317 | case NL80211_TDLS_DISCOVERY_REQ: | ||
| 318 | /* We don't support in-driver setup/teardown/discovery */ | ||
| 319 | return -ENOTSUPP; | ||
| 320 | default: | ||
| 321 | return -ENOTSUPP; | ||
| 322 | } | ||
| 323 | |||
| 324 | return 0; | ||
| 325 | } | ||
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index cec5b60487a4..762e4cd16386 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
| @@ -184,6 +184,20 @@ TRACE_EVENT(drv_return_bool, | |||
| 184 | "true" : "false") | 184 | "true" : "false") |
| 185 | ); | 185 | ); |
| 186 | 186 | ||
| 187 | TRACE_EVENT(drv_return_u32, | ||
| 188 | TP_PROTO(struct ieee80211_local *local, u32 ret), | ||
| 189 | TP_ARGS(local, ret), | ||
| 190 | TP_STRUCT__entry( | ||
| 191 | LOCAL_ENTRY | ||
| 192 | __field(u32, ret) | ||
| 193 | ), | ||
| 194 | TP_fast_assign( | ||
| 195 | LOCAL_ASSIGN; | ||
| 196 | __entry->ret = ret; | ||
| 197 | ), | ||
| 198 | TP_printk(LOCAL_PR_FMT " - %u", LOCAL_PR_ARG, __entry->ret) | ||
| 199 | ); | ||
| 200 | |||
| 187 | TRACE_EVENT(drv_return_u64, | 201 | TRACE_EVENT(drv_return_u64, |
| 188 | TP_PROTO(struct ieee80211_local *local, u64 ret), | 202 | TP_PROTO(struct ieee80211_local *local, u64 ret), |
| 189 | TP_ARGS(local, ret), | 203 | TP_ARGS(local, ret), |
| @@ -1499,6 +1513,24 @@ DEFINE_EVENT(local_sdata_evt, drv_leave_ibss, | |||
| 1499 | TP_ARGS(local, sdata) | 1513 | TP_ARGS(local, sdata) |
| 1500 | ); | 1514 | ); |
| 1501 | 1515 | ||
| 1516 | TRACE_EVENT(drv_get_expected_throughput, | ||
| 1517 | TP_PROTO(struct ieee80211_sta *sta), | ||
| 1518 | |||
| 1519 | TP_ARGS(sta), | ||
| 1520 | |||
| 1521 | TP_STRUCT__entry( | ||
| 1522 | STA_ENTRY | ||
| 1523 | ), | ||
| 1524 | |||
| 1525 | TP_fast_assign( | ||
| 1526 | STA_ASSIGN; | ||
| 1527 | ), | ||
| 1528 | |||
| 1529 | TP_printk( | ||
| 1530 | STA_PR_FMT, STA_PR_ARG | ||
| 1531 | ) | ||
| 1532 | ); | ||
| 1533 | |||
| 1502 | /* | 1534 | /* |
| 1503 | * Tracing for API calls that drivers call. | 1535 | * Tracing for API calls that drivers call. |
| 1504 | */ | 1536 | */ |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 19d36d4117e0..5214686d9fd1 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -2328,7 +2328,8 @@ void ieee80211_tx_pending(unsigned long data) | |||
| 2328 | /* functions for drivers to get certain frames */ | 2328 | /* functions for drivers to get certain frames */ |
| 2329 | 2329 | ||
| 2330 | static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | 2330 | static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, |
| 2331 | struct ps_data *ps, struct sk_buff *skb) | 2331 | struct ps_data *ps, struct sk_buff *skb, |
| 2332 | bool is_template) | ||
| 2332 | { | 2333 | { |
| 2333 | u8 *pos, *tim; | 2334 | u8 *pos, *tim; |
| 2334 | int aid0 = 0; | 2335 | int aid0 = 0; |
| @@ -2341,11 +2342,12 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | |||
| 2341 | * checking byte-for-byte */ | 2342 | * checking byte-for-byte */ |
| 2342 | have_bits = !bitmap_empty((unsigned long *)ps->tim, | 2343 | have_bits = !bitmap_empty((unsigned long *)ps->tim, |
| 2343 | IEEE80211_MAX_AID+1); | 2344 | IEEE80211_MAX_AID+1); |
| 2344 | 2345 | if (!is_template) { | |
| 2345 | if (ps->dtim_count == 0) | 2346 | if (ps->dtim_count == 0) |
| 2346 | ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1; | 2347 | ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1; |
| 2347 | else | 2348 | else |
| 2348 | ps->dtim_count--; | 2349 | ps->dtim_count--; |
| 2350 | } | ||
| 2349 | 2351 | ||
| 2350 | tim = pos = (u8 *) skb_put(skb, 6); | 2352 | tim = pos = (u8 *) skb_put(skb, 6); |
| 2351 | *pos++ = WLAN_EID_TIM; | 2353 | *pos++ = WLAN_EID_TIM; |
| @@ -2391,7 +2393,8 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | |||
| 2391 | } | 2393 | } |
| 2392 | 2394 | ||
| 2393 | static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | 2395 | static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, |
| 2394 | struct ps_data *ps, struct sk_buff *skb) | 2396 | struct ps_data *ps, struct sk_buff *skb, |
| 2397 | bool is_template) | ||
| 2395 | { | 2398 | { |
| 2396 | struct ieee80211_local *local = sdata->local; | 2399 | struct ieee80211_local *local = sdata->local; |
| 2397 | 2400 | ||
| @@ -2403,24 +2406,24 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | |||
| 2403 | * of the tim bitmap in mac80211 and the driver. | 2406 | * of the tim bitmap in mac80211 and the driver. |
| 2404 | */ | 2407 | */ |
| 2405 | if (local->tim_in_locked_section) { | 2408 | if (local->tim_in_locked_section) { |
| 2406 | __ieee80211_beacon_add_tim(sdata, ps, skb); | 2409 | __ieee80211_beacon_add_tim(sdata, ps, skb, is_template); |
| 2407 | } else { | 2410 | } else { |
| 2408 | spin_lock_bh(&local->tim_lock); | 2411 | spin_lock_bh(&local->tim_lock); |
| 2409 | __ieee80211_beacon_add_tim(sdata, ps, skb); | 2412 | __ieee80211_beacon_add_tim(sdata, ps, skb, is_template); |
| 2410 | spin_unlock_bh(&local->tim_lock); | 2413 | spin_unlock_bh(&local->tim_lock); |
| 2411 | } | 2414 | } |
| 2412 | 2415 | ||
| 2413 | return 0; | 2416 | return 0; |
| 2414 | } | 2417 | } |
| 2415 | 2418 | ||
| 2416 | static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | 2419 | static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata, |
| 2417 | struct beacon_data *beacon) | 2420 | struct beacon_data *beacon) |
| 2418 | { | 2421 | { |
| 2419 | struct probe_resp *resp; | 2422 | struct probe_resp *resp; |
| 2420 | int counter_offset_beacon = sdata->csa_counter_offset_beacon; | ||
| 2421 | int counter_offset_presp = sdata->csa_counter_offset_presp; | ||
| 2422 | u8 *beacon_data; | 2423 | u8 *beacon_data; |
| 2423 | size_t beacon_data_len; | 2424 | size_t beacon_data_len; |
| 2425 | int i; | ||
| 2426 | u8 count = sdata->csa_current_counter; | ||
| 2424 | 2427 | ||
| 2425 | switch (sdata->vif.type) { | 2428 | switch (sdata->vif.type) { |
| 2426 | case NL80211_IFTYPE_AP: | 2429 | case NL80211_IFTYPE_AP: |
| @@ -2438,40 +2441,57 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | |||
| 2438 | default: | 2441 | default: |
| 2439 | return; | 2442 | return; |
| 2440 | } | 2443 | } |
| 2441 | if (WARN_ON(counter_offset_beacon >= beacon_data_len)) | ||
| 2442 | return; | ||
| 2443 | 2444 | ||
| 2444 | /* Warn if the driver did not check for/react to csa | 2445 | for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) { |
| 2445 | * completeness. A beacon with CSA counter set to 0 should | 2446 | u16 counter_offset_beacon = |
| 2446 | * never occur, because a counter of 1 means switch just | 2447 | sdata->csa_counter_offset_beacon[i]; |
| 2447 | * before the next beacon. | 2448 | u16 counter_offset_presp = sdata->csa_counter_offset_presp[i]; |
| 2448 | */ | ||
| 2449 | if (WARN_ON(beacon_data[counter_offset_beacon] == 1)) | ||
| 2450 | return; | ||
| 2451 | 2449 | ||
| 2452 | beacon_data[counter_offset_beacon]--; | 2450 | if (counter_offset_beacon) { |
| 2451 | if (WARN_ON(counter_offset_beacon >= beacon_data_len)) | ||
| 2452 | return; | ||
| 2453 | 2453 | ||
| 2454 | if (sdata->vif.type == NL80211_IFTYPE_AP && counter_offset_presp) { | 2454 | beacon_data[counter_offset_beacon] = count; |
| 2455 | rcu_read_lock(); | 2455 | } |
| 2456 | resp = rcu_dereference(sdata->u.ap.probe_resp); | 2456 | |
| 2457 | if (sdata->vif.type == NL80211_IFTYPE_AP && | ||
| 2458 | counter_offset_presp) { | ||
| 2459 | rcu_read_lock(); | ||
| 2460 | resp = rcu_dereference(sdata->u.ap.probe_resp); | ||
| 2457 | 2461 | ||
| 2458 | /* if nl80211 accepted the offset, this should not happen. */ | 2462 | /* If nl80211 accepted the offset, this should |
| 2459 | if (WARN_ON(!resp)) { | 2463 | * not happen. |
| 2464 | */ | ||
| 2465 | if (WARN_ON(!resp)) { | ||
| 2466 | rcu_read_unlock(); | ||
| 2467 | return; | ||
| 2468 | } | ||
| 2469 | resp->data[counter_offset_presp] = count; | ||
| 2460 | rcu_read_unlock(); | 2470 | rcu_read_unlock(); |
| 2461 | return; | ||
| 2462 | } | 2471 | } |
| 2463 | resp->data[counter_offset_presp]--; | ||
| 2464 | rcu_read_unlock(); | ||
| 2465 | } | 2472 | } |
| 2466 | } | 2473 | } |
| 2467 | 2474 | ||
| 2475 | u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif) | ||
| 2476 | { | ||
| 2477 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
| 2478 | |||
| 2479 | sdata->csa_current_counter--; | ||
| 2480 | |||
| 2481 | /* the counter should never reach 0 */ | ||
| 2482 | WARN_ON(!sdata->csa_current_counter); | ||
| 2483 | |||
| 2484 | return sdata->csa_current_counter; | ||
| 2485 | } | ||
| 2486 | EXPORT_SYMBOL(ieee80211_csa_update_counter); | ||
| 2487 | |||
| 2468 | bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) | 2488 | bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) |
| 2469 | { | 2489 | { |
| 2470 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 2490 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
| 2471 | struct beacon_data *beacon = NULL; | 2491 | struct beacon_data *beacon = NULL; |
| 2472 | u8 *beacon_data; | 2492 | u8 *beacon_data; |
| 2473 | size_t beacon_data_len; | 2493 | size_t beacon_data_len; |
| 2474 | int counter_beacon = sdata->csa_counter_offset_beacon; | 2494 | int counter_beacon = sdata->csa_counter_offset_beacon[0]; |
| 2475 | int ret = false; | 2495 | int ret = false; |
| 2476 | 2496 | ||
| 2477 | if (!ieee80211_sdata_running(sdata)) | 2497 | if (!ieee80211_sdata_running(sdata)) |
| @@ -2521,9 +2541,11 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) | |||
| 2521 | } | 2541 | } |
| 2522 | EXPORT_SYMBOL(ieee80211_csa_is_complete); | 2542 | EXPORT_SYMBOL(ieee80211_csa_is_complete); |
| 2523 | 2543 | ||
| 2524 | struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | 2544 | static struct sk_buff * |
| 2525 | struct ieee80211_vif *vif, | 2545 | __ieee80211_beacon_get(struct ieee80211_hw *hw, |
| 2526 | u16 *tim_offset, u16 *tim_length) | 2546 | struct ieee80211_vif *vif, |
| 2547 | struct ieee80211_mutable_offsets *offs, | ||
| 2548 | bool is_template) | ||
| 2527 | { | 2549 | { |
| 2528 | struct ieee80211_local *local = hw_to_local(hw); | 2550 | struct ieee80211_local *local = hw_to_local(hw); |
| 2529 | struct sk_buff *skb = NULL; | 2551 | struct sk_buff *skb = NULL; |
| @@ -2532,6 +2554,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
| 2532 | enum ieee80211_band band; | 2554 | enum ieee80211_band band; |
| 2533 | struct ieee80211_tx_rate_control txrc; | 2555 | struct ieee80211_tx_rate_control txrc; |
| 2534 | struct ieee80211_chanctx_conf *chanctx_conf; | 2556 | struct ieee80211_chanctx_conf *chanctx_conf; |
| 2557 | int csa_off_base = 0; | ||
| 2535 | 2558 | ||
| 2536 | rcu_read_lock(); | 2559 | rcu_read_lock(); |
| 2537 | 2560 | ||
| @@ -2541,18 +2564,20 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
| 2541 | if (!ieee80211_sdata_running(sdata) || !chanctx_conf) | 2564 | if (!ieee80211_sdata_running(sdata) || !chanctx_conf) |
| 2542 | goto out; | 2565 | goto out; |
| 2543 | 2566 | ||
| 2544 | if (tim_offset) | 2567 | if (offs) |
| 2545 | *tim_offset = 0; | 2568 | memset(offs, 0, sizeof(*offs)); |
| 2546 | if (tim_length) | ||
| 2547 | *tim_length = 0; | ||
| 2548 | 2569 | ||
| 2549 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 2570 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
| 2550 | struct ieee80211_if_ap *ap = &sdata->u.ap; | 2571 | struct ieee80211_if_ap *ap = &sdata->u.ap; |
| 2551 | struct beacon_data *beacon = rcu_dereference(ap->beacon); | 2572 | struct beacon_data *beacon = rcu_dereference(ap->beacon); |
| 2552 | 2573 | ||
| 2553 | if (beacon) { | 2574 | if (beacon) { |
| 2554 | if (sdata->vif.csa_active) | 2575 | if (sdata->vif.csa_active) { |
| 2555 | ieee80211_update_csa(sdata, beacon); | 2576 | if (!is_template) |
| 2577 | ieee80211_csa_update_counter(vif); | ||
| 2578 | |||
| 2579 | ieee80211_set_csa(sdata, beacon); | ||
| 2580 | } | ||
| 2556 | 2581 | ||
| 2557 | /* | 2582 | /* |
| 2558 | * headroom, head length, | 2583 | * headroom, head length, |
| @@ -2569,12 +2594,16 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
| 2569 | memcpy(skb_put(skb, beacon->head_len), beacon->head, | 2594 | memcpy(skb_put(skb, beacon->head_len), beacon->head, |
| 2570 | beacon->head_len); | 2595 | beacon->head_len); |
| 2571 | 2596 | ||
| 2572 | ieee80211_beacon_add_tim(sdata, &ap->ps, skb); | 2597 | ieee80211_beacon_add_tim(sdata, &ap->ps, skb, |
| 2598 | is_template); | ||
| 2573 | 2599 | ||
| 2574 | if (tim_offset) | 2600 | if (offs) { |
| 2575 | *tim_offset = beacon->head_len; | 2601 | offs->tim_offset = beacon->head_len; |
| 2576 | if (tim_length) | 2602 | offs->tim_length = skb->len - beacon->head_len; |
| 2577 | *tim_length = skb->len - beacon->head_len; | 2603 | |
| 2604 | /* for AP the csa offsets are from tail */ | ||
| 2605 | csa_off_base = skb->len; | ||
| 2606 | } | ||
| 2578 | 2607 | ||
| 2579 | if (beacon->tail) | 2608 | if (beacon->tail) |
| 2580 | memcpy(skb_put(skb, beacon->tail_len), | 2609 | memcpy(skb_put(skb, beacon->tail_len), |
| @@ -2589,9 +2618,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
| 2589 | if (!presp) | 2618 | if (!presp) |
| 2590 | goto out; | 2619 | goto out; |
| 2591 | 2620 | ||
| 2592 | if (sdata->vif.csa_active) | 2621 | if (sdata->vif.csa_active) { |
| 2593 | ieee80211_update_csa(sdata, presp); | 2622 | if (!is_template) |
| 2623 | ieee80211_csa_update_counter(vif); | ||
| 2594 | 2624 | ||
| 2625 | ieee80211_set_csa(sdata, presp); | ||
| 2626 | } | ||
| 2595 | 2627 | ||
| 2596 | skb = dev_alloc_skb(local->tx_headroom + presp->head_len + | 2628 | skb = dev_alloc_skb(local->tx_headroom + presp->head_len + |
| 2597 | local->hw.extra_beacon_tailroom); | 2629 | local->hw.extra_beacon_tailroom); |
| @@ -2611,8 +2643,17 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
| 2611 | if (!bcn) | 2643 | if (!bcn) |
| 2612 | goto out; | 2644 | goto out; |
| 2613 | 2645 | ||
| 2614 | if (sdata->vif.csa_active) | 2646 | if (sdata->vif.csa_active) { |
| 2615 | ieee80211_update_csa(sdata, bcn); | 2647 | if (!is_template) |
| 2648 | /* TODO: For mesh csa_counter is in TU, so | ||
| 2649 | * decrementing it by one isn't correct, but | ||
| 2650 | * for now we leave it consistent with overall | ||
| 2651 | * mac80211's behavior. | ||
| 2652 | */ | ||
| 2653 | ieee80211_csa_update_counter(vif); | ||
| 2654 | |||
| 2655 | ieee80211_set_csa(sdata, bcn); | ||
| 2656 | } | ||
| 2616 | 2657 | ||
| 2617 | if (ifmsh->sync_ops) | 2658 | if (ifmsh->sync_ops) |
| 2618 | ifmsh->sync_ops->adjust_tbtt(sdata, bcn); | 2659 | ifmsh->sync_ops->adjust_tbtt(sdata, bcn); |
| @@ -2626,13 +2667,33 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
| 2626 | goto out; | 2667 | goto out; |
| 2627 | skb_reserve(skb, local->tx_headroom); | 2668 | skb_reserve(skb, local->tx_headroom); |
| 2628 | memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len); | 2669 | memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len); |
| 2629 | ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb); | 2670 | ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template); |
| 2671 | |||
| 2672 | if (offs) { | ||
| 2673 | offs->tim_offset = bcn->head_len; | ||
| 2674 | offs->tim_length = skb->len - bcn->head_len; | ||
| 2675 | } | ||
| 2676 | |||
| 2630 | memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len); | 2677 | memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len); |
| 2631 | } else { | 2678 | } else { |
| 2632 | WARN_ON(1); | 2679 | WARN_ON(1); |
| 2633 | goto out; | 2680 | goto out; |
| 2634 | } | 2681 | } |
| 2635 | 2682 | ||
| 2683 | /* CSA offsets */ | ||
| 2684 | if (offs) { | ||
| 2685 | int i; | ||
| 2686 | |||
| 2687 | for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) { | ||
| 2688 | u16 csa_off = sdata->csa_counter_offset_beacon[i]; | ||
| 2689 | |||
| 2690 | if (!csa_off) | ||
| 2691 | continue; | ||
| 2692 | |||
| 2693 | offs->csa_counter_offs[i] = csa_off_base + csa_off; | ||
| 2694 | } | ||
| 2695 | } | ||
| 2696 | |||
| 2636 | band = chanctx_conf->def.chan->band; | 2697 | band = chanctx_conf->def.chan->band; |
| 2637 | 2698 | ||
| 2638 | info = IEEE80211_SKB_CB(skb); | 2699 | info = IEEE80211_SKB_CB(skb); |
| @@ -2663,6 +2724,32 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
| 2663 | out: | 2724 | out: |
| 2664 | rcu_read_unlock(); | 2725 | rcu_read_unlock(); |
| 2665 | return skb; | 2726 | return skb; |
| 2727 | |||
| 2728 | } | ||
| 2729 | |||
| 2730 | struct sk_buff * | ||
| 2731 | ieee80211_beacon_get_template(struct ieee80211_hw *hw, | ||
| 2732 | struct ieee80211_vif *vif, | ||
| 2733 | struct ieee80211_mutable_offsets *offs) | ||
| 2734 | { | ||
| 2735 | return __ieee80211_beacon_get(hw, vif, offs, true); | ||
| 2736 | } | ||
| 2737 | EXPORT_SYMBOL(ieee80211_beacon_get_template); | ||
| 2738 | |||
| 2739 | struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | ||
| 2740 | struct ieee80211_vif *vif, | ||
| 2741 | u16 *tim_offset, u16 *tim_length) | ||
| 2742 | { | ||
| 2743 | struct ieee80211_mutable_offsets offs = {}; | ||
| 2744 | struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false); | ||
| 2745 | |||
| 2746 | if (tim_offset) | ||
| 2747 | *tim_offset = offs.tim_offset; | ||
| 2748 | |||
| 2749 | if (tim_length) | ||
| 2750 | *tim_length = offs.tim_length; | ||
| 2751 | |||
| 2752 | return bcn; | ||
| 2666 | } | 2753 | } |
| 2667 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); | 2754 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); |
| 2668 | 2755 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index c08bd4aca6bb..6886601afe1c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -1457,6 +1457,44 @@ void ieee80211_stop_device(struct ieee80211_local *local) | |||
| 1457 | drv_stop(local); | 1457 | drv_stop(local); |
| 1458 | } | 1458 | } |
| 1459 | 1459 | ||
| 1460 | static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) | ||
| 1461 | { | ||
| 1462 | struct ieee80211_sub_if_data *sdata; | ||
| 1463 | struct ieee80211_chanctx *ctx; | ||
| 1464 | |||
| 1465 | /* | ||
| 1466 | * We get here if during resume the device can't be restarted properly. | ||
| 1467 | * We might also get here if this happens during HW reset, which is a | ||
| 1468 | * slightly different situation and we need to drop all connections in | ||
| 1469 | * the latter case. | ||
| 1470 | * | ||
| 1471 | * Ask cfg80211 to turn off all interfaces, this will result in more | ||
| 1472 | * warnings but at least we'll then get into a clean stopped state. | ||
| 1473 | */ | ||
| 1474 | |||
| 1475 | local->resuming = false; | ||
| 1476 | local->suspended = false; | ||
| 1477 | local->started = false; | ||
| 1478 | |||
| 1479 | /* scheduled scan clearly can't be running any more, but tell | ||
| 1480 | * cfg80211 and clear local state | ||
| 1481 | */ | ||
| 1482 | ieee80211_sched_scan_end(local); | ||
| 1483 | |||
| 1484 | list_for_each_entry(sdata, &local->interfaces, list) | ||
| 1485 | sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER; | ||
| 1486 | |||
| 1487 | /* Mark channel contexts as not being in the driver any more to avoid | ||
| 1488 | * removing them from the driver during the shutdown process... | ||
| 1489 | */ | ||
| 1490 | mutex_lock(&local->chanctx_mtx); | ||
| 1491 | list_for_each_entry(ctx, &local->chanctx_list, list) | ||
| 1492 | ctx->driver_present = false; | ||
| 1493 | mutex_unlock(&local->chanctx_mtx); | ||
| 1494 | |||
| 1495 | cfg80211_shutdown_all_interfaces(local->hw.wiphy); | ||
| 1496 | } | ||
| 1497 | |||
| 1460 | static void ieee80211_assign_chanctx(struct ieee80211_local *local, | 1498 | static void ieee80211_assign_chanctx(struct ieee80211_local *local, |
| 1461 | struct ieee80211_sub_if_data *sdata) | 1499 | struct ieee80211_sub_if_data *sdata) |
| 1462 | { | 1500 | { |
| @@ -1520,9 +1558,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1520 | */ | 1558 | */ |
| 1521 | res = drv_start(local); | 1559 | res = drv_start(local); |
| 1522 | if (res) { | 1560 | if (res) { |
| 1523 | WARN(local->suspended, "Hardware became unavailable " | 1561 | if (local->suspended) |
| 1524 | "upon resume. This could be a software issue " | 1562 | WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n"); |
| 1525 | "prior to suspend or a hardware issue.\n"); | 1563 | else |
| 1564 | WARN(1, "Hardware became unavailable during restart.\n"); | ||
| 1565 | ieee80211_handle_reconfig_failure(local); | ||
| 1526 | return res; | 1566 | return res; |
| 1527 | } | 1567 | } |
| 1528 | 1568 | ||
diff --git a/net/nfc/digital.h b/net/nfc/digital.h index 3759add68b1b..71ad7eefddd4 100644 --- a/net/nfc/digital.h +++ b/net/nfc/digital.h | |||
| @@ -71,6 +71,7 @@ static inline int digital_in_send_cmd(struct nfc_digital_dev *ddev, | |||
| 71 | void digital_poll_next_tech(struct nfc_digital_dev *ddev); | 71 | void digital_poll_next_tech(struct nfc_digital_dev *ddev); |
| 72 | 72 | ||
| 73 | int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); | 73 | int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); |
| 74 | int digital_in_send_sensb_req(struct nfc_digital_dev *ddev, u8 rf_tech); | ||
| 74 | int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech); | 75 | int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech); |
| 75 | int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech); | 76 | int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech); |
| 76 | 77 | ||
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index e01e15dbf1ab..b105cfb00e76 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | #define DIGITAL_PROTO_NFCA_RF_TECH \ | 22 | #define DIGITAL_PROTO_NFCA_RF_TECH \ |
| 23 | (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | NFC_PROTO_NFC_DEP_MASK) | 23 | (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | NFC_PROTO_NFC_DEP_MASK) |
| 24 | 24 | ||
| 25 | #define DIGITAL_PROTO_NFCB_RF_TECH NFC_PROTO_ISO14443_B_MASK | ||
| 26 | |||
| 25 | #define DIGITAL_PROTO_NFCF_RF_TECH \ | 27 | #define DIGITAL_PROTO_NFCF_RF_TECH \ |
| 26 | (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK) | 28 | (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK) |
| 27 | 29 | ||
| @@ -345,6 +347,12 @@ int digital_target_found(struct nfc_digital_dev *ddev, | |||
| 345 | add_crc = digital_skb_add_crc_a; | 347 | add_crc = digital_skb_add_crc_a; |
| 346 | break; | 348 | break; |
| 347 | 349 | ||
| 350 | case NFC_PROTO_ISO14443_B: | ||
| 351 | framing = NFC_DIGITAL_FRAMING_NFCB_T4T; | ||
| 352 | check_crc = digital_skb_check_crc_b; | ||
| 353 | add_crc = digital_skb_add_crc_b; | ||
| 354 | break; | ||
| 355 | |||
| 348 | default: | 356 | default: |
| 349 | pr_err("Invalid protocol %d\n", protocol); | 357 | pr_err("Invalid protocol %d\n", protocol); |
| 350 | return -EINVAL; | 358 | return -EINVAL; |
| @@ -475,6 +483,10 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, | |||
| 475 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, | 483 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, |
| 476 | digital_in_send_sens_req); | 484 | digital_in_send_sens_req); |
| 477 | 485 | ||
| 486 | if (matching_im_protocols & DIGITAL_PROTO_NFCB_RF_TECH) | ||
| 487 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106B, | ||
| 488 | digital_in_send_sensb_req); | ||
| 489 | |||
| 478 | if (matching_im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { | 490 | if (matching_im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { |
| 479 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, | 491 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, |
| 480 | digital_in_send_sensf_req); | 492 | digital_in_send_sensf_req); |
| @@ -635,7 +647,8 @@ static void digital_in_send_complete(struct nfc_digital_dev *ddev, void *arg, | |||
| 635 | goto done; | 647 | goto done; |
| 636 | } | 648 | } |
| 637 | 649 | ||
| 638 | if (ddev->curr_protocol == NFC_PROTO_ISO14443) { | 650 | if ((ddev->curr_protocol == NFC_PROTO_ISO14443) || |
| 651 | (ddev->curr_protocol == NFC_PROTO_ISO14443_B)) { | ||
| 639 | rc = digital_in_iso_dep_pull_sod(ddev, resp); | 652 | rc = digital_in_iso_dep_pull_sod(ddev, resp); |
| 640 | if (rc) | 653 | if (rc) |
| 641 | goto done; | 654 | goto done; |
| @@ -676,7 +689,8 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
| 676 | goto exit; | 689 | goto exit; |
| 677 | } | 690 | } |
| 678 | 691 | ||
| 679 | if (ddev->curr_protocol == NFC_PROTO_ISO14443) { | 692 | if ((ddev->curr_protocol == NFC_PROTO_ISO14443) || |
| 693 | (ddev->curr_protocol == NFC_PROTO_ISO14443_B)) { | ||
| 680 | rc = digital_in_iso_dep_push_sod(ddev, skb); | 694 | rc = digital_in_iso_dep_push_sod(ddev, skb); |
| 681 | if (rc) | 695 | if (rc) |
| 682 | goto exit; | 696 | goto exit; |
| @@ -747,6 +761,8 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, | |||
| 747 | ddev->protocols |= NFC_PROTO_ISO15693_MASK; | 761 | ddev->protocols |= NFC_PROTO_ISO15693_MASK; |
| 748 | if (supported_protocols & NFC_PROTO_ISO14443_MASK) | 762 | if (supported_protocols & NFC_PROTO_ISO14443_MASK) |
| 749 | ddev->protocols |= NFC_PROTO_ISO14443_MASK; | 763 | ddev->protocols |= NFC_PROTO_ISO14443_MASK; |
| 764 | if (supported_protocols & NFC_PROTO_ISO14443_B_MASK) | ||
| 765 | ddev->protocols |= NFC_PROTO_ISO14443_B_MASK; | ||
| 750 | 766 | ||
| 751 | ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; | 767 | ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; |
| 752 | ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; | 768 | ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; |
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index 278c3fed27e0..12a233e9ece5 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c | |||
| @@ -41,6 +41,24 @@ | |||
| 41 | #define DIGITAL_MIFARE_READ_RES_LEN 16 | 41 | #define DIGITAL_MIFARE_READ_RES_LEN 16 |
| 42 | #define DIGITAL_MIFARE_ACK_RES 0x0A | 42 | #define DIGITAL_MIFARE_ACK_RES 0x0A |
| 43 | 43 | ||
| 44 | #define DIGITAL_CMD_SENSB_REQ 0x05 | ||
| 45 | #define DIGITAL_SENSB_ADVANCED BIT(5) | ||
| 46 | #define DIGITAL_SENSB_EXTENDED BIT(4) | ||
| 47 | #define DIGITAL_SENSB_ALLB_REQ BIT(3) | ||
| 48 | #define DIGITAL_SENSB_N(n) ((n) & 0x7) | ||
| 49 | |||
| 50 | #define DIGITAL_CMD_SENSB_RES 0x50 | ||
| 51 | |||
| 52 | #define DIGITAL_CMD_ATTRIB_REQ 0x1D | ||
| 53 | #define DIGITAL_ATTRIB_P1_TR0_DEFAULT (0x0 << 6) | ||
| 54 | #define DIGITAL_ATTRIB_P1_TR1_DEFAULT (0x0 << 4) | ||
| 55 | #define DIGITAL_ATTRIB_P1_SUPRESS_EOS BIT(3) | ||
| 56 | #define DIGITAL_ATTRIB_P1_SUPRESS_SOS BIT(2) | ||
| 57 | #define DIGITAL_ATTRIB_P2_LISTEN_POLL_1 (0x0 << 6) | ||
| 58 | #define DIGITAL_ATTRIB_P2_POLL_LISTEN_1 (0x0 << 4) | ||
| 59 | #define DIGITAL_ATTRIB_P2_MAX_FRAME_256 0x8 | ||
| 60 | #define DIGITAL_ATTRIB_P4_DID(n) ((n) & 0xf) | ||
| 61 | |||
| 44 | #define DIGITAL_CMD_SENSF_REQ 0x00 | 62 | #define DIGITAL_CMD_SENSF_REQ 0x00 |
| 45 | #define DIGITAL_CMD_SENSF_RES 0x01 | 63 | #define DIGITAL_CMD_SENSF_RES 0x01 |
| 46 | 64 | ||
| @@ -75,6 +93,7 @@ static const u8 digital_ats_fsc[] = { | |||
| 75 | }; | 93 | }; |
| 76 | 94 | ||
| 77 | #define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F) | 95 | #define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F) |
| 96 | #define DIGITAL_SENSB_FSCI(pi2) (((pi2) & 0xF0) >> 4) | ||
| 78 | #define DIGITAL_ATS_MAX_FSC 256 | 97 | #define DIGITAL_ATS_MAX_FSC 256 |
| 79 | 98 | ||
| 80 | #define DIGITAL_RATS_BYTE1 0xE0 | 99 | #define DIGITAL_RATS_BYTE1 0xE0 |
| @@ -92,6 +111,32 @@ struct digital_sel_req { | |||
| 92 | u8 bcc; | 111 | u8 bcc; |
| 93 | } __packed; | 112 | } __packed; |
| 94 | 113 | ||
| 114 | struct digital_sensb_req { | ||
| 115 | u8 cmd; | ||
| 116 | u8 afi; | ||
| 117 | u8 param; | ||
| 118 | } __packed; | ||
| 119 | |||
| 120 | struct digital_sensb_res { | ||
| 121 | u8 cmd; | ||
| 122 | u8 nfcid0[4]; | ||
| 123 | u8 app_data[4]; | ||
| 124 | u8 proto_info[3]; | ||
| 125 | } __packed; | ||
| 126 | |||
| 127 | struct digital_attrib_req { | ||
| 128 | u8 cmd; | ||
| 129 | u8 nfcid0[4]; | ||
| 130 | u8 param1; | ||
| 131 | u8 param2; | ||
| 132 | u8 param3; | ||
| 133 | u8 param4; | ||
| 134 | } __packed; | ||
| 135 | |||
| 136 | struct digital_attrib_res { | ||
| 137 | u8 mbli_did; | ||
| 138 | } __packed; | ||
| 139 | |||
| 95 | struct digital_sensf_req { | 140 | struct digital_sensf_req { |
| 96 | u8 cmd; | 141 | u8 cmd; |
| 97 | u8 sc1; | 142 | u8 sc1; |
| @@ -531,6 +576,175 @@ int digital_in_recv_mifare_res(struct sk_buff *resp) | |||
| 531 | return -EIO; | 576 | return -EIO; |
| 532 | } | 577 | } |
| 533 | 578 | ||
| 579 | static void digital_in_recv_attrib_res(struct nfc_digital_dev *ddev, void *arg, | ||
| 580 | struct sk_buff *resp) | ||
| 581 | { | ||
| 582 | struct nfc_target *target = arg; | ||
| 583 | struct digital_attrib_res *attrib_res; | ||
| 584 | int rc; | ||
| 585 | |||
| 586 | if (IS_ERR(resp)) { | ||
| 587 | rc = PTR_ERR(resp); | ||
| 588 | resp = NULL; | ||
| 589 | goto exit; | ||
| 590 | } | ||
| 591 | |||
| 592 | if (resp->len < sizeof(*attrib_res)) { | ||
| 593 | PROTOCOL_ERR("12.6.2"); | ||
| 594 | rc = -EIO; | ||
| 595 | goto exit; | ||
| 596 | } | ||
| 597 | |||
| 598 | attrib_res = (struct digital_attrib_res *)resp->data; | ||
| 599 | |||
| 600 | if (attrib_res->mbli_did & 0x0f) { | ||
| 601 | PROTOCOL_ERR("12.6.2.1"); | ||
| 602 | rc = -EIO; | ||
| 603 | goto exit; | ||
| 604 | } | ||
| 605 | |||
| 606 | rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443_B); | ||
| 607 | |||
| 608 | exit: | ||
| 609 | dev_kfree_skb(resp); | ||
| 610 | kfree(target); | ||
| 611 | |||
| 612 | if (rc) | ||
| 613 | digital_poll_next_tech(ddev); | ||
| 614 | } | ||
| 615 | |||
| 616 | int digital_in_send_attrib_req(struct nfc_digital_dev *ddev, | ||
| 617 | struct nfc_target *target, | ||
| 618 | struct digital_sensb_res *sensb_res) | ||
| 619 | { | ||
| 620 | struct digital_attrib_req *attrib_req; | ||
| 621 | struct sk_buff *skb; | ||
| 622 | int rc; | ||
| 623 | |||
| 624 | skb = digital_skb_alloc(ddev, sizeof(*attrib_req)); | ||
| 625 | if (!skb) | ||
| 626 | return -ENOMEM; | ||
| 627 | |||
| 628 | attrib_req = (struct digital_attrib_req *)skb_put(skb, | ||
| 629 | sizeof(*attrib_req)); | ||
| 630 | |||
| 631 | attrib_req->cmd = DIGITAL_CMD_ATTRIB_REQ; | ||
| 632 | memcpy(attrib_req->nfcid0, sensb_res->nfcid0, | ||
| 633 | sizeof(attrib_req->nfcid0)); | ||
| 634 | attrib_req->param1 = DIGITAL_ATTRIB_P1_TR0_DEFAULT | | ||
| 635 | DIGITAL_ATTRIB_P1_TR1_DEFAULT; | ||
| 636 | attrib_req->param2 = DIGITAL_ATTRIB_P2_LISTEN_POLL_1 | | ||
| 637 | DIGITAL_ATTRIB_P2_POLL_LISTEN_1 | | ||
| 638 | DIGITAL_ATTRIB_P2_MAX_FRAME_256; | ||
| 639 | attrib_req->param3 = sensb_res->proto_info[1] & 0x07; | ||
| 640 | attrib_req->param4 = DIGITAL_ATTRIB_P4_DID(0); | ||
| 641 | |||
| 642 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_attrib_res, | ||
| 643 | target); | ||
| 644 | if (rc) | ||
| 645 | kfree_skb(skb); | ||
| 646 | |||
| 647 | return rc; | ||
| 648 | } | ||
| 649 | |||
| 650 | static void digital_in_recv_sensb_res(struct nfc_digital_dev *ddev, void *arg, | ||
| 651 | struct sk_buff *resp) | ||
| 652 | { | ||
| 653 | struct nfc_target *target = NULL; | ||
| 654 | struct digital_sensb_res *sensb_res; | ||
| 655 | u8 fsci; | ||
| 656 | int rc; | ||
| 657 | |||
| 658 | if (IS_ERR(resp)) { | ||
| 659 | rc = PTR_ERR(resp); | ||
| 660 | resp = NULL; | ||
| 661 | goto exit; | ||
| 662 | } | ||
| 663 | |||
| 664 | if (resp->len != sizeof(*sensb_res)) { | ||
| 665 | PROTOCOL_ERR("5.6.2.1"); | ||
| 666 | rc = -EIO; | ||
| 667 | goto exit; | ||
| 668 | } | ||
| 669 | |||
| 670 | sensb_res = (struct digital_sensb_res *)resp->data; | ||
| 671 | |||
| 672 | if (sensb_res->cmd != DIGITAL_CMD_SENSB_RES) { | ||
| 673 | PROTOCOL_ERR("5.6.2"); | ||
| 674 | rc = -EIO; | ||
| 675 | goto exit; | ||
| 676 | } | ||
| 677 | |||
| 678 | if (!(sensb_res->proto_info[1] & BIT(0))) { | ||
| 679 | PROTOCOL_ERR("5.6.2.12"); | ||
| 680 | rc = -EIO; | ||
| 681 | goto exit; | ||
| 682 | } | ||
| 683 | |||
| 684 | if (sensb_res->proto_info[1] & BIT(3)) { | ||
| 685 | PROTOCOL_ERR("5.6.2.16"); | ||
| 686 | rc = -EIO; | ||
| 687 | goto exit; | ||
| 688 | } | ||
| 689 | |||
| 690 | fsci = DIGITAL_SENSB_FSCI(sensb_res->proto_info[1]); | ||
| 691 | if (fsci >= 8) | ||
| 692 | ddev->target_fsc = DIGITAL_ATS_MAX_FSC; | ||
| 693 | else | ||
| 694 | ddev->target_fsc = digital_ats_fsc[fsci]; | ||
| 695 | |||
| 696 | target = kzalloc(sizeof(struct nfc_target), GFP_KERNEL); | ||
| 697 | if (!target) { | ||
| 698 | rc = -ENOMEM; | ||
| 699 | goto exit; | ||
| 700 | } | ||
| 701 | |||
| 702 | rc = digital_in_send_attrib_req(ddev, target, sensb_res); | ||
| 703 | |||
| 704 | exit: | ||
| 705 | dev_kfree_skb(resp); | ||
| 706 | |||
| 707 | if (rc) { | ||
| 708 | kfree(target); | ||
| 709 | digital_poll_next_tech(ddev); | ||
| 710 | } | ||
| 711 | } | ||
| 712 | |||
| 713 | int digital_in_send_sensb_req(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
| 714 | { | ||
| 715 | struct digital_sensb_req *sensb_req; | ||
| 716 | struct sk_buff *skb; | ||
| 717 | int rc; | ||
| 718 | |||
| 719 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, | ||
| 720 | NFC_DIGITAL_RF_TECH_106B); | ||
| 721 | if (rc) | ||
| 722 | return rc; | ||
| 723 | |||
| 724 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
| 725 | NFC_DIGITAL_FRAMING_NFCB); | ||
| 726 | if (rc) | ||
| 727 | return rc; | ||
| 728 | |||
| 729 | skb = digital_skb_alloc(ddev, sizeof(*sensb_req)); | ||
| 730 | if (!skb) | ||
| 731 | return -ENOMEM; | ||
| 732 | |||
| 733 | sensb_req = (struct digital_sensb_req *)skb_put(skb, | ||
| 734 | sizeof(*sensb_req)); | ||
| 735 | |||
| 736 | sensb_req->cmd = DIGITAL_CMD_SENSB_REQ; | ||
| 737 | sensb_req->afi = 0x00; /* All families and sub-families */ | ||
| 738 | sensb_req->param = DIGITAL_SENSB_N(0); | ||
| 739 | |||
| 740 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sensb_res, | ||
| 741 | NULL); | ||
| 742 | if (rc) | ||
| 743 | kfree_skb(skb); | ||
| 744 | |||
| 745 | return rc; | ||
| 746 | } | ||
| 747 | |||
| 534 | static void digital_in_recv_sensf_res(struct nfc_digital_dev *ddev, void *arg, | 748 | static void digital_in_recv_sensf_res(struct nfc_digital_dev *ddev, void *arg, |
| 535 | struct sk_buff *resp) | 749 | struct sk_buff *resp) |
| 536 | { | 750 | { |
| @@ -877,6 +1091,18 @@ exit: | |||
| 877 | dev_kfree_skb(resp); | 1091 | dev_kfree_skb(resp); |
| 878 | } | 1092 | } |
| 879 | 1093 | ||
| 1094 | static void digital_tg_recv_atr_or_sensf_req(struct nfc_digital_dev *ddev, | ||
| 1095 | void *arg, struct sk_buff *resp) | ||
| 1096 | { | ||
| 1097 | if (!IS_ERR(resp) && (resp->len >= 2) && | ||
| 1098 | (resp->data[1] == DIGITAL_CMD_SENSF_REQ)) | ||
| 1099 | digital_tg_recv_sensf_req(ddev, arg, resp); | ||
| 1100 | else | ||
| 1101 | digital_tg_recv_atr_req(ddev, arg, resp); | ||
| 1102 | |||
| 1103 | return; | ||
| 1104 | } | ||
| 1105 | |||
| 880 | static int digital_tg_send_sensf_res(struct nfc_digital_dev *ddev, | 1106 | static int digital_tg_send_sensf_res(struct nfc_digital_dev *ddev, |
| 881 | struct digital_sensf_req *sensf_req) | 1107 | struct digital_sensf_req *sensf_req) |
| 882 | { | 1108 | { |
| @@ -887,7 +1113,7 @@ static int digital_tg_send_sensf_res(struct nfc_digital_dev *ddev, | |||
| 887 | 1113 | ||
| 888 | size = sizeof(struct digital_sensf_res); | 1114 | size = sizeof(struct digital_sensf_res); |
| 889 | 1115 | ||
| 890 | if (sensf_req->rc != DIGITAL_SENSF_REQ_RC_NONE) | 1116 | if (sensf_req->rc == DIGITAL_SENSF_REQ_RC_NONE) |
| 891 | size -= sizeof(sensf_res->rd); | 1117 | size -= sizeof(sensf_res->rd); |
| 892 | 1118 | ||
| 893 | skb = digital_skb_alloc(ddev, size); | 1119 | skb = digital_skb_alloc(ddev, size); |
| @@ -922,7 +1148,7 @@ static int digital_tg_send_sensf_res(struct nfc_digital_dev *ddev, | |||
| 922 | digital_skb_add_crc_f(skb); | 1148 | digital_skb_add_crc_f(skb); |
| 923 | 1149 | ||
| 924 | rc = digital_tg_send_cmd(ddev, skb, 300, | 1150 | rc = digital_tg_send_cmd(ddev, skb, 300, |
| 925 | digital_tg_recv_atr_req, NULL); | 1151 | digital_tg_recv_atr_or_sensf_req, NULL); |
| 926 | if (rc) | 1152 | if (rc) |
| 927 | kfree_skb(skb); | 1153 | kfree_skb(skb); |
| 928 | 1154 | ||
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index a9f4d2e62d8d..677d24bb70f8 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | 26 | ||
| 27 | #include "hci.h" | 27 | #include "hci.h" |
| 28 | 28 | ||
| 29 | #define MAX_FWI 4949 | ||
| 30 | |||
| 29 | static int nfc_hci_execute_cmd_async(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | 31 | static int nfc_hci_execute_cmd_async(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, |
| 30 | const u8 *param, size_t param_len, | 32 | const u8 *param, size_t param_len, |
| 31 | data_exchange_cb_t cb, void *cb_context) | 33 | data_exchange_cb_t cb, void *cb_context) |
| @@ -37,7 +39,7 @@ static int nfc_hci_execute_cmd_async(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | |||
| 37 | * for all commands? | 39 | * for all commands? |
| 38 | */ | 40 | */ |
| 39 | return nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_COMMAND, cmd, | 41 | return nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_COMMAND, cmd, |
| 40 | param, param_len, cb, cb_context, 3000); | 42 | param, param_len, cb, cb_context, MAX_FWI); |
| 41 | } | 43 | } |
| 42 | 44 | ||
| 43 | /* | 45 | /* |
| @@ -82,7 +84,7 @@ static int nfc_hci_execute_cmd(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | |||
| 82 | NFC_HCI_HCP_COMMAND, cmd, | 84 | NFC_HCI_HCP_COMMAND, cmd, |
| 83 | param, param_len, | 85 | param, param_len, |
| 84 | nfc_hci_execute_cb, &hcp_ew, | 86 | nfc_hci_execute_cb, &hcp_ew, |
| 85 | 3000); | 87 | MAX_FWI); |
| 86 | if (hcp_ew.exec_result < 0) | 88 | if (hcp_ew.exec_result < 0) |
| 87 | return hcp_ew.exec_result; | 89 | return hcp_ew.exec_result; |
| 88 | 90 | ||
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index d45b638e77c7..47403705197e 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
| @@ -225,7 +225,7 @@ int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) | |||
| 225 | goto exit; | 225 | goto exit; |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | targets->sens_res = be16_to_cpu(*(u16 *)atqa_skb->data); | 228 | targets->sens_res = be16_to_cpu(*(__be16 *)atqa_skb->data); |
| 229 | targets->sel_res = sak_skb->data[0]; | 229 | targets->sel_res = sak_skb->data[0]; |
| 230 | 230 | ||
| 231 | r = nfc_hci_get_param(hdev, NFC_HCI_RF_READER_A_GATE, | 231 | r = nfc_hci_get_param(hdev, NFC_HCI_RF_READER_A_GATE, |
| @@ -380,34 +380,31 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev) | |||
| 380 | if (r < 0) | 380 | if (r < 0) |
| 381 | goto disconnect_all; | 381 | goto disconnect_all; |
| 382 | 382 | ||
| 383 | if (skb->len && skb->len == strlen(hdev->init_data.session_id)) | 383 | if (skb->len && skb->len == strlen(hdev->init_data.session_id) && |
| 384 | if (memcmp(hdev->init_data.session_id, skb->data, | 384 | (memcmp(hdev->init_data.session_id, skb->data, |
| 385 | skb->len) == 0) { | 385 | skb->len) == 0) && hdev->ops->load_session) { |
| 386 | /* TODO ELa: restore gate<->pipe table from | 386 | /* Restore gate<->pipe table from some proprietary location. */ |
| 387 | * some TBD location. | ||
| 388 | * note: it doesn't seem possible to get the chip | ||
| 389 | * currently open gate/pipe table. | ||
| 390 | * It is only possible to obtain the supported | ||
| 391 | * gate list. | ||
| 392 | */ | ||
| 393 | 387 | ||
| 394 | /* goto exit | 388 | r = hdev->ops->load_session(hdev); |
| 395 | * For now, always do a full initialization */ | ||
| 396 | } | ||
| 397 | 389 | ||
| 398 | r = nfc_hci_disconnect_all_gates(hdev); | 390 | if (r < 0) |
| 399 | if (r < 0) | 391 | goto disconnect_all; |
| 400 | goto exit; | 392 | } else { |
| 401 | 393 | ||
| 402 | r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count, | 394 | r = nfc_hci_disconnect_all_gates(hdev); |
| 403 | hdev->init_data.gates); | 395 | if (r < 0) |
| 404 | if (r < 0) | 396 | goto exit; |
| 405 | goto disconnect_all; | ||
| 406 | 397 | ||
| 407 | r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, | 398 | r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count, |
| 408 | NFC_HCI_ADMIN_SESSION_IDENTITY, | 399 | hdev->init_data.gates); |
| 409 | hdev->init_data.session_id, | 400 | if (r < 0) |
| 410 | strlen(hdev->init_data.session_id)); | 401 | goto disconnect_all; |
| 402 | |||
| 403 | r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, | ||
| 404 | NFC_HCI_ADMIN_SESSION_IDENTITY, | ||
| 405 | hdev->init_data.session_id, | ||
| 406 | strlen(hdev->init_data.session_id)); | ||
| 407 | } | ||
| 411 | if (r == 0) | 408 | if (r == 0) |
| 412 | goto exit; | 409 | goto exit; |
| 413 | 410 | ||
diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c index bec6ed15f503..a3ad69a4c648 100644 --- a/net/nfc/llcp_commands.c +++ b/net/nfc/llcp_commands.c | |||
| @@ -387,7 +387,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) | |||
| 387 | 387 | ||
| 388 | __net_timestamp(skb); | 388 | __net_timestamp(skb); |
| 389 | 389 | ||
| 390 | nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX); | 390 | nfc_llcp_send_to_raw_sock(local, skb, NFC_DIRECTION_TX); |
| 391 | 391 | ||
| 392 | return nfc_data_exchange(dev, local->target_idx, skb, | 392 | return nfc_data_exchange(dev, local->target_idx, skb, |
| 393 | nfc_llcp_recv, local); | 393 | nfc_llcp_recv, local); |
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index b4671958fcf9..f6278da68763 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c | |||
| @@ -680,16 +680,17 @@ void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local, | |||
| 680 | continue; | 680 | continue; |
| 681 | 681 | ||
| 682 | if (skb_copy == NULL) { | 682 | if (skb_copy == NULL) { |
| 683 | skb_copy = __pskb_copy(skb, NFC_LLCP_RAW_HEADER_SIZE, | 683 | skb_copy = __pskb_copy(skb, NFC_RAW_HEADER_SIZE, |
| 684 | GFP_ATOMIC); | 684 | GFP_ATOMIC); |
| 685 | 685 | ||
| 686 | if (skb_copy == NULL) | 686 | if (skb_copy == NULL) |
| 687 | continue; | 687 | continue; |
| 688 | 688 | ||
| 689 | data = skb_push(skb_copy, NFC_LLCP_RAW_HEADER_SIZE); | 689 | data = skb_push(skb_copy, NFC_RAW_HEADER_SIZE); |
| 690 | 690 | ||
| 691 | data[0] = local->dev ? local->dev->idx : 0xFF; | 691 | data[0] = local->dev ? local->dev->idx : 0xFF; |
| 692 | data[1] = direction; | 692 | data[1] = direction & 0x01; |
| 693 | data[1] |= (RAW_PAYLOAD_LLCP << 1); | ||
| 693 | } | 694 | } |
| 694 | 695 | ||
| 695 | nskb = skb_clone(skb_copy, GFP_ATOMIC); | 696 | nskb = skb_clone(skb_copy, GFP_ATOMIC); |
| @@ -747,7 +748,7 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
| 747 | __net_timestamp(skb); | 748 | __net_timestamp(skb); |
| 748 | 749 | ||
| 749 | nfc_llcp_send_to_raw_sock(local, skb, | 750 | nfc_llcp_send_to_raw_sock(local, skb, |
| 750 | NFC_LLCP_DIRECTION_TX); | 751 | NFC_DIRECTION_TX); |
| 751 | 752 | ||
| 752 | ret = nfc_data_exchange(local->dev, local->target_idx, | 753 | ret = nfc_data_exchange(local->dev, local->target_idx, |
| 753 | skb, nfc_llcp_recv, local); | 754 | skb, nfc_llcp_recv, local); |
| @@ -1476,7 +1477,7 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
| 1476 | 1477 | ||
| 1477 | __net_timestamp(skb); | 1478 | __net_timestamp(skb); |
| 1478 | 1479 | ||
| 1479 | nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX); | 1480 | nfc_llcp_send_to_raw_sock(local, skb, NFC_DIRECTION_RX); |
| 1480 | 1481 | ||
| 1481 | nfc_llcp_rx_skb(local, skb); | 1482 | nfc_llcp_rx_skb(local, skb); |
| 1482 | 1483 | ||
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 6c34ac978501..2b400e1a8695 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
| @@ -861,6 +861,10 @@ static int nci_send_frame(struct nci_dev *ndev, struct sk_buff *skb) | |||
| 861 | /* Get rid of skb owner, prior to sending to the driver. */ | 861 | /* Get rid of skb owner, prior to sending to the driver. */ |
| 862 | skb_orphan(skb); | 862 | skb_orphan(skb); |
| 863 | 863 | ||
| 864 | /* Send copy to sniffer */ | ||
| 865 | nfc_send_to_raw_sock(ndev->nfc_dev, skb, | ||
| 866 | RAW_PAYLOAD_NCI, NFC_DIRECTION_TX); | ||
| 867 | |||
| 864 | return ndev->ops->send(ndev, skb); | 868 | return ndev->ops->send(ndev, skb); |
| 865 | } | 869 | } |
| 866 | 870 | ||
| @@ -935,6 +939,11 @@ static void nci_rx_work(struct work_struct *work) | |||
| 935 | struct sk_buff *skb; | 939 | struct sk_buff *skb; |
| 936 | 940 | ||
| 937 | while ((skb = skb_dequeue(&ndev->rx_q))) { | 941 | while ((skb = skb_dequeue(&ndev->rx_q))) { |
| 942 | |||
| 943 | /* Send copy to sniffer */ | ||
| 944 | nfc_send_to_raw_sock(ndev->nfc_dev, skb, | ||
| 945 | RAW_PAYLOAD_NCI, NFC_DIRECTION_RX); | ||
| 946 | |||
| 938 | /* Process frame */ | 947 | /* Process frame */ |
| 939 | switch (nci_mt(skb->data)) { | 948 | switch (nci_mt(skb->data)) { |
| 940 | case NCI_MT_RSP_PKT: | 949 | case NCI_MT_RSP_PKT: |
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index 1e905097456b..f8f6af231381 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c | |||
| @@ -366,7 +366,6 @@ static int nci_extract_activation_params_nfc_dep(struct nci_dev *ndev, | |||
| 366 | struct nci_rf_intf_activated_ntf *ntf, __u8 *data) | 366 | struct nci_rf_intf_activated_ntf *ntf, __u8 *data) |
| 367 | { | 367 | { |
| 368 | struct activation_params_poll_nfc_dep *poll; | 368 | struct activation_params_poll_nfc_dep *poll; |
| 369 | int i; | ||
| 370 | 369 | ||
| 371 | switch (ntf->activation_rf_tech_and_mode) { | 370 | switch (ntf->activation_rf_tech_and_mode) { |
| 372 | case NCI_NFC_A_PASSIVE_POLL_MODE: | 371 | case NCI_NFC_A_PASSIVE_POLL_MODE: |
| @@ -374,10 +373,8 @@ static int nci_extract_activation_params_nfc_dep(struct nci_dev *ndev, | |||
| 374 | poll = &ntf->activation_params.poll_nfc_dep; | 373 | poll = &ntf->activation_params.poll_nfc_dep; |
| 375 | poll->atr_res_len = min_t(__u8, *data++, 63); | 374 | poll->atr_res_len = min_t(__u8, *data++, 63); |
| 376 | pr_debug("atr_res_len %d\n", poll->atr_res_len); | 375 | pr_debug("atr_res_len %d\n", poll->atr_res_len); |
| 377 | if (poll->atr_res_len > 0) { | 376 | if (poll->atr_res_len > 0) |
| 378 | for (i = 0; i < poll->atr_res_len; i++) | 377 | memcpy(poll->atr_res, data, poll->atr_res_len); |
| 379 | poll->atr_res[poll->atr_res_len-1-i] = data[i]; | ||
| 380 | } | ||
| 381 | break; | 378 | break; |
| 382 | 379 | ||
| 383 | default: | 380 | default: |
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index 9d6e74f7e6b3..88d60064890e 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
| @@ -40,6 +40,12 @@ struct nfc_rawsock { | |||
| 40 | struct work_struct tx_work; | 40 | struct work_struct tx_work; |
| 41 | bool tx_work_scheduled; | 41 | bool tx_work_scheduled; |
| 42 | }; | 42 | }; |
| 43 | |||
| 44 | struct nfc_sock_list { | ||
| 45 | struct hlist_head head; | ||
| 46 | rwlock_t lock; | ||
| 47 | }; | ||
| 48 | |||
| 43 | #define nfc_rawsock(sk) ((struct nfc_rawsock *) sk) | 49 | #define nfc_rawsock(sk) ((struct nfc_rawsock *) sk) |
| 44 | #define to_rawsock_sk(_tx_work) \ | 50 | #define to_rawsock_sk(_tx_work) \ |
| 45 | ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work)) | 51 | ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work)) |
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index c27a6e86cae4..8627c75063e2 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c | |||
| @@ -27,6 +27,24 @@ | |||
| 27 | 27 | ||
| 28 | #include "nfc.h" | 28 | #include "nfc.h" |
| 29 | 29 | ||
| 30 | static struct nfc_sock_list raw_sk_list = { | ||
| 31 | .lock = __RW_LOCK_UNLOCKED(raw_sk_list.lock) | ||
| 32 | }; | ||
| 33 | |||
| 34 | void nfc_sock_link(struct nfc_sock_list *l, struct sock *sk) | ||
| 35 | { | ||
| 36 | write_lock(&l->lock); | ||
| 37 | sk_add_node(sk, &l->head); | ||
| 38 | write_unlock(&l->lock); | ||
| 39 | } | ||
| 40 | |||
| 41 | void nfc_sock_unlink(struct nfc_sock_list *l, struct sock *sk) | ||
| 42 | { | ||
| 43 | write_lock(&l->lock); | ||
| 44 | sk_del_node_init(sk); | ||
| 45 | write_unlock(&l->lock); | ||
| 46 | } | ||
| 47 | |||
| 30 | static void rawsock_write_queue_purge(struct sock *sk) | 48 | static void rawsock_write_queue_purge(struct sock *sk) |
| 31 | { | 49 | { |
| 32 | pr_debug("sk=%p\n", sk); | 50 | pr_debug("sk=%p\n", sk); |
| @@ -57,6 +75,9 @@ static int rawsock_release(struct socket *sock) | |||
| 57 | if (!sk) | 75 | if (!sk) |
| 58 | return 0; | 76 | return 0; |
| 59 | 77 | ||
| 78 | if (sock->type == SOCK_RAW) | ||
| 79 | nfc_sock_unlink(&raw_sk_list, sk); | ||
| 80 | |||
| 60 | sock_orphan(sk); | 81 | sock_orphan(sk); |
| 61 | sock_put(sk); | 82 | sock_put(sk); |
| 62 | 83 | ||
| @@ -275,6 +296,26 @@ static const struct proto_ops rawsock_ops = { | |||
| 275 | .mmap = sock_no_mmap, | 296 | .mmap = sock_no_mmap, |
| 276 | }; | 297 | }; |
| 277 | 298 | ||
| 299 | static const struct proto_ops rawsock_raw_ops = { | ||
| 300 | .family = PF_NFC, | ||
| 301 | .owner = THIS_MODULE, | ||
| 302 | .release = rawsock_release, | ||
| 303 | .bind = sock_no_bind, | ||
| 304 | .connect = sock_no_connect, | ||
| 305 | .socketpair = sock_no_socketpair, | ||
| 306 | .accept = sock_no_accept, | ||
| 307 | .getname = sock_no_getname, | ||
| 308 | .poll = datagram_poll, | ||
| 309 | .ioctl = sock_no_ioctl, | ||
| 310 | .listen = sock_no_listen, | ||
| 311 | .shutdown = sock_no_shutdown, | ||
| 312 | .setsockopt = sock_no_setsockopt, | ||
| 313 | .getsockopt = sock_no_getsockopt, | ||
| 314 | .sendmsg = sock_no_sendmsg, | ||
| 315 | .recvmsg = rawsock_recvmsg, | ||
| 316 | .mmap = sock_no_mmap, | ||
| 317 | }; | ||
| 318 | |||
| 278 | static void rawsock_destruct(struct sock *sk) | 319 | static void rawsock_destruct(struct sock *sk) |
| 279 | { | 320 | { |
| 280 | pr_debug("sk=%p\n", sk); | 321 | pr_debug("sk=%p\n", sk); |
| @@ -300,10 +341,13 @@ static int rawsock_create(struct net *net, struct socket *sock, | |||
| 300 | 341 | ||
| 301 | pr_debug("sock=%p\n", sock); | 342 | pr_debug("sock=%p\n", sock); |
| 302 | 343 | ||
| 303 | if (sock->type != SOCK_SEQPACKET) | 344 | if ((sock->type != SOCK_SEQPACKET) && (sock->type != SOCK_RAW)) |
| 304 | return -ESOCKTNOSUPPORT; | 345 | return -ESOCKTNOSUPPORT; |
| 305 | 346 | ||
| 306 | sock->ops = &rawsock_ops; | 347 | if (sock->type == SOCK_RAW) |
| 348 | sock->ops = &rawsock_raw_ops; | ||
| 349 | else | ||
| 350 | sock->ops = &rawsock_ops; | ||
| 307 | 351 | ||
| 308 | sk = sk_alloc(net, PF_NFC, GFP_ATOMIC, nfc_proto->proto); | 352 | sk = sk_alloc(net, PF_NFC, GFP_ATOMIC, nfc_proto->proto); |
| 309 | if (!sk) | 353 | if (!sk) |
| @@ -313,13 +357,53 @@ static int rawsock_create(struct net *net, struct socket *sock, | |||
| 313 | sk->sk_protocol = nfc_proto->id; | 357 | sk->sk_protocol = nfc_proto->id; |
| 314 | sk->sk_destruct = rawsock_destruct; | 358 | sk->sk_destruct = rawsock_destruct; |
| 315 | sock->state = SS_UNCONNECTED; | 359 | sock->state = SS_UNCONNECTED; |
| 316 | 360 | if (sock->type == SOCK_RAW) | |
| 317 | INIT_WORK(&nfc_rawsock(sk)->tx_work, rawsock_tx_work); | 361 | nfc_sock_link(&raw_sk_list, sk); |
| 318 | nfc_rawsock(sk)->tx_work_scheduled = false; | 362 | else { |
| 363 | INIT_WORK(&nfc_rawsock(sk)->tx_work, rawsock_tx_work); | ||
| 364 | nfc_rawsock(sk)->tx_work_scheduled = false; | ||
| 365 | } | ||
| 319 | 366 | ||
| 320 | return 0; | 367 | return 0; |
| 321 | } | 368 | } |
| 322 | 369 | ||
| 370 | void nfc_send_to_raw_sock(struct nfc_dev *dev, struct sk_buff *skb, | ||
| 371 | u8 payload_type, u8 direction) | ||
| 372 | { | ||
| 373 | struct sk_buff *skb_copy = NULL, *nskb; | ||
| 374 | struct sock *sk; | ||
| 375 | u8 *data; | ||
| 376 | |||
| 377 | read_lock(&raw_sk_list.lock); | ||
| 378 | |||
| 379 | sk_for_each(sk, &raw_sk_list.head) { | ||
| 380 | if (!skb_copy) { | ||
| 381 | skb_copy = __pskb_copy(skb, NFC_RAW_HEADER_SIZE, | ||
| 382 | GFP_ATOMIC); | ||
| 383 | if (!skb_copy) | ||
| 384 | continue; | ||
| 385 | |||
| 386 | data = skb_push(skb_copy, NFC_RAW_HEADER_SIZE); | ||
| 387 | |||
| 388 | data[0] = dev ? dev->idx : 0xFF; | ||
| 389 | data[1] = direction & 0x01; | ||
| 390 | data[1] |= (payload_type << 1); | ||
| 391 | } | ||
| 392 | |||
| 393 | nskb = skb_clone(skb_copy, GFP_ATOMIC); | ||
| 394 | if (!nskb) | ||
| 395 | continue; | ||
| 396 | |||
| 397 | if (sock_queue_rcv_skb(sk, nskb)) | ||
| 398 | kfree_skb(nskb); | ||
| 399 | } | ||
| 400 | |||
| 401 | read_unlock(&raw_sk_list.lock); | ||
| 402 | |||
| 403 | kfree_skb(skb_copy); | ||
| 404 | } | ||
| 405 | EXPORT_SYMBOL(nfc_send_to_raw_sock); | ||
| 406 | |||
| 323 | static struct proto rawsock_proto = { | 407 | static struct proto rawsock_proto = { |
| 324 | .name = "NFC_RAW", | 408 | .name = "NFC_RAW", |
| 325 | .owner = THIS_MODULE, | 409 | .owner = THIS_MODULE, |
diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c index c2be901d19ee..6cd9d1deafc3 100644 --- a/net/rds/rdma_transport.c +++ b/net/rds/rdma_transport.c | |||
| @@ -168,7 +168,7 @@ static int rds_rdma_listen_init(void) | |||
| 168 | return ret; | 168 | return ret; |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | sin.sin_family = AF_INET, | 171 | sin.sin_family = AF_INET; |
| 172 | sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY); | 172 | sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY); |
| 173 | sin.sin_port = (__force u16)htons(RDS_PORT); | 173 | sin.sin_port = (__force u16)htons(RDS_PORT); |
| 174 | 174 | ||
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 4e638f851185..23ab4dcd1d9f 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c | |||
| @@ -153,7 +153,7 @@ int rds_tcp_listen_init(void) | |||
| 153 | sock->sk->sk_data_ready = rds_tcp_listen_data_ready; | 153 | sock->sk->sk_data_ready = rds_tcp_listen_data_ready; |
| 154 | write_unlock_bh(&sock->sk->sk_callback_lock); | 154 | write_unlock_bh(&sock->sk->sk_callback_lock); |
| 155 | 155 | ||
| 156 | sin.sin_family = PF_INET, | 156 | sin.sin_family = PF_INET; |
| 157 | sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY); | 157 | sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY); |
| 158 | sin.sin_port = (__force u16)htons(RDS_TCP_PORT); | 158 | sin.sin_port = (__force u16)htons(RDS_TCP_PORT); |
| 159 | 159 | ||
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c index bd2a5b90400c..14c98e48f261 100644 --- a/net/rfkill/rfkill-gpio.c +++ b/net/rfkill/rfkill-gpio.c | |||
| @@ -36,8 +36,6 @@ struct rfkill_gpio_data { | |||
| 36 | struct gpio_desc *shutdown_gpio; | 36 | struct gpio_desc *shutdown_gpio; |
| 37 | 37 | ||
| 38 | struct rfkill *rfkill_dev; | 38 | struct rfkill *rfkill_dev; |
| 39 | char *reset_name; | ||
| 40 | char *shutdown_name; | ||
| 41 | struct clk *clk; | 39 | struct clk *clk; |
| 42 | 40 | ||
| 43 | bool clk_enabled; | 41 | bool clk_enabled; |
| @@ -47,17 +45,14 @@ static int rfkill_gpio_set_power(void *data, bool blocked) | |||
| 47 | { | 45 | { |
| 48 | struct rfkill_gpio_data *rfkill = data; | 46 | struct rfkill_gpio_data *rfkill = data; |
| 49 | 47 | ||
| 50 | if (blocked) { | 48 | if (!blocked && !IS_ERR(rfkill->clk) && !rfkill->clk_enabled) |
| 51 | gpiod_set_value(rfkill->shutdown_gpio, 0); | 49 | clk_enable(rfkill->clk); |
| 52 | gpiod_set_value(rfkill->reset_gpio, 0); | 50 | |
| 53 | if (!IS_ERR(rfkill->clk) && rfkill->clk_enabled) | 51 | gpiod_set_value_cansleep(rfkill->shutdown_gpio, !blocked); |
| 54 | clk_disable(rfkill->clk); | 52 | gpiod_set_value_cansleep(rfkill->reset_gpio, !blocked); |
| 55 | } else { | 53 | |
| 56 | if (!IS_ERR(rfkill->clk) && !rfkill->clk_enabled) | 54 | if (blocked && !IS_ERR(rfkill->clk) && rfkill->clk_enabled) |
| 57 | clk_enable(rfkill->clk); | 55 | clk_disable(rfkill->clk); |
| 58 | gpiod_set_value(rfkill->reset_gpio, 1); | ||
| 59 | gpiod_set_value(rfkill->shutdown_gpio, 1); | ||
| 60 | } | ||
| 61 | 56 | ||
| 62 | rfkill->clk_enabled = blocked; | 57 | rfkill->clk_enabled = blocked; |
| 63 | 58 | ||
| @@ -87,10 +82,8 @@ static int rfkill_gpio_probe(struct platform_device *pdev) | |||
| 87 | { | 82 | { |
| 88 | struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; | 83 | struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; |
| 89 | struct rfkill_gpio_data *rfkill; | 84 | struct rfkill_gpio_data *rfkill; |
| 90 | const char *clk_name = NULL; | ||
| 91 | struct gpio_desc *gpio; | 85 | struct gpio_desc *gpio; |
| 92 | int ret; | 86 | int ret; |
| 93 | int len; | ||
| 94 | 87 | ||
| 95 | rfkill = devm_kzalloc(&pdev->dev, sizeof(*rfkill), GFP_KERNEL); | 88 | rfkill = devm_kzalloc(&pdev->dev, sizeof(*rfkill), GFP_KERNEL); |
| 96 | if (!rfkill) | 89 | if (!rfkill) |
| @@ -101,28 +94,15 @@ static int rfkill_gpio_probe(struct platform_device *pdev) | |||
| 101 | if (ret) | 94 | if (ret) |
| 102 | return ret; | 95 | return ret; |
| 103 | } else if (pdata) { | 96 | } else if (pdata) { |
| 104 | clk_name = pdata->power_clk_name; | ||
| 105 | rfkill->name = pdata->name; | 97 | rfkill->name = pdata->name; |
| 106 | rfkill->type = pdata->type; | 98 | rfkill->type = pdata->type; |
| 107 | } else { | 99 | } else { |
| 108 | return -ENODEV; | 100 | return -ENODEV; |
| 109 | } | 101 | } |
| 110 | 102 | ||
| 111 | len = strlen(rfkill->name); | 103 | rfkill->clk = devm_clk_get(&pdev->dev, NULL); |
| 112 | rfkill->reset_name = devm_kzalloc(&pdev->dev, len + 7, GFP_KERNEL); | ||
| 113 | if (!rfkill->reset_name) | ||
| 114 | return -ENOMEM; | ||
| 115 | |||
| 116 | rfkill->shutdown_name = devm_kzalloc(&pdev->dev, len + 10, GFP_KERNEL); | ||
| 117 | if (!rfkill->shutdown_name) | ||
| 118 | return -ENOMEM; | ||
| 119 | 104 | ||
| 120 | snprintf(rfkill->reset_name, len + 6 , "%s_reset", rfkill->name); | 105 | gpio = devm_gpiod_get_index(&pdev->dev, "reset", 0); |
| 121 | snprintf(rfkill->shutdown_name, len + 9, "%s_shutdown", rfkill->name); | ||
| 122 | |||
| 123 | rfkill->clk = devm_clk_get(&pdev->dev, clk_name); | ||
| 124 | |||
| 125 | gpio = devm_gpiod_get_index(&pdev->dev, rfkill->reset_name, 0); | ||
| 126 | if (!IS_ERR(gpio)) { | 106 | if (!IS_ERR(gpio)) { |
| 127 | ret = gpiod_direction_output(gpio, 0); | 107 | ret = gpiod_direction_output(gpio, 0); |
| 128 | if (ret) | 108 | if (ret) |
| @@ -130,7 +110,7 @@ static int rfkill_gpio_probe(struct platform_device *pdev) | |||
| 130 | rfkill->reset_gpio = gpio; | 110 | rfkill->reset_gpio = gpio; |
| 131 | } | 111 | } |
| 132 | 112 | ||
| 133 | gpio = devm_gpiod_get_index(&pdev->dev, rfkill->shutdown_name, 1); | 113 | gpio = devm_gpiod_get_index(&pdev->dev, "shutdown", 1); |
| 134 | if (!IS_ERR(gpio)) { | 114 | if (!IS_ERR(gpio)) { |
| 135 | ret = gpiod_direction_output(gpio, 0); | 115 | ret = gpiod_direction_output(gpio, 0); |
| 136 | if (ret) | 116 | if (ret) |
| @@ -146,14 +126,6 @@ static int rfkill_gpio_probe(struct platform_device *pdev) | |||
| 146 | return -EINVAL; | 126 | return -EINVAL; |
| 147 | } | 127 | } |
| 148 | 128 | ||
| 149 | if (pdata && pdata->gpio_runtime_setup) { | ||
| 150 | ret = pdata->gpio_runtime_setup(pdev); | ||
| 151 | if (ret) { | ||
| 152 | dev_err(&pdev->dev, "can't set up gpio\n"); | ||
| 153 | return ret; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | rfkill->rfkill_dev = rfkill_alloc(rfkill->name, &pdev->dev, | 129 | rfkill->rfkill_dev = rfkill_alloc(rfkill->name, &pdev->dev, |
| 158 | rfkill->type, &rfkill_gpio_ops, | 130 | rfkill->type, &rfkill_gpio_ops, |
| 159 | rfkill); | 131 | rfkill); |
| @@ -174,20 +146,23 @@ static int rfkill_gpio_probe(struct platform_device *pdev) | |||
| 174 | static int rfkill_gpio_remove(struct platform_device *pdev) | 146 | static int rfkill_gpio_remove(struct platform_device *pdev) |
| 175 | { | 147 | { |
| 176 | struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev); | 148 | struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev); |
| 177 | struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data; | ||
| 178 | 149 | ||
| 179 | if (pdata && pdata->gpio_runtime_close) | ||
| 180 | pdata->gpio_runtime_close(pdev); | ||
| 181 | rfkill_unregister(rfkill->rfkill_dev); | 150 | rfkill_unregister(rfkill->rfkill_dev); |
| 182 | rfkill_destroy(rfkill->rfkill_dev); | 151 | rfkill_destroy(rfkill->rfkill_dev); |
| 183 | 152 | ||
| 184 | return 0; | 153 | return 0; |
| 185 | } | 154 | } |
| 186 | 155 | ||
| 156 | #ifdef CONFIG_ACPI | ||
| 187 | static const struct acpi_device_id rfkill_acpi_match[] = { | 157 | static const struct acpi_device_id rfkill_acpi_match[] = { |
| 158 | { "BCM2E1A", RFKILL_TYPE_BLUETOOTH }, | ||
| 159 | { "BCM2E39", RFKILL_TYPE_BLUETOOTH }, | ||
| 160 | { "BCM2E3D", RFKILL_TYPE_BLUETOOTH }, | ||
| 188 | { "BCM4752", RFKILL_TYPE_GPS }, | 161 | { "BCM4752", RFKILL_TYPE_GPS }, |
| 162 | { "LNV4752", RFKILL_TYPE_GPS }, | ||
| 189 | { }, | 163 | { }, |
| 190 | }; | 164 | }; |
| 165 | #endif | ||
| 191 | 166 | ||
| 192 | static struct platform_driver rfkill_gpio_driver = { | 167 | static struct platform_driver rfkill_gpio_driver = { |
| 193 | .probe = rfkill_gpio_probe, | 168 | .probe = rfkill_gpio_probe, |
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index 3e02ade508d8..bdad1f951561 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c | |||
| @@ -6,8 +6,8 @@ | |||
| 6 | #include "rdev-ops.h" | 6 | #include "rdev-ops.h" |
| 7 | 7 | ||
| 8 | 8 | ||
| 9 | static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 9 | int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, |
| 10 | struct net_device *dev, bool notify) | 10 | struct net_device *dev, bool notify) |
| 11 | { | 11 | { |
| 12 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 12 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 13 | int err; | 13 | int err; |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 84d686e2dbd0..992b34070bcb 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
| @@ -370,8 +370,8 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, | |||
| 370 | case NL80211_IFTYPE_AP_VLAN: | 370 | case NL80211_IFTYPE_AP_VLAN: |
| 371 | case NL80211_IFTYPE_WDS: | 371 | case NL80211_IFTYPE_WDS: |
| 372 | case NL80211_IFTYPE_P2P_DEVICE: | 372 | case NL80211_IFTYPE_P2P_DEVICE: |
| 373 | case NL80211_IFTYPE_UNSPECIFIED: | ||
| 374 | break; | 373 | break; |
| 374 | case NL80211_IFTYPE_UNSPECIFIED: | ||
| 375 | case NUM_NL80211_IFTYPES: | 375 | case NUM_NL80211_IFTYPES: |
| 376 | WARN_ON(1); | 376 | WARN_ON(1); |
| 377 | } | 377 | } |
| @@ -796,8 +796,7 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | |||
| 796 | !cfg80211_go_permissive_chan(rdev, chandef->chan)) | 796 | !cfg80211_go_permissive_chan(rdev, chandef->chan)) |
| 797 | prohibited_flags |= IEEE80211_CHAN_NO_IR; | 797 | prohibited_flags |= IEEE80211_CHAN_NO_IR; |
| 798 | 798 | ||
| 799 | if (cfg80211_chandef_dfs_required(wiphy, chandef, | 799 | if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 && |
| 800 | NL80211_IFTYPE_UNSPECIFIED) > 0 && | ||
| 801 | cfg80211_chandef_dfs_available(wiphy, chandef)) { | 800 | cfg80211_chandef_dfs_available(wiphy, chandef)) { |
| 802 | /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */ | 801 | /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */ |
| 803 | prohibited_flags = IEEE80211_CHAN_DISABLED; | 802 | prohibited_flags = IEEE80211_CHAN_DISABLED; |
diff --git a/net/wireless/core.c b/net/wireless/core.c index b3ff3697239a..d03d8bdb29ca 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -210,15 +210,12 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | |||
| 210 | } | 210 | } |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | static int cfg80211_rfkill_set_block(void *data, bool blocked) | 213 | void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy) |
| 214 | { | 214 | { |
| 215 | struct cfg80211_registered_device *rdev = data; | 215 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
| 216 | struct wireless_dev *wdev; | 216 | struct wireless_dev *wdev; |
| 217 | 217 | ||
| 218 | if (!blocked) | 218 | ASSERT_RTNL(); |
| 219 | return 0; | ||
| 220 | |||
| 221 | rtnl_lock(); | ||
| 222 | 219 | ||
| 223 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 220 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
| 224 | if (wdev->netdev) { | 221 | if (wdev->netdev) { |
| @@ -234,7 +231,18 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | |||
| 234 | break; | 231 | break; |
| 235 | } | 232 | } |
| 236 | } | 233 | } |
| 234 | } | ||
| 235 | EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces); | ||
| 237 | 236 | ||
| 237 | static int cfg80211_rfkill_set_block(void *data, bool blocked) | ||
| 238 | { | ||
| 239 | struct cfg80211_registered_device *rdev = data; | ||
| 240 | |||
| 241 | if (!blocked) | ||
| 242 | return 0; | ||
| 243 | |||
| 244 | rtnl_lock(); | ||
| 245 | cfg80211_shutdown_all_interfaces(&rdev->wiphy); | ||
| 238 | rtnl_unlock(); | 246 | rtnl_unlock(); |
| 239 | 247 | ||
| 240 | return 0; | 248 | return 0; |
| @@ -394,6 +402,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
| 394 | rdev->wiphy.rts_threshold = (u32) -1; | 402 | rdev->wiphy.rts_threshold = (u32) -1; |
| 395 | rdev->wiphy.coverage_class = 0; | 403 | rdev->wiphy.coverage_class = 0; |
| 396 | 404 | ||
| 405 | rdev->wiphy.max_num_csa_counters = 1; | ||
| 406 | |||
| 397 | return &rdev->wiphy; | 407 | return &rdev->wiphy; |
| 398 | } | 408 | } |
| 399 | EXPORT_SYMBOL(wiphy_new); | 409 | EXPORT_SYMBOL(wiphy_new); |
| @@ -690,7 +700,7 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
| 690 | rtnl_lock(); | 700 | rtnl_lock(); |
| 691 | rdev->wiphy.registered = false; | 701 | rdev->wiphy.registered = false; |
| 692 | 702 | ||
| 693 | BUG_ON(!list_empty(&rdev->wdev_list)); | 703 | WARN_ON(!list_empty(&rdev->wdev_list)); |
| 694 | 704 | ||
| 695 | /* | 705 | /* |
| 696 | * First remove the hardware from everywhere, this makes | 706 | * First remove the hardware from everywhere, this makes |
| @@ -792,23 +802,23 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | |||
| 792 | rdev->num_running_monitor_ifaces += num; | 802 | rdev->num_running_monitor_ifaces += num; |
| 793 | } | 803 | } |
| 794 | 804 | ||
| 795 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | 805 | void __cfg80211_leave(struct cfg80211_registered_device *rdev, |
| 796 | struct wireless_dev *wdev) | 806 | struct wireless_dev *wdev) |
| 797 | { | 807 | { |
| 798 | struct net_device *dev = wdev->netdev; | 808 | struct net_device *dev = wdev->netdev; |
| 799 | 809 | ||
| 800 | ASSERT_RTNL(); | 810 | ASSERT_RTNL(); |
| 811 | ASSERT_WDEV_LOCK(wdev); | ||
| 801 | 812 | ||
| 802 | switch (wdev->iftype) { | 813 | switch (wdev->iftype) { |
| 803 | case NL80211_IFTYPE_ADHOC: | 814 | case NL80211_IFTYPE_ADHOC: |
| 804 | cfg80211_leave_ibss(rdev, dev, true); | 815 | __cfg80211_leave_ibss(rdev, dev, true); |
| 805 | break; | 816 | break; |
| 806 | case NL80211_IFTYPE_P2P_CLIENT: | 817 | case NL80211_IFTYPE_P2P_CLIENT: |
| 807 | case NL80211_IFTYPE_STATION: | 818 | case NL80211_IFTYPE_STATION: |
| 808 | if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev) | 819 | if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev) |
| 809 | __cfg80211_stop_sched_scan(rdev, false); | 820 | __cfg80211_stop_sched_scan(rdev, false); |
| 810 | 821 | ||
| 811 | wdev_lock(wdev); | ||
| 812 | #ifdef CONFIG_CFG80211_WEXT | 822 | #ifdef CONFIG_CFG80211_WEXT |
| 813 | kfree(wdev->wext.ie); | 823 | kfree(wdev->wext.ie); |
| 814 | wdev->wext.ie = NULL; | 824 | wdev->wext.ie = NULL; |
| @@ -817,20 +827,49 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
| 817 | #endif | 827 | #endif |
| 818 | cfg80211_disconnect(rdev, dev, | 828 | cfg80211_disconnect(rdev, dev, |
| 819 | WLAN_REASON_DEAUTH_LEAVING, true); | 829 | WLAN_REASON_DEAUTH_LEAVING, true); |
| 820 | wdev_unlock(wdev); | ||
| 821 | break; | 830 | break; |
| 822 | case NL80211_IFTYPE_MESH_POINT: | 831 | case NL80211_IFTYPE_MESH_POINT: |
| 823 | cfg80211_leave_mesh(rdev, dev); | 832 | __cfg80211_leave_mesh(rdev, dev); |
| 824 | break; | 833 | break; |
| 825 | case NL80211_IFTYPE_AP: | 834 | case NL80211_IFTYPE_AP: |
| 826 | case NL80211_IFTYPE_P2P_GO: | 835 | case NL80211_IFTYPE_P2P_GO: |
| 827 | cfg80211_stop_ap(rdev, dev, true); | 836 | __cfg80211_stop_ap(rdev, dev, true); |
| 828 | break; | 837 | break; |
| 829 | default: | 838 | default: |
| 830 | break; | 839 | break; |
| 831 | } | 840 | } |
| 832 | } | 841 | } |
| 833 | 842 | ||
| 843 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | ||
| 844 | struct wireless_dev *wdev) | ||
| 845 | { | ||
| 846 | wdev_lock(wdev); | ||
| 847 | __cfg80211_leave(rdev, wdev); | ||
| 848 | wdev_unlock(wdev); | ||
| 849 | } | ||
| 850 | |||
| 851 | void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, | ||
| 852 | gfp_t gfp) | ||
| 853 | { | ||
| 854 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | ||
| 855 | struct cfg80211_event *ev; | ||
| 856 | unsigned long flags; | ||
| 857 | |||
| 858 | trace_cfg80211_stop_iface(wiphy, wdev); | ||
| 859 | |||
| 860 | ev = kzalloc(sizeof(*ev), gfp); | ||
| 861 | if (!ev) | ||
| 862 | return; | ||
| 863 | |||
| 864 | ev->type = EVENT_STOPPED; | ||
| 865 | |||
| 866 | spin_lock_irqsave(&wdev->event_lock, flags); | ||
| 867 | list_add_tail(&ev->list, &wdev->event_list); | ||
| 868 | spin_unlock_irqrestore(&wdev->event_lock, flags); | ||
| 869 | queue_work(cfg80211_wq, &rdev->event_work); | ||
| 870 | } | ||
| 871 | EXPORT_SYMBOL(cfg80211_stop_iface); | ||
| 872 | |||
| 834 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | 873 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, |
| 835 | unsigned long state, void *ptr) | 874 | unsigned long state, void *ptr) |
| 836 | { | 875 | { |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 681b8fa4355b..e9afbf10e756 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
| @@ -185,6 +185,7 @@ enum cfg80211_event_type { | |||
| 185 | EVENT_ROAMED, | 185 | EVENT_ROAMED, |
| 186 | EVENT_DISCONNECTED, | 186 | EVENT_DISCONNECTED, |
| 187 | EVENT_IBSS_JOINED, | 187 | EVENT_IBSS_JOINED, |
| 188 | EVENT_STOPPED, | ||
| 188 | }; | 189 | }; |
| 189 | 190 | ||
| 190 | struct cfg80211_event { | 191 | struct cfg80211_event { |
| @@ -281,6 +282,8 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
| 281 | struct net_device *dev, | 282 | struct net_device *dev, |
| 282 | struct mesh_setup *setup, | 283 | struct mesh_setup *setup, |
| 283 | const struct mesh_config *conf); | 284 | const struct mesh_config *conf); |
| 285 | int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | ||
| 286 | struct net_device *dev); | ||
| 284 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 287 | int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
| 285 | struct net_device *dev); | 288 | struct net_device *dev); |
| 286 | int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, | 289 | int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, |
| @@ -288,6 +291,8 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, | |||
| 288 | struct cfg80211_chan_def *chandef); | 291 | struct cfg80211_chan_def *chandef); |
| 289 | 292 | ||
| 290 | /* AP */ | 293 | /* AP */ |
| 294 | int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | ||
| 295 | struct net_device *dev, bool notify); | ||
| 291 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 296 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, |
| 292 | struct net_device *dev, bool notify); | 297 | struct net_device *dev, bool notify); |
| 293 | 298 | ||
| @@ -441,6 +446,8 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | |||
| 441 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | 446 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, |
| 442 | enum nl80211_iftype iftype, int num); | 447 | enum nl80211_iftype iftype, int num); |
| 443 | 448 | ||
| 449 | void __cfg80211_leave(struct cfg80211_registered_device *rdev, | ||
| 450 | struct wireless_dev *wdev); | ||
| 444 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | 451 | void cfg80211_leave(struct cfg80211_registered_device *rdev, |
| 445 | struct wireless_dev *wdev); | 452 | struct wireless_dev *wdev); |
| 446 | 453 | ||
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 6b50588b709f..8f345da3ea5f 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
| @@ -420,8 +420,8 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev, | |||
| 420 | if (len > 0 && ssid[len - 1] == '\0') | 420 | if (len > 0 && ssid[len - 1] == '\0') |
| 421 | len--; | 421 | len--; |
| 422 | 422 | ||
| 423 | memcpy(wdev->ssid, ssid, len); | ||
| 423 | wdev->wext.ibss.ssid = wdev->ssid; | 424 | wdev->wext.ibss.ssid = wdev->ssid; |
| 424 | memcpy(wdev->wext.ibss.ssid, ssid, len); | ||
| 425 | wdev->wext.ibss.ssid_len = len; | 425 | wdev->wext.ibss.ssid_len = len; |
| 426 | 426 | ||
| 427 | wdev_lock(wdev); | 427 | wdev_lock(wdev); |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 3ddfb7cd335e..092300b30c37 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
| @@ -238,8 +238,8 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, | |||
| 238 | return 0; | 238 | return 0; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | 241 | int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, |
| 242 | struct net_device *dev) | 242 | struct net_device *dev) |
| 243 | { | 243 | { |
| 244 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 244 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 245 | int err; | 245 | int err; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0f1b18f209d6..62bdb1adaa4d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -371,8 +371,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
| 371 | [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 }, | 371 | [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 }, |
| 372 | [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG }, | 372 | [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG }, |
| 373 | [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, | 373 | [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, |
| 374 | [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, | 374 | [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_BINARY }, |
| 375 | [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 }, | 375 | [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_BINARY }, |
| 376 | [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY }, | 376 | [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY }, |
| 377 | [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY }, | 377 | [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY }, |
| 378 | [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG }, | 378 | [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG }, |
| @@ -386,6 +386,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
| 386 | [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 }, | 386 | [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 }, |
| 387 | [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 }, | 387 | [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 }, |
| 388 | [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG }, | 388 | [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG }, |
| 389 | [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY }, | ||
| 389 | }; | 390 | }; |
| 390 | 391 | ||
| 391 | /* policy for the key attributes */ | 392 | /* policy for the key attributes */ |
| @@ -970,8 +971,10 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, | |||
| 970 | c->max_interfaces)) | 971 | c->max_interfaces)) |
| 971 | goto nla_put_failure; | 972 | goto nla_put_failure; |
| 972 | if (large && | 973 | if (large && |
| 973 | nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, | 974 | (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, |
| 974 | c->radar_detect_widths)) | 975 | c->radar_detect_widths) || |
| 976 | nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, | ||
| 977 | c->radar_detect_regions))) | ||
| 975 | goto nla_put_failure; | 978 | goto nla_put_failure; |
| 976 | 979 | ||
| 977 | nla_nest_end(msg, nl_combi); | 980 | nla_nest_end(msg, nl_combi); |
| @@ -1667,6 +1670,13 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, | |||
| 1667 | } | 1670 | } |
| 1668 | nla_nest_end(msg, nested); | 1671 | nla_nest_end(msg, nested); |
| 1669 | } | 1672 | } |
| 1673 | state->split_start++; | ||
| 1674 | break; | ||
| 1675 | case 12: | ||
| 1676 | if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH && | ||
| 1677 | nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS, | ||
| 1678 | rdev->wiphy.max_num_csa_counters)) | ||
| 1679 | goto nla_put_failure; | ||
| 1670 | 1680 | ||
| 1671 | /* done */ | 1681 | /* done */ |
| 1672 | state->split_start = 0; | 1682 | state->split_start = 0; |
| @@ -3640,6 +3650,10 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | |||
| 3640 | nla_put_u32(msg, NL80211_STA_INFO_TX_FAILED, | 3650 | nla_put_u32(msg, NL80211_STA_INFO_TX_FAILED, |
| 3641 | sinfo->tx_failed)) | 3651 | sinfo->tx_failed)) |
| 3642 | goto nla_put_failure; | 3652 | goto nla_put_failure; |
| 3653 | if ((sinfo->filled & STATION_INFO_EXPECTED_THROUGHPUT) && | ||
| 3654 | nla_put_u32(msg, NL80211_STA_INFO_EXPECTED_THROUGHPUT, | ||
| 3655 | sinfo->expected_throughput)) | ||
| 3656 | goto nla_put_failure; | ||
| 3643 | if ((sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT) && | 3657 | if ((sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT) && |
| 3644 | nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS, | 3658 | nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS, |
| 3645 | sinfo->beacon_loss_count)) | 3659 | sinfo->beacon_loss_count)) |
| @@ -5820,7 +5834,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
| 5820 | return -EBUSY; | 5834 | return -EBUSY; |
| 5821 | 5835 | ||
| 5822 | err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, | 5836 | err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, |
| 5823 | NL80211_IFTYPE_UNSPECIFIED); | 5837 | wdev->iftype); |
| 5824 | if (err < 0) | 5838 | if (err < 0) |
| 5825 | return err; | 5839 | return err; |
| 5826 | 5840 | ||
| @@ -5861,6 +5875,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
| 5861 | u8 radar_detect_width = 0; | 5875 | u8 radar_detect_width = 0; |
| 5862 | int err; | 5876 | int err; |
| 5863 | bool need_new_beacon = false; | 5877 | bool need_new_beacon = false; |
| 5878 | int len, i; | ||
| 5864 | 5879 | ||
| 5865 | if (!rdev->ops->channel_switch || | 5880 | if (!rdev->ops->channel_switch || |
| 5866 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) | 5881 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) |
| @@ -5919,26 +5934,55 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
| 5919 | if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]) | 5934 | if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]) |
| 5920 | return -EINVAL; | 5935 | return -EINVAL; |
| 5921 | 5936 | ||
| 5922 | params.counter_offset_beacon = | 5937 | len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); |
| 5923 | nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); | 5938 | if (!len || (len % sizeof(u16))) |
| 5924 | if (params.counter_offset_beacon >= params.beacon_csa.tail_len) | ||
| 5925 | return -EINVAL; | 5939 | return -EINVAL; |
| 5926 | 5940 | ||
| 5927 | /* sanity check - counters should be the same */ | 5941 | params.n_counter_offsets_beacon = len / sizeof(u16); |
| 5928 | if (params.beacon_csa.tail[params.counter_offset_beacon] != | 5942 | if (rdev->wiphy.max_num_csa_counters && |
| 5929 | params.count) | 5943 | (params.n_counter_offsets_beacon > |
| 5944 | rdev->wiphy.max_num_csa_counters)) | ||
| 5930 | return -EINVAL; | 5945 | return -EINVAL; |
| 5931 | 5946 | ||
| 5947 | params.counter_offsets_beacon = | ||
| 5948 | nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); | ||
| 5949 | |||
| 5950 | /* sanity checks - counters should fit and be the same */ | ||
| 5951 | for (i = 0; i < params.n_counter_offsets_beacon; i++) { | ||
| 5952 | u16 offset = params.counter_offsets_beacon[i]; | ||
| 5953 | |||
| 5954 | if (offset >= params.beacon_csa.tail_len) | ||
| 5955 | return -EINVAL; | ||
| 5956 | |||
| 5957 | if (params.beacon_csa.tail[offset] != params.count) | ||
| 5958 | return -EINVAL; | ||
| 5959 | } | ||
| 5960 | |||
| 5932 | if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) { | 5961 | if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) { |
| 5933 | params.counter_offset_presp = | 5962 | len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); |
| 5934 | nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); | 5963 | if (!len || (len % sizeof(u16))) |
| 5935 | if (params.counter_offset_presp >= | ||
| 5936 | params.beacon_csa.probe_resp_len) | ||
| 5937 | return -EINVAL; | 5964 | return -EINVAL; |
| 5938 | 5965 | ||
| 5939 | if (params.beacon_csa.probe_resp[params.counter_offset_presp] != | 5966 | params.n_counter_offsets_presp = len / sizeof(u16); |
| 5940 | params.count) | 5967 | if (rdev->wiphy.max_num_csa_counters && |
| 5968 | (params.n_counter_offsets_beacon > | ||
| 5969 | rdev->wiphy.max_num_csa_counters)) | ||
| 5941 | return -EINVAL; | 5970 | return -EINVAL; |
| 5971 | |||
| 5972 | params.counter_offsets_presp = | ||
| 5973 | nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); | ||
| 5974 | |||
| 5975 | /* sanity checks - counters should fit and be the same */ | ||
| 5976 | for (i = 0; i < params.n_counter_offsets_presp; i++) { | ||
| 5977 | u16 offset = params.counter_offsets_presp[i]; | ||
| 5978 | |||
| 5979 | if (offset >= params.beacon_csa.probe_resp_len) | ||
| 5980 | return -EINVAL; | ||
| 5981 | |||
| 5982 | if (params.beacon_csa.probe_resp[offset] != | ||
| 5983 | params.count) | ||
| 5984 | return -EINVAL; | ||
| 5985 | } | ||
| 5942 | } | 5986 | } |
| 5943 | 5987 | ||
| 5944 | skip_beacons: | 5988 | skip_beacons: |
| @@ -7784,6 +7828,27 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
| 7784 | if (!chandef.chan && params.offchan) | 7828 | if (!chandef.chan && params.offchan) |
| 7785 | return -EINVAL; | 7829 | return -EINVAL; |
| 7786 | 7830 | ||
| 7831 | params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); | ||
| 7832 | params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); | ||
| 7833 | |||
| 7834 | if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) { | ||
| 7835 | int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]); | ||
| 7836 | int i; | ||
| 7837 | |||
| 7838 | if (len % sizeof(u16)) | ||
| 7839 | return -EINVAL; | ||
| 7840 | |||
| 7841 | params.n_csa_offsets = len / sizeof(u16); | ||
| 7842 | params.csa_offsets = | ||
| 7843 | nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]); | ||
| 7844 | |||
| 7845 | /* check that all the offsets fit the frame */ | ||
| 7846 | for (i = 0; i < params.n_csa_offsets; i++) { | ||
| 7847 | if (params.csa_offsets[i] >= params.len) | ||
| 7848 | return -EINVAL; | ||
| 7849 | } | ||
| 7850 | } | ||
| 7851 | |||
| 7787 | if (!params.dont_wait_for_ack) { | 7852 | if (!params.dont_wait_for_ack) { |
| 7788 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 7853 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
| 7789 | if (!msg) | 7854 | if (!msg) |
| @@ -7797,8 +7862,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
| 7797 | } | 7862 | } |
| 7798 | } | 7863 | } |
| 7799 | 7864 | ||
| 7800 | params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); | ||
| 7801 | params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); | ||
| 7802 | params.chan = chandef.chan; | 7865 | params.chan = chandef.chan; |
| 7803 | err = cfg80211_mlme_mgmt_tx(rdev, wdev, ¶ms, &cookie); | 7866 | err = cfg80211_mlme_mgmt_tx(rdev, wdev, ¶ms, &cookie); |
| 7804 | if (err) | 7867 | if (err) |
| @@ -8495,6 +8558,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
| 8495 | 8558 | ||
| 8496 | nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], | 8559 | nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], |
| 8497 | rem) { | 8560 | rem) { |
| 8561 | u8 *mask_pat; | ||
| 8562 | |||
| 8498 | nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), | 8563 | nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), |
| 8499 | nla_len(pat), NULL); | 8564 | nla_len(pat), NULL); |
| 8500 | err = -EINVAL; | 8565 | err = -EINVAL; |
| @@ -8518,19 +8583,18 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
| 8518 | goto error; | 8583 | goto error; |
| 8519 | new_triggers.patterns[i].pkt_offset = pkt_offset; | 8584 | new_triggers.patterns[i].pkt_offset = pkt_offset; |
| 8520 | 8585 | ||
| 8521 | new_triggers.patterns[i].mask = | 8586 | mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL); |
| 8522 | kmalloc(mask_len + pat_len, GFP_KERNEL); | 8587 | if (!mask_pat) { |
| 8523 | if (!new_triggers.patterns[i].mask) { | ||
| 8524 | err = -ENOMEM; | 8588 | err = -ENOMEM; |
| 8525 | goto error; | 8589 | goto error; |
| 8526 | } | 8590 | } |
| 8527 | new_triggers.patterns[i].pattern = | 8591 | new_triggers.patterns[i].mask = mask_pat; |
| 8528 | new_triggers.patterns[i].mask + mask_len; | 8592 | memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]), |
| 8529 | memcpy(new_triggers.patterns[i].mask, | ||
| 8530 | nla_data(pat_tb[NL80211_PKTPAT_MASK]), | ||
| 8531 | mask_len); | 8593 | mask_len); |
| 8594 | mask_pat += mask_len; | ||
| 8595 | new_triggers.patterns[i].pattern = mask_pat; | ||
| 8532 | new_triggers.patterns[i].pattern_len = pat_len; | 8596 | new_triggers.patterns[i].pattern_len = pat_len; |
| 8533 | memcpy(new_triggers.patterns[i].pattern, | 8597 | memcpy(mask_pat, |
| 8534 | nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), | 8598 | nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), |
| 8535 | pat_len); | 8599 | pat_len); |
| 8536 | i++; | 8600 | i++; |
| @@ -8722,6 +8786,8 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev, | |||
| 8722 | 8786 | ||
| 8723 | nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN], | 8787 | nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN], |
| 8724 | rem) { | 8788 | rem) { |
| 8789 | u8 *mask_pat; | ||
| 8790 | |||
| 8725 | nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), | 8791 | nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), |
| 8726 | nla_len(pat), NULL); | 8792 | nla_len(pat), NULL); |
| 8727 | if (!pat_tb[NL80211_PKTPAT_MASK] || | 8793 | if (!pat_tb[NL80211_PKTPAT_MASK] || |
| @@ -8743,17 +8809,19 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev, | |||
| 8743 | return -EINVAL; | 8809 | return -EINVAL; |
| 8744 | new_rule->patterns[i].pkt_offset = pkt_offset; | 8810 | new_rule->patterns[i].pkt_offset = pkt_offset; |
| 8745 | 8811 | ||
| 8746 | new_rule->patterns[i].mask = | 8812 | mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL); |
| 8747 | kmalloc(mask_len + pat_len, GFP_KERNEL); | 8813 | if (!mask_pat) |
| 8748 | if (!new_rule->patterns[i].mask) | ||
| 8749 | return -ENOMEM; | 8814 | return -ENOMEM; |
| 8750 | new_rule->patterns[i].pattern = | 8815 | |
| 8751 | new_rule->patterns[i].mask + mask_len; | 8816 | new_rule->patterns[i].mask = mask_pat; |
| 8752 | memcpy(new_rule->patterns[i].mask, | 8817 | memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]), |
| 8753 | nla_data(pat_tb[NL80211_PKTPAT_MASK]), mask_len); | 8818 | mask_len); |
| 8819 | |||
| 8820 | mask_pat += mask_len; | ||
| 8821 | new_rule->patterns[i].pattern = mask_pat; | ||
| 8754 | new_rule->patterns[i].pattern_len = pat_len; | 8822 | new_rule->patterns[i].pattern_len = pat_len; |
| 8755 | memcpy(new_rule->patterns[i].pattern, | 8823 | memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), |
| 8756 | nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), pat_len); | 8824 | pat_len); |
| 8757 | i++; | 8825 | i++; |
| 8758 | } | 8826 | } |
| 8759 | 8827 | ||
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 00cdf73ba6c4..d95bbe348138 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
| @@ -199,7 +199,7 @@ static inline int rdev_change_station(struct cfg80211_registered_device *rdev, | |||
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | static inline int rdev_get_station(struct cfg80211_registered_device *rdev, | 201 | static inline int rdev_get_station(struct cfg80211_registered_device *rdev, |
| 202 | struct net_device *dev, u8 *mac, | 202 | struct net_device *dev, const u8 *mac, |
| 203 | struct station_info *sinfo) | 203 | struct station_info *sinfo) |
| 204 | { | 204 | { |
| 205 | int ret; | 205 | int ret; |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index e78f532aaa5b..558b0e3a02d8 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -1876,7 +1876,8 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
| 1876 | case NL80211_REGDOM_SET_BY_USER: | 1876 | case NL80211_REGDOM_SET_BY_USER: |
| 1877 | treatment = reg_process_hint_user(reg_request); | 1877 | treatment = reg_process_hint_user(reg_request); |
| 1878 | if (treatment == REG_REQ_IGNORE || | 1878 | if (treatment == REG_REQ_IGNORE || |
| 1879 | treatment == REG_REQ_ALREADY_SET) | 1879 | treatment == REG_REQ_ALREADY_SET || |
| 1880 | treatment == REG_REQ_USER_HINT_HANDLED) | ||
| 1880 | return; | 1881 | return; |
| 1881 | queue_delayed_work(system_power_efficient_wq, | 1882 | queue_delayed_work(system_power_efficient_wq, |
| 1882 | ®_timeout, msecs_to_jiffies(3142)); | 1883 | ®_timeout, msecs_to_jiffies(3142)); |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e7329bb6a323..0798c62e6085 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
| @@ -891,6 +891,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
| 891 | struct cfg80211_bss_ies *ies; | 891 | struct cfg80211_bss_ies *ies; |
| 892 | struct ieee80211_channel *channel; | 892 | struct ieee80211_channel *channel; |
| 893 | struct cfg80211_internal_bss tmp = {}, *res; | 893 | struct cfg80211_internal_bss tmp = {}, *res; |
| 894 | bool signal_valid; | ||
| 894 | 895 | ||
| 895 | if (WARN_ON(!wiphy)) | 896 | if (WARN_ON(!wiphy)) |
| 896 | return NULL; | 897 | return NULL; |
| @@ -927,8 +928,9 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
| 927 | rcu_assign_pointer(tmp.pub.beacon_ies, ies); | 928 | rcu_assign_pointer(tmp.pub.beacon_ies, ies); |
| 928 | rcu_assign_pointer(tmp.pub.ies, ies); | 929 | rcu_assign_pointer(tmp.pub.ies, ies); |
| 929 | 930 | ||
| 930 | res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, | 931 | signal_valid = abs(rx_channel->center_freq - channel->center_freq) <= |
| 931 | rx_channel == channel); | 932 | wiphy->max_adj_channel_rssi_comp; |
| 933 | res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid); | ||
| 932 | if (!res) | 934 | if (!res) |
| 933 | return NULL; | 935 | return NULL; |
| 934 | 936 | ||
| @@ -952,6 +954,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
| 952 | struct cfg80211_internal_bss tmp = {}, *res; | 954 | struct cfg80211_internal_bss tmp = {}, *res; |
| 953 | struct cfg80211_bss_ies *ies; | 955 | struct cfg80211_bss_ies *ies; |
| 954 | struct ieee80211_channel *channel; | 956 | struct ieee80211_channel *channel; |
| 957 | bool signal_valid; | ||
| 955 | size_t ielen = len - offsetof(struct ieee80211_mgmt, | 958 | size_t ielen = len - offsetof(struct ieee80211_mgmt, |
| 956 | u.probe_resp.variable); | 959 | u.probe_resp.variable); |
| 957 | 960 | ||
| @@ -999,8 +1002,9 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
| 999 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); | 1002 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); |
| 1000 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); | 1003 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); |
| 1001 | 1004 | ||
| 1002 | res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, | 1005 | signal_valid = abs(rx_channel->center_freq - channel->center_freq) <= |
| 1003 | rx_channel == channel); | 1006 | wiphy->max_adj_channel_rssi_comp; |
| 1007 | res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid); | ||
| 1004 | if (!res) | 1008 | if (!res) |
| 1005 | return NULL; | 1009 | return NULL; |
| 1006 | 1010 | ||
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 0c0844b585d1..8bbeeb302216 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
| @@ -149,7 +149,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
| 149 | case CFG80211_CONN_SCAN_AGAIN: | 149 | case CFG80211_CONN_SCAN_AGAIN: |
| 150 | return cfg80211_conn_scan(wdev); | 150 | return cfg80211_conn_scan(wdev); |
| 151 | case CFG80211_CONN_AUTHENTICATE_NEXT: | 151 | case CFG80211_CONN_AUTHENTICATE_NEXT: |
| 152 | BUG_ON(!rdev->ops->auth); | 152 | if (WARN_ON(!rdev->ops->auth)) |
| 153 | return -EOPNOTSUPP; | ||
| 153 | wdev->conn->state = CFG80211_CONN_AUTHENTICATING; | 154 | wdev->conn->state = CFG80211_CONN_AUTHENTICATING; |
| 154 | return cfg80211_mlme_auth(rdev, wdev->netdev, | 155 | return cfg80211_mlme_auth(rdev, wdev->netdev, |
| 155 | params->channel, params->auth_type, | 156 | params->channel, params->auth_type, |
| @@ -161,7 +162,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
| 161 | case CFG80211_CONN_AUTH_FAILED: | 162 | case CFG80211_CONN_AUTH_FAILED: |
| 162 | return -ENOTCONN; | 163 | return -ENOTCONN; |
| 163 | case CFG80211_CONN_ASSOCIATE_NEXT: | 164 | case CFG80211_CONN_ASSOCIATE_NEXT: |
| 164 | BUG_ON(!rdev->ops->assoc); | 165 | if (WARN_ON(!rdev->ops->assoc)) |
| 166 | return -EOPNOTSUPP; | ||
| 165 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; | 167 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; |
| 166 | if (wdev->conn->prev_bssid_valid) | 168 | if (wdev->conn->prev_bssid_valid) |
| 167 | req.prev_bssid = wdev->conn->prev_bssid; | 169 | req.prev_bssid = wdev->conn->prev_bssid; |
| @@ -877,7 +879,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
| 877 | } | 879 | } |
| 878 | 880 | ||
| 879 | void cfg80211_disconnected(struct net_device *dev, u16 reason, | 881 | void cfg80211_disconnected(struct net_device *dev, u16 reason, |
| 880 | u8 *ie, size_t ie_len, gfp_t gfp) | 882 | const u8 *ie, size_t ie_len, gfp_t gfp) |
| 881 | { | 883 | { |
| 882 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 884 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 883 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | 885 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index f3c13ff4d04c..560ed77084e9 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
| @@ -1876,29 +1876,33 @@ TRACE_EVENT(rdev_channel_switch, | |||
| 1876 | WIPHY_ENTRY | 1876 | WIPHY_ENTRY |
| 1877 | NETDEV_ENTRY | 1877 | NETDEV_ENTRY |
| 1878 | CHAN_DEF_ENTRY | 1878 | CHAN_DEF_ENTRY |
| 1879 | __field(u16, counter_offset_beacon) | ||
| 1880 | __field(u16, counter_offset_presp) | ||
| 1881 | __field(bool, radar_required) | 1879 | __field(bool, radar_required) |
| 1882 | __field(bool, block_tx) | 1880 | __field(bool, block_tx) |
| 1883 | __field(u8, count) | 1881 | __field(u8, count) |
| 1882 | __dynamic_array(u16, bcn_ofs, params->n_counter_offsets_beacon) | ||
| 1883 | __dynamic_array(u16, pres_ofs, params->n_counter_offsets_presp) | ||
| 1884 | ), | 1884 | ), |
| 1885 | TP_fast_assign( | 1885 | TP_fast_assign( |
| 1886 | WIPHY_ASSIGN; | 1886 | WIPHY_ASSIGN; |
| 1887 | NETDEV_ASSIGN; | 1887 | NETDEV_ASSIGN; |
| 1888 | CHAN_DEF_ASSIGN(¶ms->chandef); | 1888 | CHAN_DEF_ASSIGN(¶ms->chandef); |
| 1889 | __entry->counter_offset_beacon = params->counter_offset_beacon; | ||
| 1890 | __entry->counter_offset_presp = params->counter_offset_presp; | ||
| 1891 | __entry->radar_required = params->radar_required; | 1889 | __entry->radar_required = params->radar_required; |
| 1892 | __entry->block_tx = params->block_tx; | 1890 | __entry->block_tx = params->block_tx; |
| 1893 | __entry->count = params->count; | 1891 | __entry->count = params->count; |
| 1892 | memcpy(__get_dynamic_array(bcn_ofs), | ||
| 1893 | params->counter_offsets_beacon, | ||
| 1894 | params->n_counter_offsets_beacon * sizeof(u16)); | ||
| 1895 | |||
| 1896 | /* probe response offsets are optional */ | ||
| 1897 | if (params->n_counter_offsets_presp) | ||
| 1898 | memcpy(__get_dynamic_array(pres_ofs), | ||
| 1899 | params->counter_offsets_presp, | ||
| 1900 | params->n_counter_offsets_presp * sizeof(u16)); | ||
| 1894 | ), | 1901 | ), |
| 1895 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT | 1902 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT |
| 1896 | ", block_tx: %d, count: %u, radar_required: %d" | 1903 | ", block_tx: %d, count: %u, radar_required: %d", |
| 1897 | ", counter offsets (beacon/presp): %u/%u", | ||
| 1898 | WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG, | 1904 | WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG, |
| 1899 | __entry->block_tx, __entry->count, __entry->radar_required, | 1905 | __entry->block_tx, __entry->count, __entry->radar_required) |
| 1900 | __entry->counter_offset_beacon, | ||
| 1901 | __entry->counter_offset_presp) | ||
| 1902 | ); | 1906 | ); |
| 1903 | 1907 | ||
| 1904 | TRACE_EVENT(rdev_set_qos_map, | 1908 | TRACE_EVENT(rdev_set_qos_map, |
| @@ -2636,6 +2640,21 @@ TRACE_EVENT(cfg80211_ft_event, | |||
| 2636 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap)) | 2640 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap)) |
| 2637 | ); | 2641 | ); |
| 2638 | 2642 | ||
| 2643 | TRACE_EVENT(cfg80211_stop_iface, | ||
| 2644 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), | ||
| 2645 | TP_ARGS(wiphy, wdev), | ||
| 2646 | TP_STRUCT__entry( | ||
| 2647 | WIPHY_ENTRY | ||
| 2648 | WDEV_ENTRY | ||
| 2649 | ), | ||
| 2650 | TP_fast_assign( | ||
| 2651 | WIPHY_ASSIGN; | ||
| 2652 | WDEV_ASSIGN; | ||
| 2653 | ), | ||
| 2654 | TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, | ||
| 2655 | WIPHY_PR_ARG, WDEV_PR_ARG) | ||
| 2656 | ); | ||
| 2657 | |||
| 2639 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ | 2658 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ |
| 2640 | 2659 | ||
| 2641 | #undef TRACE_INCLUDE_PATH | 2660 | #undef TRACE_INCLUDE_PATH |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 7c47fa07b276..728f1c0dc70d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
| @@ -476,7 +476,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
| 476 | EXPORT_SYMBOL(ieee80211_data_to_8023); | 476 | EXPORT_SYMBOL(ieee80211_data_to_8023); |
| 477 | 477 | ||
| 478 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, | 478 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, |
| 479 | enum nl80211_iftype iftype, u8 *bssid, bool qos) | 479 | enum nl80211_iftype iftype, |
| 480 | const u8 *bssid, bool qos) | ||
| 480 | { | 481 | { |
| 481 | struct ieee80211_hdr hdr; | 482 | struct ieee80211_hdr hdr; |
| 482 | u16 hdrlen, ethertype; | 483 | u16 hdrlen, ethertype; |
| @@ -839,6 +840,9 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) | |||
| 839 | __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, | 840 | __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, |
| 840 | ev->ij.channel); | 841 | ev->ij.channel); |
| 841 | break; | 842 | break; |
| 843 | case EVENT_STOPPED: | ||
| 844 | __cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev); | ||
| 845 | break; | ||
| 842 | } | 846 | } |
| 843 | wdev_unlock(wdev); | 847 | wdev_unlock(wdev); |
| 844 | 848 | ||
| @@ -1271,10 +1275,20 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, | |||
| 1271 | void *data), | 1275 | void *data), |
| 1272 | void *data) | 1276 | void *data) |
| 1273 | { | 1277 | { |
| 1278 | const struct ieee80211_regdomain *regdom; | ||
| 1279 | enum nl80211_dfs_regions region = 0; | ||
| 1274 | int i, j, iftype; | 1280 | int i, j, iftype; |
| 1275 | int num_interfaces = 0; | 1281 | int num_interfaces = 0; |
| 1276 | u32 used_iftypes = 0; | 1282 | u32 used_iftypes = 0; |
| 1277 | 1283 | ||
| 1284 | if (radar_detect) { | ||
| 1285 | rcu_read_lock(); | ||
| 1286 | regdom = rcu_dereference(cfg80211_regdomain); | ||
| 1287 | if (regdom) | ||
| 1288 | region = regdom->dfs_region; | ||
| 1289 | rcu_read_unlock(); | ||
| 1290 | } | ||
| 1291 | |||
| 1278 | for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { | 1292 | for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { |
| 1279 | num_interfaces += iftype_num[iftype]; | 1293 | num_interfaces += iftype_num[iftype]; |
| 1280 | if (iftype_num[iftype] > 0 && | 1294 | if (iftype_num[iftype] > 0 && |
| @@ -1315,6 +1329,10 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, | |||
| 1315 | if (radar_detect != (c->radar_detect_widths & radar_detect)) | 1329 | if (radar_detect != (c->radar_detect_widths & radar_detect)) |
| 1316 | goto cont; | 1330 | goto cont; |
| 1317 | 1331 | ||
| 1332 | if (radar_detect && c->radar_detect_regions && | ||
| 1333 | !(c->radar_detect_regions & BIT(region))) | ||
| 1334 | goto cont; | ||
| 1335 | |||
| 1318 | /* Finally check that all iftypes that we're currently | 1336 | /* Finally check that all iftypes that we're currently |
| 1319 | * using are actually part of this combination. If they | 1337 | * using are actually part of this combination. If they |
| 1320 | * aren't then we can't use this combination and have | 1338 | * aren't then we can't use this combination and have |
| @@ -1528,6 +1546,24 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy) | |||
| 1528 | } | 1546 | } |
| 1529 | EXPORT_SYMBOL(ieee80211_get_num_supported_channels); | 1547 | EXPORT_SYMBOL(ieee80211_get_num_supported_channels); |
| 1530 | 1548 | ||
| 1549 | int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr, | ||
| 1550 | struct station_info *sinfo) | ||
| 1551 | { | ||
| 1552 | struct cfg80211_registered_device *rdev; | ||
| 1553 | struct wireless_dev *wdev; | ||
| 1554 | |||
| 1555 | wdev = dev->ieee80211_ptr; | ||
| 1556 | if (!wdev) | ||
| 1557 | return -EOPNOTSUPP; | ||
| 1558 | |||
| 1559 | rdev = wiphy_to_rdev(wdev->wiphy); | ||
| 1560 | if (!rdev->ops->get_station) | ||
| 1561 | return -EOPNOTSUPP; | ||
| 1562 | |||
| 1563 | return rdev_get_station(rdev, dev, mac_addr, sinfo); | ||
| 1564 | } | ||
| 1565 | EXPORT_SYMBOL(cfg80211_get_station); | ||
| 1566 | |||
| 1531 | /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ | 1567 | /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ |
| 1532 | /* Ethernet-II snap header (RFC1042 for most EtherTypes) */ | 1568 | /* Ethernet-II snap header (RFC1042 for most EtherTypes) */ |
| 1533 | const unsigned char rfc1042_header[] __aligned(2) = | 1569 | const unsigned char rfc1042_header[] __aligned(2) = |
