diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-01-28 14:43:00 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-01-28 14:43:00 -0500 |
commit | 4205e6ef4ee747aa81930537b6035086ba5f1e28 (patch) | |
tree | b2ebe2b4621f5f531f283cb9bf0005cd3c04ca7b | |
parent | cef401de7be8c4e155c6746bfccf721a4fa5fab9 (diff) | |
parent | 9ebea3829fac7505e0cd2642fbd13cfa9c038831 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
210 files changed, 7702 insertions, 4987 deletions
diff --git a/Documentation/nfc/nfc-hci.txt b/Documentation/nfc/nfc-hci.txt index 89a339c9b079..0686c9e211c2 100644 --- a/Documentation/nfc/nfc-hci.txt +++ b/Documentation/nfc/nfc-hci.txt | |||
@@ -17,10 +17,12 @@ HCI | |||
17 | HCI registers as an nfc device with NFC Core. Requests coming from userspace are | 17 | HCI registers as an nfc device with NFC Core. Requests coming from userspace are |
18 | routed through netlink sockets to NFC Core and then to HCI. From this point, | 18 | routed through netlink sockets to NFC Core and then to HCI. From this point, |
19 | they are translated in a sequence of HCI commands sent to the HCI layer in the | 19 | they are translated in a sequence of HCI commands sent to the HCI layer in the |
20 | host controller (the chip). The sending context blocks while waiting for the | 20 | host controller (the chip). Commands can be executed synchronously (the sending |
21 | response to arrive. | 21 | context blocks waiting for response) or asynchronously (the response is returned |
22 | from HCI Rx context). | ||
22 | HCI events can also be received from the host controller. They will be handled | 23 | HCI events can also be received from the host controller. They will be handled |
23 | and a translation will be forwarded to NFC Core as needed. | 24 | and a translation will be forwarded to NFC Core as needed. There are hooks to |
25 | let the HCI driver handle proprietary events or override standard behavior. | ||
24 | HCI uses 2 execution contexts: | 26 | HCI uses 2 execution contexts: |
25 | - one for executing commands : nfc_hci_msg_tx_work(). Only one command | 27 | - one for executing commands : nfc_hci_msg_tx_work(). Only one command |
26 | can be executing at any given moment. | 28 | can be executing at any given moment. |
@@ -33,6 +35,8 @@ The Session initialization is an HCI standard which must unfortunately | |||
33 | support proprietary gates. This is the reason why the driver will pass a list | 35 | support proprietary gates. This is the reason why the driver will pass a list |
34 | of proprietary gates that must be part of the session. HCI will ensure all | 36 | of proprietary gates that must be part of the session. HCI will ensure all |
35 | those gates have pipes connected when the hci device is set up. | 37 | those gates have pipes connected when the hci device is set up. |
38 | In case the chip supports pre-opened gates and pseudo-static pipes, the driver | ||
39 | can pass that information to HCI core. | ||
36 | 40 | ||
37 | HCI Gates and Pipes | 41 | HCI Gates and Pipes |
38 | ------------------- | 42 | ------------------- |
@@ -46,6 +50,13 @@ without knowing the pipe connected to it. | |||
46 | Driver interface | 50 | Driver interface |
47 | ---------------- | 51 | ---------------- |
48 | 52 | ||
53 | A driver is generally written in two parts : the physical link management and | ||
54 | the HCI management. This makes it easier to maintain a driver for a chip that | ||
55 | can be connected using various phy (i2c, spi, ...) | ||
56 | |||
57 | HCI Management | ||
58 | -------------- | ||
59 | |||
49 | A driver would normally register itself with HCI and provide the following | 60 | A driver would normally register itself with HCI and provide the following |
50 | entry points: | 61 | entry points: |
51 | 62 | ||
@@ -53,58 +64,113 @@ struct nfc_hci_ops { | |||
53 | int (*open)(struct nfc_hci_dev *hdev); | 64 | int (*open)(struct nfc_hci_dev *hdev); |
54 | void (*close)(struct nfc_hci_dev *hdev); | 65 | void (*close)(struct nfc_hci_dev *hdev); |
55 | int (*hci_ready) (struct nfc_hci_dev *hdev); | 66 | int (*hci_ready) (struct nfc_hci_dev *hdev); |
56 | int (*xmit)(struct nfc_hci_dev *hdev, struct sk_buff *skb); | 67 | int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); |
57 | int (*start_poll)(struct nfc_hci_dev *hdev, u32 protocols); | 68 | int (*start_poll) (struct nfc_hci_dev *hdev, |
58 | int (*target_from_gate)(struct nfc_hci_dev *hdev, u8 gate, | 69 | u32 im_protocols, u32 tm_protocols); |
59 | struct nfc_target *target); | 70 | int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target, |
71 | u8 comm_mode, u8 *gb, size_t gb_len); | ||
72 | int (*dep_link_down)(struct nfc_hci_dev *hdev); | ||
73 | int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, | ||
74 | struct nfc_target *target); | ||
60 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, | 75 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, |
61 | struct nfc_target *target); | 76 | struct nfc_target *target); |
62 | int (*data_exchange) (struct nfc_hci_dev *hdev, | 77 | int (*im_transceive) (struct nfc_hci_dev *hdev, |
63 | struct nfc_target *target, | 78 | struct nfc_target *target, struct sk_buff *skb, |
64 | struct sk_buff *skb, struct sk_buff **res_skb); | 79 | data_exchange_cb_t cb, void *cb_context); |
80 | int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb); | ||
65 | int (*check_presence)(struct nfc_hci_dev *hdev, | 81 | int (*check_presence)(struct nfc_hci_dev *hdev, |
66 | struct nfc_target *target); | 82 | struct nfc_target *target); |
83 | int (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, | ||
84 | struct sk_buff *skb); | ||
67 | }; | 85 | }; |
68 | 86 | ||
69 | - open() and close() shall turn the hardware on and off. | 87 | - open() and close() shall turn the hardware on and off. |
70 | - hci_ready() is an optional entry point that is called right after the hci | 88 | - hci_ready() is an optional entry point that is called right after the hci |
71 | session has been set up. The driver can use it to do additional initialization | 89 | session has been set up. The driver can use it to do additional initialization |
72 | that must be performed using HCI commands. | 90 | that must be performed using HCI commands. |
73 | - xmit() shall simply write a frame to the chip. | 91 | - xmit() shall simply write a frame to the physical link. |
74 | - start_poll() is an optional entrypoint that shall set the hardware in polling | 92 | - start_poll() is an optional entrypoint that shall set the hardware in polling |
75 | mode. This must be implemented only if the hardware uses proprietary gates or a | 93 | mode. This must be implemented only if the hardware uses proprietary gates or a |
76 | mechanism slightly different from the HCI standard. | 94 | mechanism slightly different from the HCI standard. |
95 | - dep_link_up() is called after a p2p target has been detected, to finish | ||
96 | the p2p connection setup with hardware parameters that need to be passed back | ||
97 | to nfc core. | ||
98 | - dep_link_down() is called to bring the p2p link down. | ||
77 | - target_from_gate() is an optional entrypoint to return the nfc protocols | 99 | - target_from_gate() is an optional entrypoint to return the nfc protocols |
78 | corresponding to a proprietary gate. | 100 | corresponding to a proprietary gate. |
79 | - complete_target_discovered() is an optional entry point to let the driver | 101 | - complete_target_discovered() is an optional entry point to let the driver |
80 | perform additional proprietary processing necessary to auto activate the | 102 | perform additional proprietary processing necessary to auto activate the |
81 | discovered target. | 103 | discovered target. |
82 | - data_exchange() must be implemented by the driver if proprietary HCI commands | 104 | - im_transceive() must be implemented by the driver if proprietary HCI commands |
83 | are required to send data to the tag. Some tag types will require custom | 105 | are required to send data to the tag. Some tag types will require custom |
84 | commands, others can be written to using the standard HCI commands. The driver | 106 | commands, others can be written to using the standard HCI commands. The driver |
85 | can check the tag type and either do proprietary processing, or return 1 to ask | 107 | can check the tag type and either do proprietary processing, or return 1 to ask |
86 | for standard processing. | 108 | for standard processing. The data exchange command itself must be sent |
109 | asynchronously. | ||
110 | - tm_send() is called to send data in the case of a p2p connection | ||
87 | - check_presence() is an optional entry point that will be called regularly | 111 | - check_presence() is an optional entry point that will be called regularly |
88 | by the core to check that an activated tag is still in the field. If this is | 112 | by the core to check that an activated tag is still in the field. If this is |
89 | not implemented, the core will not be able to push tag_lost events to the user | 113 | not implemented, the core will not be able to push tag_lost events to the user |
90 | space | 114 | space |
115 | - event_received() is called to handle an event coming from the chip. Driver | ||
116 | can handle the event or return 1 to let HCI attempt standard processing. | ||
91 | 117 | ||
92 | On the rx path, the driver is responsible to push incoming HCP frames to HCI | 118 | On the rx path, the driver is responsible to push incoming HCP frames to HCI |
93 | using nfc_hci_recv_frame(). HCI will take care of re-aggregation and handling | 119 | using nfc_hci_recv_frame(). HCI will take care of re-aggregation and handling |
94 | This must be done from a context that can sleep. | 120 | This must be done from a context that can sleep. |
95 | 121 | ||
96 | SHDLC | 122 | PHY Management |
97 | ----- | 123 | -------------- |
124 | |||
125 | The physical link (i2c, ...) management is defined by the following struture: | ||
126 | |||
127 | struct nfc_phy_ops { | ||
128 | int (*write)(void *dev_id, struct sk_buff *skb); | ||
129 | int (*enable)(void *dev_id); | ||
130 | void (*disable)(void *dev_id); | ||
131 | }; | ||
132 | |||
133 | enable(): turn the phy on (power on), make it ready to transfer data | ||
134 | disable(): turn the phy off | ||
135 | write(): Send a data frame to the chip. Note that to enable higher | ||
136 | layers such as an llc to store the frame for re-emission, this function must | ||
137 | not alter the skb. It must also not return a positive result (return 0 for | ||
138 | success, negative for failure). | ||
139 | |||
140 | Data coming from the chip shall be sent directly to nfc_hci_recv_frame(). | ||
141 | |||
142 | LLC | ||
143 | --- | ||
144 | |||
145 | Communication between the CPU and the chip often requires some link layer | ||
146 | protocol. Those are isolated as modules managed by the HCI layer. There are | ||
147 | currently two modules : nop (raw transfert) and shdlc. | ||
148 | A new llc must implement the following functions: | ||
149 | |||
150 | struct nfc_llc_ops { | ||
151 | void *(*init) (struct nfc_hci_dev *hdev, xmit_to_drv_t xmit_to_drv, | ||
152 | rcv_to_hci_t rcv_to_hci, int tx_headroom, | ||
153 | int tx_tailroom, int *rx_headroom, int *rx_tailroom, | ||
154 | llc_failure_t llc_failure); | ||
155 | void (*deinit) (struct nfc_llc *llc); | ||
156 | int (*start) (struct nfc_llc *llc); | ||
157 | int (*stop) (struct nfc_llc *llc); | ||
158 | void (*rcv_from_drv) (struct nfc_llc *llc, struct sk_buff *skb); | ||
159 | int (*xmit_from_hci) (struct nfc_llc *llc, struct sk_buff *skb); | ||
160 | }; | ||
161 | |||
162 | - init() : allocate and init your private storage | ||
163 | - deinit() : cleanup | ||
164 | - start() : establish the logical connection | ||
165 | - stop () : terminate the logical connection | ||
166 | - rcv_from_drv() : handle data coming from the chip, going to HCI | ||
167 | - xmit_from_hci() : handle data sent by HCI, going to the chip | ||
98 | 168 | ||
99 | Most chips use shdlc to ensure integrity and delivery ordering of the HCP | 169 | The llc must be registered with nfc before it can be used. Do that by |
100 | frames between the host controller (the chip) and hosts (entities connected | 170 | calling nfc_llc_register(const char *name, struct nfc_llc_ops *ops); |
101 | to the chip, like the cpu). In order to simplify writing the driver, an shdlc | 171 | |
102 | layer is available for use by the driver. | 172 | Again, note that the llc does not handle the physical link. It is thus very |
103 | When used, the driver actually registers with shdlc, and shdlc will register | 173 | easy to mix any physical link with any llc for a given chip driver. |
104 | with HCI. HCI sees shdlc as the driver and thus send its HCP frames | ||
105 | through shdlc->xmit. | ||
106 | SHDLC adds a new execution context (nfc_shdlc_sm_work()) to run its state | ||
107 | machine and handle both its rx and tx path. | ||
108 | 174 | ||
109 | Included Drivers | 175 | Included Drivers |
110 | ---------------- | 176 | ---------------- |
@@ -117,10 +183,12 @@ Execution Contexts | |||
117 | 183 | ||
118 | The execution contexts are the following: | 184 | The execution contexts are the following: |
119 | - IRQ handler (IRQH): | 185 | - IRQ handler (IRQH): |
120 | fast, cannot sleep. stores incoming frames into an shdlc rx queue | 186 | fast, cannot sleep. sends incoming frames to HCI where they are passed to |
187 | the current llc. In case of shdlc, the frame is queued in shdlc rx queue. | ||
121 | 188 | ||
122 | - SHDLC State Machine worker (SMW) | 189 | - SHDLC State Machine worker (SMW) |
123 | handles shdlc rx & tx queues. Dispatches HCI cmd responses. | 190 | Only when llc_shdlc is used: handles shdlc rx & tx queues. |
191 | Dispatches HCI cmd responses. | ||
124 | 192 | ||
125 | - HCI Tx Cmd worker (MSGTXWQ) | 193 | - HCI Tx Cmd worker (MSGTXWQ) |
126 | Serializes execution of HCI commands. Completes execution in case of response | 194 | Serializes execution of HCI commands. Completes execution in case of response |
@@ -166,6 +234,15 @@ waiting command execution. Response processing involves invoking the completion | |||
166 | callback that was provided by nfc_hci_msg_tx_work() when it sent the command. | 234 | callback that was provided by nfc_hci_msg_tx_work() when it sent the command. |
167 | The completion callback will then wake the syscall context. | 235 | The completion callback will then wake the syscall context. |
168 | 236 | ||
237 | It is also possible to execute the command asynchronously using this API: | ||
238 | |||
239 | static int nfc_hci_execute_cmd_async(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | ||
240 | const u8 *param, size_t param_len, | ||
241 | data_exchange_cb_t cb, void *cb_context) | ||
242 | |||
243 | The workflow is the same, except that the API call returns immediately, and | ||
244 | the callback will be called with the result from the SMW context. | ||
245 | |||
169 | Workflow receiving an HCI event or command | 246 | Workflow receiving an HCI event or command |
170 | ------------------------------------------ | 247 | ------------------------------------------ |
171 | 248 | ||
diff --git a/Documentation/nfc/nfc-pn544.txt b/Documentation/nfc/nfc-pn544.txt index 2fcac9f5996e..b36ca14ca2d6 100644 --- a/Documentation/nfc/nfc-pn544.txt +++ b/Documentation/nfc/nfc-pn544.txt | |||
@@ -1,32 +1,15 @@ | |||
1 | Kernel driver for the NXP Semiconductors PN544 Near Field | 1 | Kernel driver for the NXP Semiconductors PN544 Near Field |
2 | Communication chip | 2 | Communication chip |
3 | 3 | ||
4 | Author: Jari Vanhala | ||
5 | Contact: Matti Aaltonen (matti.j.aaltonen at nokia.com) | ||
6 | |||
7 | General | 4 | General |
8 | ------- | 5 | ------- |
9 | 6 | ||
10 | The PN544 is an integrated transmission module for contactless | 7 | The PN544 is an integrated transmission module for contactless |
11 | communication. The driver goes under drives/nfc/ and is compiled as a | 8 | communication. The driver goes under drives/nfc/ and is compiled as a |
12 | module named "pn544". It registers a misc device and creates a device | 9 | module named "pn544". |
13 | file named "/dev/pn544". | ||
14 | 10 | ||
15 | Host Interfaces: I2C, SPI and HSU, this driver supports currently only I2C. | 11 | Host Interfaces: I2C, SPI and HSU, this driver supports currently only I2C. |
16 | 12 | ||
17 | The Interface | ||
18 | ------------- | ||
19 | |||
20 | The driver offers a sysfs interface for a hardware test and an IOCTL | ||
21 | interface for selecting between two operating modes. There are read, | ||
22 | write and poll functions for transferring messages. The two operating | ||
23 | modes are the normal (HCI) mode and the firmware update mode. | ||
24 | |||
25 | PN544 is controlled by sending messages from the userspace to the | ||
26 | chip. The main function of the driver is just to pass those messages | ||
27 | without caring about the message content. | ||
28 | |||
29 | |||
30 | Protocols | 13 | Protocols |
31 | --------- | 14 | --------- |
32 | 15 | ||
@@ -47,68 +30,3 @@ and third (LSB) bytes of the message. The maximum FW message length is | |||
47 | 30 | ||
48 | For the ETSI HCI specification see | 31 | For the ETSI HCI specification see |
49 | http://www.etsi.org/WebSite/Technologies/ProtocolSpecification.aspx | 32 | http://www.etsi.org/WebSite/Technologies/ProtocolSpecification.aspx |
50 | |||
51 | The Hardware Test | ||
52 | ----------------- | ||
53 | |||
54 | The idea of the test is that it can performed by reading from the | ||
55 | corresponding sysfs file. The test is implemented in the board file | ||
56 | and it should test that PN544 can be put into the firmware update | ||
57 | mode. If the test is not implemented the sysfs file does not get | ||
58 | created. | ||
59 | |||
60 | Example: | ||
61 | > cat /sys/module/pn544/drivers/i2c\:pn544/3-002b/nfc_test | ||
62 | 1 | ||
63 | |||
64 | Normal Operation | ||
65 | ---------------- | ||
66 | |||
67 | PN544 is powered up when the device file is opened, otherwise it's | ||
68 | turned off. Only one instance can use the device at a time. | ||
69 | |||
70 | Userspace applications control PN544 with HCI messages. The hardware | ||
71 | sends an interrupt when data is available for reading. Data is | ||
72 | physically read when the read function is called by a userspace | ||
73 | application. Poll() checks the read interrupt state. Configuration and | ||
74 | self testing are also done from the userspace using read and write. | ||
75 | |||
76 | Example platform data: | ||
77 | |||
78 | static int rx71_pn544_nfc_request_resources(struct i2c_client *client) | ||
79 | { | ||
80 | /* Get and setup the HW resources for the device */ | ||
81 | } | ||
82 | |||
83 | static void rx71_pn544_nfc_free_resources(void) | ||
84 | { | ||
85 | /* Release the HW resources */ | ||
86 | } | ||
87 | |||
88 | static void rx71_pn544_nfc_enable(int fw) | ||
89 | { | ||
90 | /* Turn the device on */ | ||
91 | } | ||
92 | |||
93 | static int rx71_pn544_nfc_test(void) | ||
94 | { | ||
95 | /* | ||
96 | * Put the device into the FW update mode | ||
97 | * and then back to the normal mode. | ||
98 | * Check the behavior and return one on success, | ||
99 | * zero on failure. | ||
100 | */ | ||
101 | } | ||
102 | |||
103 | static void rx71_pn544_nfc_disable(void) | ||
104 | { | ||
105 | /* turn the power off */ | ||
106 | } | ||
107 | |||
108 | static struct pn544_nfc_platform_data rx71_nfc_data = { | ||
109 | .request_resources = rx71_pn544_nfc_request_resources, | ||
110 | .free_resources = rx71_pn544_nfc_free_resources, | ||
111 | .enable = rx71_pn544_nfc_enable, | ||
112 | .test = rx71_pn544_nfc_test, | ||
113 | .disable = rx71_pn544_nfc_disable, | ||
114 | }; | ||
diff --git a/arch/mips/bcm47xx/serial.c b/arch/mips/bcm47xx/serial.c index 57981e4fe2bc..b8ef965705cf 100644 --- a/arch/mips/bcm47xx/serial.c +++ b/arch/mips/bcm47xx/serial.c | |||
@@ -62,7 +62,7 @@ static int __init uart8250_init_bcma(void) | |||
62 | 62 | ||
63 | p->mapbase = (unsigned int) bcma_port->regs; | 63 | p->mapbase = (unsigned int) bcma_port->regs; |
64 | p->membase = (void *) bcma_port->regs; | 64 | p->membase = (void *) bcma_port->regs; |
65 | p->irq = bcma_port->irq + 2; | 65 | p->irq = bcma_port->irq; |
66 | p->uartclk = bcma_port->baud_base; | 66 | p->uartclk = bcma_port->baud_base; |
67 | p->regshift = bcma_port->reg_shift; | 67 | p->regshift = bcma_port->reg_shift; |
68 | p->iotype = UPIO_MEM; | 68 | p->iotype = UPIO_MEM; |
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 19e3fbfd5757..04f7c86ea3d8 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
@@ -31,6 +31,8 @@ int __init bcma_bus_early_register(struct bcma_bus *bus, | |||
31 | int bcma_bus_suspend(struct bcma_bus *bus); | 31 | int bcma_bus_suspend(struct bcma_bus *bus); |
32 | int bcma_bus_resume(struct bcma_bus *bus); | 32 | int bcma_bus_resume(struct bcma_bus *bus); |
33 | #endif | 33 | #endif |
34 | struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, | ||
35 | u8 unit); | ||
34 | 36 | ||
35 | /* scan.c */ | 37 | /* scan.c */ |
36 | int bcma_bus_scan(struct bcma_bus *bus); | 38 | int bcma_bus_scan(struct bcma_bus *bus); |
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index e461ad25fda4..28fa50ad87be 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c | |||
@@ -329,7 +329,7 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc) | |||
329 | return; | 329 | return; |
330 | } | 330 | } |
331 | 331 | ||
332 | irq = bcma_core_mips_irq(cc->core); | 332 | irq = bcma_core_irq(cc->core); |
333 | 333 | ||
334 | /* Determine the registers of the UARTs */ | 334 | /* Determine the registers of the UARTs */ |
335 | cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART); | 335 | cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART); |
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c index 792daad28cbc..9fe86ee16c66 100644 --- a/drivers/bcma/driver_mips.c +++ b/drivers/bcma/driver_mips.c | |||
@@ -74,28 +74,41 @@ static u32 bcma_core_mips_irqflag(struct bcma_device *dev) | |||
74 | return dev->core_index; | 74 | return dev->core_index; |
75 | flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30); | 75 | flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30); |
76 | 76 | ||
77 | return flag & 0x1F; | 77 | if (flag) |
78 | return flag & 0x1F; | ||
79 | else | ||
80 | return 0x3f; | ||
78 | } | 81 | } |
79 | 82 | ||
80 | /* Get the MIPS IRQ assignment for a specified device. | 83 | /* Get the MIPS IRQ assignment for a specified device. |
81 | * If unassigned, 0 is returned. | 84 | * If unassigned, 0 is returned. |
85 | * If disabled, 5 is returned. | ||
86 | * If not supported, 6 is returned. | ||
82 | */ | 87 | */ |
83 | unsigned int bcma_core_mips_irq(struct bcma_device *dev) | 88 | static unsigned int bcma_core_mips_irq(struct bcma_device *dev) |
84 | { | 89 | { |
85 | struct bcma_device *mdev = dev->bus->drv_mips.core; | 90 | struct bcma_device *mdev = dev->bus->drv_mips.core; |
86 | u32 irqflag; | 91 | u32 irqflag; |
87 | unsigned int irq; | 92 | unsigned int irq; |
88 | 93 | ||
89 | irqflag = bcma_core_mips_irqflag(dev); | 94 | irqflag = bcma_core_mips_irqflag(dev); |
95 | if (irqflag == 0x3f) | ||
96 | return 6; | ||
90 | 97 | ||
91 | for (irq = 1; irq <= 4; irq++) | 98 | for (irq = 0; irq <= 4; irq++) |
92 | if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) & | 99 | if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) & |
93 | (1 << irqflag)) | 100 | (1 << irqflag)) |
94 | return irq; | 101 | return irq; |
95 | 102 | ||
96 | return 0; | 103 | return 5; |
104 | } | ||
105 | |||
106 | unsigned int bcma_core_irq(struct bcma_device *dev) | ||
107 | { | ||
108 | unsigned int mips_irq = bcma_core_mips_irq(dev); | ||
109 | return mips_irq <= 4 ? mips_irq + 2 : 0; | ||
97 | } | 110 | } |
98 | EXPORT_SYMBOL(bcma_core_mips_irq); | 111 | EXPORT_SYMBOL(bcma_core_irq); |
99 | 112 | ||
100 | static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) | 113 | static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) |
101 | { | 114 | { |
@@ -114,7 +127,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) | |||
114 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0), | 127 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0), |
115 | bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & | 128 | bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & |
116 | ~(1 << irqflag)); | 129 | ~(1 << irqflag)); |
117 | else | 130 | else if (oldirq != 5) |
118 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); | 131 | bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); |
119 | 132 | ||
120 | /* assign the new one */ | 133 | /* assign the new one */ |
@@ -123,9 +136,9 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) | |||
123 | bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) | | 136 | bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) | |
124 | (1 << irqflag)); | 137 | (1 << irqflag)); |
125 | } else { | 138 | } else { |
126 | u32 oldirqflag = bcma_read32(mdev, | 139 | u32 irqinitmask = bcma_read32(mdev, |
127 | BCMA_MIPS_MIPS74K_INTMASK(irq)); | 140 | BCMA_MIPS_MIPS74K_INTMASK(irq)); |
128 | if (oldirqflag) { | 141 | if (irqinitmask) { |
129 | struct bcma_device *core; | 142 | struct bcma_device *core; |
130 | 143 | ||
131 | /* backplane irq line is in use, find out who uses | 144 | /* backplane irq line is in use, find out who uses |
@@ -133,7 +146,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) | |||
133 | */ | 146 | */ |
134 | list_for_each_entry(core, &bus->cores, list) { | 147 | list_for_each_entry(core, &bus->cores, list) { |
135 | if ((1 << bcma_core_mips_irqflag(core)) == | 148 | if ((1 << bcma_core_mips_irqflag(core)) == |
136 | oldirqflag) { | 149 | irqinitmask) { |
137 | bcma_core_mips_set_irq(core, 0); | 150 | bcma_core_mips_set_irq(core, 0); |
138 | break; | 151 | break; |
139 | } | 152 | } |
@@ -143,15 +156,31 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) | |||
143 | 1 << irqflag); | 156 | 1 << irqflag); |
144 | } | 157 | } |
145 | 158 | ||
146 | bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n", | 159 | bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n", |
147 | dev->id.id, oldirq + 2, irq + 2); | 160 | dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2); |
161 | } | ||
162 | |||
163 | static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq, | ||
164 | u16 coreid, u8 unit) | ||
165 | { | ||
166 | struct bcma_device *core; | ||
167 | |||
168 | core = bcma_find_core_unit(bus, coreid, unit); | ||
169 | if (!core) { | ||
170 | bcma_warn(bus, | ||
171 | "Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n", | ||
172 | coreid, unit); | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | bcma_core_mips_set_irq(core, irq); | ||
148 | } | 177 | } |
149 | 178 | ||
150 | static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq) | 179 | static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq) |
151 | { | 180 | { |
152 | int i; | 181 | int i; |
153 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; | 182 | static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; |
154 | printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id); | 183 | printk(KERN_DEBUG KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id); |
155 | for (i = 0; i <= 6; i++) | 184 | for (i = 0; i <= 6; i++) |
156 | printk(" %s%s", irq_name[i], i == irq ? "*" : " "); | 185 | printk(" %s%s", irq_name[i], i == irq ? "*" : " "); |
157 | printk("\n"); | 186 | printk("\n"); |
@@ -227,6 +256,32 @@ void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) | |||
227 | mcore->early_setup_done = true; | 256 | mcore->early_setup_done = true; |
228 | } | 257 | } |
229 | 258 | ||
259 | static void bcma_fix_i2s_irqflag(struct bcma_bus *bus) | ||
260 | { | ||
261 | struct bcma_device *cpu, *pcie, *i2s; | ||
262 | |||
263 | /* Fixup the interrupts in 4716/4748 for i2s core (2010 Broadcom SDK) | ||
264 | * (IRQ flags > 7 are ignored when setting the interrupt masks) | ||
265 | */ | ||
266 | if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4716 && | ||
267 | bus->chipinfo.id != BCMA_CHIP_ID_BCM4748) | ||
268 | return; | ||
269 | |||
270 | cpu = bcma_find_core(bus, BCMA_CORE_MIPS_74K); | ||
271 | pcie = bcma_find_core(bus, BCMA_CORE_PCIE); | ||
272 | i2s = bcma_find_core(bus, BCMA_CORE_I2S); | ||
273 | if (cpu && pcie && i2s && | ||
274 | bcma_aread32(cpu, BCMA_MIPS_OOBSELINA74) == 0x08060504 && | ||
275 | bcma_aread32(pcie, BCMA_MIPS_OOBSELINA74) == 0x08060504 && | ||
276 | bcma_aread32(i2s, BCMA_MIPS_OOBSELOUTA30) == 0x88) { | ||
277 | bcma_awrite32(cpu, BCMA_MIPS_OOBSELINA74, 0x07060504); | ||
278 | bcma_awrite32(pcie, BCMA_MIPS_OOBSELINA74, 0x07060504); | ||
279 | bcma_awrite32(i2s, BCMA_MIPS_OOBSELOUTA30, 0x87); | ||
280 | bcma_debug(bus, | ||
281 | "Moved i2s interrupt to oob line 7 instead of 8\n"); | ||
282 | } | ||
283 | } | ||
284 | |||
230 | void bcma_core_mips_init(struct bcma_drv_mips *mcore) | 285 | void bcma_core_mips_init(struct bcma_drv_mips *mcore) |
231 | { | 286 | { |
232 | struct bcma_bus *bus; | 287 | struct bcma_bus *bus; |
@@ -236,43 +291,55 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore) | |||
236 | if (mcore->setup_done) | 291 | if (mcore->setup_done) |
237 | return; | 292 | return; |
238 | 293 | ||
239 | bcma_info(bus, "Initializing MIPS core...\n"); | 294 | bcma_debug(bus, "Initializing MIPS core...\n"); |
240 | 295 | ||
241 | bcma_core_mips_early_init(mcore); | 296 | bcma_core_mips_early_init(mcore); |
242 | 297 | ||
243 | mcore->assigned_irqs = 1; | 298 | bcma_fix_i2s_irqflag(bus); |
244 | 299 | ||
245 | /* Assign IRQs to all cores on the bus */ | 300 | switch (bus->chipinfo.id) { |
246 | list_for_each_entry(core, &bus->cores, list) { | 301 | case BCMA_CHIP_ID_BCM4716: |
247 | int mips_irq; | 302 | case BCMA_CHIP_ID_BCM4748: |
248 | if (core->irq) | 303 | bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0); |
249 | continue; | 304 | bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0); |
250 | 305 | bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0); | |
251 | mips_irq = bcma_core_mips_irq(core); | 306 | bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0); |
252 | if (mips_irq > 4) | 307 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0); |
253 | core->irq = 0; | 308 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0); |
254 | else | 309 | break; |
255 | core->irq = mips_irq + 2; | 310 | case BCMA_CHIP_ID_BCM5356: |
256 | if (core->irq > 5) | 311 | case BCMA_CHIP_ID_BCM47162: |
257 | continue; | 312 | case BCMA_CHIP_ID_BCM53572: |
258 | switch (core->id.id) { | 313 | bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0); |
259 | case BCMA_CORE_PCI: | 314 | bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0); |
260 | case BCMA_CORE_PCIE: | 315 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0); |
261 | case BCMA_CORE_ETHERNET: | 316 | break; |
262 | case BCMA_CORE_ETHERNET_GBIT: | 317 | case BCMA_CHIP_ID_BCM5357: |
263 | case BCMA_CORE_MAC_GBIT: | 318 | case BCMA_CHIP_ID_BCM4749: |
264 | case BCMA_CORE_80211: | 319 | bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0); |
265 | case BCMA_CORE_USB20_HOST: | 320 | bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0); |
266 | /* These devices get their own IRQ line if available, | 321 | bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0); |
267 | * the rest goes on IRQ0 | 322 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0); |
268 | */ | 323 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0); |
269 | if (mcore->assigned_irqs <= 4) | 324 | break; |
270 | bcma_core_mips_set_irq(core, | 325 | case BCMA_CHIP_ID_BCM4706: |
271 | mcore->assigned_irqs++); | 326 | bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0); |
272 | break; | 327 | bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT, |
328 | 0); | ||
329 | bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1); | ||
330 | bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0); | ||
331 | bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON, | ||
332 | 0); | ||
333 | break; | ||
334 | default: | ||
335 | list_for_each_entry(core, &bus->cores, list) { | ||
336 | core->irq = bcma_core_irq(core); | ||
273 | } | 337 | } |
338 | bcma_err(bus, | ||
339 | "Unknown device (0x%x) found, can not configure IRQs\n", | ||
340 | bus->chipinfo.id); | ||
274 | } | 341 | } |
275 | bcma_info(bus, "IRQ reconfiguration done\n"); | 342 | bcma_debug(bus, "IRQ reconfiguration done\n"); |
276 | bcma_core_mips_dump_irq(bus); | 343 | bcma_core_mips_dump_irq(bus); |
277 | 344 | ||
278 | mcore->setup_done = true; | 345 | mcore->setup_done = true; |
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index af0c9fabee54..d3bde6cec927 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c | |||
@@ -94,19 +94,19 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
94 | if (dev == 0) { | 94 | if (dev == 0) { |
95 | /* we support only two functions on device 0 */ | 95 | /* we support only two functions on device 0 */ |
96 | if (func > 1) | 96 | if (func > 1) |
97 | return -EINVAL; | 97 | goto out; |
98 | 98 | ||
99 | /* accesses to config registers with offsets >= 256 | 99 | /* accesses to config registers with offsets >= 256 |
100 | * requires indirect access. | 100 | * requires indirect access. |
101 | */ | 101 | */ |
102 | if (off >= PCI_CONFIG_SPACE_SIZE) { | 102 | if (off >= PCI_CONFIG_SPACE_SIZE) { |
103 | addr = (func << 12); | 103 | addr = (func << 12); |
104 | addr |= (off & 0x0FFF); | 104 | addr |= (off & 0x0FFC); |
105 | val = bcma_pcie_read_config(pc, addr); | 105 | val = bcma_pcie_read_config(pc, addr); |
106 | } else { | 106 | } else { |
107 | addr = BCMA_CORE_PCI_PCICFG0; | 107 | addr = BCMA_CORE_PCI_PCICFG0; |
108 | addr |= (func << 8); | 108 | addr |= (func << 8); |
109 | addr |= (off & 0xfc); | 109 | addr |= (off & 0xFC); |
110 | val = pcicore_read32(pc, addr); | 110 | val = pcicore_read32(pc, addr); |
111 | } | 111 | } |
112 | } else { | 112 | } else { |
@@ -119,11 +119,9 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
119 | goto out; | 119 | goto out; |
120 | 120 | ||
121 | if (mips_busprobe32(val, mmio)) { | 121 | if (mips_busprobe32(val, mmio)) { |
122 | val = 0xffffffff; | 122 | val = 0xFFFFFFFF; |
123 | goto unmap; | 123 | goto unmap; |
124 | } | 124 | } |
125 | |||
126 | val = readl(mmio); | ||
127 | } | 125 | } |
128 | val >>= (8 * (off & 3)); | 126 | val >>= (8 * (off & 3)); |
129 | 127 | ||
@@ -151,7 +149,7 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
151 | const void *buf, int len) | 149 | const void *buf, int len) |
152 | { | 150 | { |
153 | int err = -EINVAL; | 151 | int err = -EINVAL; |
154 | u32 addr = 0, val = 0; | 152 | u32 addr, val; |
155 | void __iomem *mmio = 0; | 153 | void __iomem *mmio = 0; |
156 | u16 chipid = pc->core->bus->chipinfo.id; | 154 | u16 chipid = pc->core->bus->chipinfo.id; |
157 | 155 | ||
@@ -159,16 +157,22 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
159 | if (unlikely(len != 1 && len != 2 && len != 4)) | 157 | if (unlikely(len != 1 && len != 2 && len != 4)) |
160 | goto out; | 158 | goto out; |
161 | if (dev == 0) { | 159 | if (dev == 0) { |
160 | /* we support only two functions on device 0 */ | ||
161 | if (func > 1) | ||
162 | goto out; | ||
163 | |||
162 | /* accesses to config registers with offsets >= 256 | 164 | /* accesses to config registers with offsets >= 256 |
163 | * requires indirect access. | 165 | * requires indirect access. |
164 | */ | 166 | */ |
165 | if (off < PCI_CONFIG_SPACE_SIZE) { | 167 | if (off >= PCI_CONFIG_SPACE_SIZE) { |
166 | addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0; | 168 | addr = (func << 12); |
169 | addr |= (off & 0x0FFC); | ||
170 | val = bcma_pcie_read_config(pc, addr); | ||
171 | } else { | ||
172 | addr = BCMA_CORE_PCI_PCICFG0; | ||
167 | addr |= (func << 8); | 173 | addr |= (func << 8); |
168 | addr |= (off & 0xfc); | 174 | addr |= (off & 0xFC); |
169 | mmio = ioremap_nocache(addr, sizeof(val)); | 175 | val = pcicore_read32(pc, addr); |
170 | if (!mmio) | ||
171 | goto out; | ||
172 | } | 176 | } |
173 | } else { | 177 | } else { |
174 | addr = bcma_get_cfgspace_addr(pc, dev, func, off); | 178 | addr = bcma_get_cfgspace_addr(pc, dev, func, off); |
@@ -180,19 +184,17 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
180 | goto out; | 184 | goto out; |
181 | 185 | ||
182 | if (mips_busprobe32(val, mmio)) { | 186 | if (mips_busprobe32(val, mmio)) { |
183 | val = 0xffffffff; | 187 | val = 0xFFFFFFFF; |
184 | goto unmap; | 188 | goto unmap; |
185 | } | 189 | } |
186 | } | 190 | } |
187 | 191 | ||
188 | switch (len) { | 192 | switch (len) { |
189 | case 1: | 193 | case 1: |
190 | val = readl(mmio); | ||
191 | val &= ~(0xFF << (8 * (off & 3))); | 194 | val &= ~(0xFF << (8 * (off & 3))); |
192 | val |= *((const u8 *)buf) << (8 * (off & 3)); | 195 | val |= *((const u8 *)buf) << (8 * (off & 3)); |
193 | break; | 196 | break; |
194 | case 2: | 197 | case 2: |
195 | val = readl(mmio); | ||
196 | val &= ~(0xFFFF << (8 * (off & 3))); | 198 | val &= ~(0xFFFF << (8 * (off & 3))); |
197 | val |= *((const u16 *)buf) << (8 * (off & 3)); | 199 | val |= *((const u16 *)buf) << (8 * (off & 3)); |
198 | break; | 200 | break; |
@@ -200,13 +202,14 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
200 | val = *((const u32 *)buf); | 202 | val = *((const u32 *)buf); |
201 | break; | 203 | break; |
202 | } | 204 | } |
203 | if (dev == 0 && !addr) { | 205 | if (dev == 0) { |
204 | /* accesses to config registers with offsets >= 256 | 206 | /* accesses to config registers with offsets >= 256 |
205 | * requires indirect access. | 207 | * requires indirect access. |
206 | */ | 208 | */ |
207 | addr = (func << 12); | 209 | if (off >= PCI_CONFIG_SPACE_SIZE) |
208 | addr |= (off & 0x0FFF); | 210 | bcma_pcie_write_config(pc, addr, val); |
209 | bcma_pcie_write_config(pc, addr, val); | 211 | else |
212 | pcicore_write32(pc, addr, val); | ||
210 | } else { | 213 | } else { |
211 | writel(val, mmio); | 214 | writel(val, mmio); |
212 | 215 | ||
@@ -276,7 +279,7 @@ static u8 bcma_find_pci_capability(struct bcma_drv_pci *pc, unsigned int dev, | |||
276 | /* check for Header type 0 */ | 279 | /* check for Header type 0 */ |
277 | bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, | 280 | bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, |
278 | sizeof(u8)); | 281 | sizeof(u8)); |
279 | if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) | 282 | if ((byte_val & 0x7F) != PCI_HEADER_TYPE_NORMAL) |
280 | return cap_ptr; | 283 | return cap_ptr; |
281 | 284 | ||
282 | /* check if the capability pointer field exists */ | 285 | /* check if the capability pointer field exists */ |
@@ -426,7 +429,7 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | |||
426 | /* Reset RC */ | 429 | /* Reset RC */ |
427 | usleep_range(3000, 5000); | 430 | usleep_range(3000, 5000); |
428 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); | 431 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); |
429 | usleep_range(1000, 2000); | 432 | msleep(50); |
430 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | | 433 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | |
431 | BCMA_CORE_PCI_CTL_RST_OE); | 434 | BCMA_CORE_PCI_CTL_RST_OE); |
432 | 435 | ||
@@ -488,6 +491,17 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | |||
488 | 491 | ||
489 | bcma_core_pci_enable_crs(pc); | 492 | bcma_core_pci_enable_crs(pc); |
490 | 493 | ||
494 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706 || | ||
495 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4716) { | ||
496 | u16 val16; | ||
497 | bcma_extpci_read_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL, | ||
498 | &val16, sizeof(val16)); | ||
499 | val16 |= (2 << 5); /* Max payload size of 512 */ | ||
500 | val16 |= (2 << 12); /* MRRS 512 */ | ||
501 | bcma_extpci_write_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL, | ||
502 | &val16, sizeof(val16)); | ||
503 | } | ||
504 | |||
491 | /* Enable PCI bridge BAR0 memory & master access */ | 505 | /* Enable PCI bridge BAR0 memory & master access */ |
492 | tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; | 506 | tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; |
493 | bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); | 507 | bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); |
@@ -576,7 +590,7 @@ int bcma_core_pci_plat_dev_init(struct pci_dev *dev) | |||
576 | pr_info("PCI: Fixing up device %s\n", pci_name(dev)); | 590 | pr_info("PCI: Fixing up device %s\n", pci_name(dev)); |
577 | 591 | ||
578 | /* Fix up interrupt lines */ | 592 | /* Fix up interrupt lines */ |
579 | dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2; | 593 | dev->irq = bcma_core_irq(pc_host->pdev->core); |
580 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | 594 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); |
581 | 595 | ||
582 | return 0; | 596 | return 0; |
@@ -595,6 +609,6 @@ int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev) | |||
595 | 609 | ||
596 | pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, | 610 | pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, |
597 | pci_ops); | 611 | pci_ops); |
598 | return bcma_core_mips_irq(pc_host->pdev->core) + 2; | 612 | return bcma_core_irq(pc_host->pdev->core); |
599 | } | 613 | } |
600 | EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); | 614 | EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); |
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 4a92f647b58b..ff8528925322 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -81,8 +81,8 @@ struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) | |||
81 | } | 81 | } |
82 | EXPORT_SYMBOL_GPL(bcma_find_core); | 82 | EXPORT_SYMBOL_GPL(bcma_find_core); |
83 | 83 | ||
84 | static struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, | 84 | struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, |
85 | u8 unit) | 85 | u8 unit) |
86 | { | 86 | { |
87 | struct bcma_device *core; | 87 | struct bcma_device *core; |
88 | 88 | ||
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index b00000e8aef6..33c9a44a9678 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -77,10 +77,15 @@ static struct usb_device_id ath3k_table[] = { | |||
77 | { USB_DEVICE(0x0CF3, 0x311D) }, | 77 | { USB_DEVICE(0x0CF3, 0x311D) }, |
78 | { USB_DEVICE(0x13d3, 0x3375) }, | 78 | { USB_DEVICE(0x13d3, 0x3375) }, |
79 | { USB_DEVICE(0x04CA, 0x3005) }, | 79 | { USB_DEVICE(0x04CA, 0x3005) }, |
80 | { USB_DEVICE(0x04CA, 0x3006) }, | ||
81 | { USB_DEVICE(0x04CA, 0x3008) }, | ||
80 | { USB_DEVICE(0x13d3, 0x3362) }, | 82 | { USB_DEVICE(0x13d3, 0x3362) }, |
81 | { USB_DEVICE(0x0CF3, 0xE004) }, | 83 | { USB_DEVICE(0x0CF3, 0xE004) }, |
82 | { USB_DEVICE(0x0930, 0x0219) }, | 84 | { USB_DEVICE(0x0930, 0x0219) }, |
83 | { USB_DEVICE(0x0489, 0xe057) }, | 85 | { USB_DEVICE(0x0489, 0xe057) }, |
86 | { USB_DEVICE(0x13d3, 0x3393) }, | ||
87 | { USB_DEVICE(0x0489, 0xe04e) }, | ||
88 | { USB_DEVICE(0x0489, 0xe056) }, | ||
84 | 89 | ||
85 | /* Atheros AR5BBU12 with sflash firmware */ | 90 | /* Atheros AR5BBU12 with sflash firmware */ |
86 | { USB_DEVICE(0x0489, 0xE02C) }, | 91 | { USB_DEVICE(0x0489, 0xE02C) }, |
@@ -104,10 +109,15 @@ static struct usb_device_id ath3k_blist_tbl[] = { | |||
104 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, | 109 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, |
105 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 110 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
106 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | 111 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
112 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, | ||
113 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||
107 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, | 114 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, |
108 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, | 115 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, |
109 | { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, | 116 | { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, |
110 | { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, | 117 | { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, |
118 | { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, | ||
119 | { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, | ||
120 | { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, | ||
111 | 121 | ||
112 | /* Atheros AR5BBU22 with sflash firmware */ | 122 | /* Atheros AR5BBU22 with sflash firmware */ |
113 | { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, | 123 | { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index a1d4ede5b892..7e351e345476 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -135,10 +135,15 @@ static struct usb_device_id blacklist_table[] = { | |||
135 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, | 135 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, |
136 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 136 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
137 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | 137 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
138 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, | ||
139 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||
138 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, | 140 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, |
139 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, | 141 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, |
140 | { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, | 142 | { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, |
141 | { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, | 143 | { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, |
144 | { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, | ||
145 | { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, | ||
146 | { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, | ||
142 | 147 | ||
143 | /* Atheros AR5BBU12 with sflash firmware */ | 148 | /* Atheros AR5BBU12 with sflash firmware */ |
144 | { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, | 149 | { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 30ca0a60a64c..1d264c0f5a9b 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -240,13 +240,14 @@ static const struct ath_ops ath5k_common_ops = { | |||
240 | * Driver Initialization * | 240 | * Driver Initialization * |
241 | \***********************/ | 241 | \***********************/ |
242 | 242 | ||
243 | static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) | 243 | static void ath5k_reg_notifier(struct wiphy *wiphy, |
244 | struct regulatory_request *request) | ||
244 | { | 245 | { |
245 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 246 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
246 | struct ath5k_hw *ah = hw->priv; | 247 | struct ath5k_hw *ah = hw->priv; |
247 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); | 248 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); |
248 | 249 | ||
249 | return ath_reg_notifier_apply(wiphy, request, regulatory); | 250 | ath_reg_notifier_apply(wiphy, request, regulatory); |
250 | } | 251 | } |
251 | 252 | ||
252 | /********************\ | 253 | /********************\ |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 5516a8ccc3c6..4225cca0f198 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -3492,8 +3492,8 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar) | |||
3492 | ath6kl_cfg80211_stop(vif); | 3492 | ath6kl_cfg80211_stop(vif); |
3493 | } | 3493 | } |
3494 | 3494 | ||
3495 | static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy, | 3495 | static void ath6kl_cfg80211_reg_notify(struct wiphy *wiphy, |
3496 | struct regulatory_request *request) | 3496 | struct regulatory_request *request) |
3497 | { | 3497 | { |
3498 | struct ath6kl *ar = wiphy_priv(wiphy); | 3498 | struct ath6kl *ar = wiphy_priv(wiphy); |
3499 | u32 rates[IEEE80211_NUM_BANDS]; | 3499 | u32 rates[IEEE80211_NUM_BANDS]; |
@@ -3506,17 +3506,13 @@ static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy, | |||
3506 | request->processed ? " processed" : "", | 3506 | request->processed ? " processed" : "", |
3507 | request->initiator, request->user_reg_hint_type); | 3507 | request->initiator, request->user_reg_hint_type); |
3508 | 3508 | ||
3509 | /* | ||
3510 | * As firmware is not able intersect regdoms, we can only listen to | ||
3511 | * cellular hints. | ||
3512 | */ | ||
3513 | if (request->user_reg_hint_type != NL80211_USER_REG_HINT_CELL_BASE) | 3509 | if (request->user_reg_hint_type != NL80211_USER_REG_HINT_CELL_BASE) |
3514 | return -EOPNOTSUPP; | 3510 | return; |
3515 | 3511 | ||
3516 | ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, request->alpha2); | 3512 | ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, request->alpha2); |
3517 | if (ret) { | 3513 | if (ret) { |
3518 | ath6kl_err("failed to set regdomain: %d\n", ret); | 3514 | ath6kl_err("failed to set regdomain: %d\n", ret); |
3519 | return ret; | 3515 | return; |
3520 | } | 3516 | } |
3521 | 3517 | ||
3522 | /* | 3518 | /* |
@@ -3536,10 +3532,8 @@ static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy, | |||
3536 | if (ret) { | 3532 | if (ret) { |
3537 | ath6kl_err("failed to start scan for a regdomain change: %d\n", | 3533 | ath6kl_err("failed to start scan for a regdomain change: %d\n", |
3538 | ret); | 3534 | ret); |
3539 | return ret; | 3535 | return; |
3540 | } | 3536 | } |
3541 | |||
3542 | return 0; | ||
3543 | } | 3537 | } |
3544 | 3538 | ||
3545 | static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) | 3539 | static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 3a69804f4c16..d1ff3c246a12 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -86,29 +86,25 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
86 | 86 | ||
87 | if (!pdev->dev.platform_data) { | 87 | if (!pdev->dev.platform_data) { |
88 | dev_err(&pdev->dev, "no platform data specified\n"); | 88 | dev_err(&pdev->dev, "no platform data specified\n"); |
89 | ret = -EINVAL; | 89 | return -EINVAL; |
90 | goto err_out; | ||
91 | } | 90 | } |
92 | 91 | ||
93 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 92 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
94 | if (res == NULL) { | 93 | if (res == NULL) { |
95 | dev_err(&pdev->dev, "no memory resource found\n"); | 94 | dev_err(&pdev->dev, "no memory resource found\n"); |
96 | ret = -ENXIO; | 95 | return -ENXIO; |
97 | goto err_out; | ||
98 | } | 96 | } |
99 | 97 | ||
100 | mem = ioremap_nocache(res->start, resource_size(res)); | 98 | mem = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res)); |
101 | if (mem == NULL) { | 99 | if (mem == NULL) { |
102 | dev_err(&pdev->dev, "ioremap failed\n"); | 100 | dev_err(&pdev->dev, "ioremap failed\n"); |
103 | ret = -ENOMEM; | 101 | return -ENOMEM; |
104 | goto err_out; | ||
105 | } | 102 | } |
106 | 103 | ||
107 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 104 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
108 | if (res == NULL) { | 105 | if (res == NULL) { |
109 | dev_err(&pdev->dev, "no IRQ resource found\n"); | 106 | dev_err(&pdev->dev, "no IRQ resource found\n"); |
110 | ret = -ENXIO; | 107 | return -ENXIO; |
111 | goto err_iounmap; | ||
112 | } | 108 | } |
113 | 109 | ||
114 | irq = res->start; | 110 | irq = res->start; |
@@ -116,8 +112,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
116 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); | 112 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); |
117 | if (hw == NULL) { | 113 | if (hw == NULL) { |
118 | dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); | 114 | dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); |
119 | ret = -ENOMEM; | 115 | return -ENOMEM; |
120 | goto err_iounmap; | ||
121 | } | 116 | } |
122 | 117 | ||
123 | SET_IEEE80211_DEV(hw, &pdev->dev); | 118 | SET_IEEE80211_DEV(hw, &pdev->dev); |
@@ -156,9 +151,6 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
156 | err_free_hw: | 151 | err_free_hw: |
157 | ieee80211_free_hw(hw); | 152 | ieee80211_free_hw(hw); |
158 | platform_set_drvdata(pdev, NULL); | 153 | platform_set_drvdata(pdev, NULL); |
159 | err_iounmap: | ||
160 | iounmap(mem); | ||
161 | err_out: | ||
162 | return ret; | 154 | return ret; |
163 | } | 155 | } |
164 | 156 | ||
@@ -168,12 +160,10 @@ static int ath_ahb_remove(struct platform_device *pdev) | |||
168 | 160 | ||
169 | if (hw) { | 161 | if (hw) { |
170 | struct ath_softc *sc = hw->priv; | 162 | struct ath_softc *sc = hw->priv; |
171 | void __iomem *mem = sc->mem; | ||
172 | 163 | ||
173 | ath9k_deinit_device(sc); | 164 | ath9k_deinit_device(sc); |
174 | free_irq(sc->irq, sc); | 165 | free_irq(sc->irq, sc); |
175 | ieee80211_free_hw(sc->hw); | 166 | ieee80211_free_hw(sc->hw); |
176 | iounmap(mem); | ||
177 | platform_set_drvdata(pdev, NULL); | 167 | platform_set_drvdata(pdev, NULL); |
178 | } | 168 | } |
179 | 169 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index e09ec40ce71a..7ecd40f07a74 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -152,7 +152,8 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, | |||
152 | ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", | 152 | ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", |
153 | aniState->ofdmNoiseImmunityLevel, | 153 | aniState->ofdmNoiseImmunityLevel, |
154 | immunityLevel, BEACON_RSSI(ah), | 154 | immunityLevel, BEACON_RSSI(ah), |
155 | aniState->rssiThrLow, aniState->rssiThrHigh); | 155 | ATH9K_ANI_RSSI_THR_LOW, |
156 | ATH9K_ANI_RSSI_THR_HIGH); | ||
156 | 157 | ||
157 | if (!scan) | 158 | if (!scan) |
158 | aniState->ofdmNoiseImmunityLevel = immunityLevel; | 159 | aniState->ofdmNoiseImmunityLevel = immunityLevel; |
@@ -173,7 +174,7 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, | |||
173 | 174 | ||
174 | weak_sig = entry_ofdm->ofdm_weak_signal_on; | 175 | weak_sig = entry_ofdm->ofdm_weak_signal_on; |
175 | if (ah->opmode == NL80211_IFTYPE_STATION && | 176 | if (ah->opmode == NL80211_IFTYPE_STATION && |
176 | BEACON_RSSI(ah) <= aniState->rssiThrHigh) | 177 | BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_HIGH) |
177 | weak_sig = true; | 178 | weak_sig = true; |
178 | 179 | ||
179 | if (aniState->ofdmWeakSigDetect != weak_sig) | 180 | if (aniState->ofdmWeakSigDetect != weak_sig) |
@@ -216,11 +217,11 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel, | |||
216 | 217 | ||
217 | ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", | 218 | ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", |
218 | aniState->cckNoiseImmunityLevel, immunityLevel, | 219 | aniState->cckNoiseImmunityLevel, immunityLevel, |
219 | BEACON_RSSI(ah), aniState->rssiThrLow, | 220 | BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW, |
220 | aniState->rssiThrHigh); | 221 | ATH9K_ANI_RSSI_THR_HIGH); |
221 | 222 | ||
222 | if (ah->opmode == NL80211_IFTYPE_STATION && | 223 | if (ah->opmode == NL80211_IFTYPE_STATION && |
223 | BEACON_RSSI(ah) <= aniState->rssiThrLow && | 224 | BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW && |
224 | immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) | 225 | immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) |
225 | immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; | 226 | immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; |
226 | 227 | ||
@@ -418,9 +419,6 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) | |||
418 | return; | 419 | return; |
419 | 420 | ||
420 | aniState = &ah->curchan->ani; | 421 | aniState = &ah->curchan->ani; |
421 | if (WARN_ON(!aniState)) | ||
422 | return; | ||
423 | |||
424 | if (!ath9k_hw_ani_read_counters(ah)) | 422 | if (!ath9k_hw_ani_read_counters(ah)) |
425 | return; | 423 | return; |
426 | 424 | ||
@@ -489,23 +487,6 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah) | |||
489 | } | 487 | } |
490 | EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); | 488 | EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); |
491 | 489 | ||
492 | void ath9k_hw_ani_setup(struct ath_hw *ah) | ||
493 | { | ||
494 | int i; | ||
495 | |||
496 | static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; | ||
497 | static const int coarseHigh[] = { -14, -14, -14, -14, -12 }; | ||
498 | static const int coarseLow[] = { -64, -64, -64, -64, -70 }; | ||
499 | static const int firpwr[] = { -78, -78, -78, -78, -80 }; | ||
500 | |||
501 | for (i = 0; i < 5; i++) { | ||
502 | ah->totalSizeDesired[i] = totalSizeDesired[i]; | ||
503 | ah->coarse_high[i] = coarseHigh[i]; | ||
504 | ah->coarse_low[i] = coarseLow[i]; | ||
505 | ah->firpwr[i] = firpwr[i]; | ||
506 | } | ||
507 | } | ||
508 | |||
509 | void ath9k_hw_ani_init(struct ath_hw *ah) | 490 | void ath9k_hw_ani_init(struct ath_hw *ah) |
510 | { | 491 | { |
511 | struct ath_common *common = ath9k_hw_common(ah); | 492 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -531,8 +512,6 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
531 | 512 | ||
532 | ani->ofdmsTurn = true; | 513 | ani->ofdmsTurn = true; |
533 | 514 | ||
534 | ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; | ||
535 | ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; | ||
536 | ani->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG; | 515 | ani->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG; |
537 | ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; | 516 | ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; |
538 | ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; | 517 | ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; |
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 1485bf5e3518..dddb1361039a 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
@@ -104,7 +104,6 @@ struct ath9k_ani_default { | |||
104 | }; | 104 | }; |
105 | 105 | ||
106 | struct ar5416AniState { | 106 | struct ar5416AniState { |
107 | struct ath9k_channel *c; | ||
108 | u8 noiseImmunityLevel; | 107 | u8 noiseImmunityLevel; |
109 | u8 ofdmNoiseImmunityLevel; | 108 | u8 ofdmNoiseImmunityLevel; |
110 | u8 cckNoiseImmunityLevel; | 109 | u8 cckNoiseImmunityLevel; |
@@ -113,15 +112,9 @@ struct ar5416AniState { | |||
113 | u8 spurImmunityLevel; | 112 | u8 spurImmunityLevel; |
114 | u8 firstepLevel; | 113 | u8 firstepLevel; |
115 | u8 ofdmWeakSigDetect; | 114 | u8 ofdmWeakSigDetect; |
116 | u8 cckWeakSigThreshold; | ||
117 | u32 listenTime; | 115 | u32 listenTime; |
118 | int32_t rssiThrLow; | ||
119 | int32_t rssiThrHigh; | ||
120 | u32 ofdmPhyErrCount; | 116 | u32 ofdmPhyErrCount; |
121 | u32 cckPhyErrCount; | 117 | u32 cckPhyErrCount; |
122 | int16_t pktRssi[2]; | ||
123 | int16_t ofdmErrRssi[2]; | ||
124 | int16_t cckErrRssi[2]; | ||
125 | struct ath9k_ani_default iniDef; | 118 | struct ath9k_ani_default iniDef; |
126 | }; | 119 | }; |
127 | 120 | ||
@@ -147,7 +140,6 @@ struct ar5416Stats { | |||
147 | 140 | ||
148 | void ath9k_enable_mib_counters(struct ath_hw *ah); | 141 | void ath9k_enable_mib_counters(struct ath_hw *ah); |
149 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); | 142 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); |
150 | void ath9k_hw_ani_setup(struct ath_hw *ah); | ||
151 | void ath9k_hw_ani_init(struct ath_hw *ah); | 143 | void ath9k_hw_ani_init(struct ath_hw *ah); |
152 | 144 | ||
153 | #endif /* ANI_H */ | 145 | #endif /* ANI_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h index f81e7fc60a36..467ccfae2cee 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h | |||
@@ -466,7 +466,7 @@ static const u32 ar5416Bank0[][2] = { | |||
466 | }; | 466 | }; |
467 | 467 | ||
468 | static const u32 ar5416BB_RfGain[][3] = { | 468 | static const u32 ar5416BB_RfGain[][3] = { |
469 | /* Addr 5G_HT20 5G_HT40 */ | 469 | /* Addr 5G 2G */ |
470 | {0x00009a00, 0x00000000, 0x00000000}, | 470 | {0x00009a00, 0x00000000, 0x00000000}, |
471 | {0x00009a04, 0x00000040, 0x00000040}, | 471 | {0x00009a04, 0x00000040, 0x00000040}, |
472 | {0x00009a08, 0x00000080, 0x00000080}, | 472 | {0x00009a08, 0x00000080, 0x00000080}, |
@@ -546,12 +546,12 @@ static const u32 ar5416Bank2[][2] = { | |||
546 | }; | 546 | }; |
547 | 547 | ||
548 | static const u32 ar5416Bank3[][3] = { | 548 | static const u32 ar5416Bank3[][3] = { |
549 | /* Addr 5G_HT20 5G_HT40 */ | 549 | /* Addr 5G 2G */ |
550 | {0x000098f0, 0x01400018, 0x01c00018}, | 550 | {0x000098f0, 0x01400018, 0x01c00018}, |
551 | }; | 551 | }; |
552 | 552 | ||
553 | static const u32 ar5416Bank6[][3] = { | 553 | static const u32 ar5416Bank6[][3] = { |
554 | /* Addr 5G_HT20 5G_HT40 */ | 554 | /* Addr 5G 2G */ |
555 | {0x0000989c, 0x00000000, 0x00000000}, | 555 | {0x0000989c, 0x00000000, 0x00000000}, |
556 | {0x0000989c, 0x00000000, 0x00000000}, | 556 | {0x0000989c, 0x00000000, 0x00000000}, |
557 | {0x0000989c, 0x00000000, 0x00000000}, | 557 | {0x0000989c, 0x00000000, 0x00000000}, |
@@ -588,7 +588,7 @@ static const u32 ar5416Bank6[][3] = { | |||
588 | }; | 588 | }; |
589 | 589 | ||
590 | static const u32 ar5416Bank6TPC[][3] = { | 590 | static const u32 ar5416Bank6TPC[][3] = { |
591 | /* Addr 5G_HT20 5G_HT40 */ | 591 | /* Addr 5G 2G */ |
592 | {0x0000989c, 0x00000000, 0x00000000}, | 592 | {0x0000989c, 0x00000000, 0x00000000}, |
593 | {0x0000989c, 0x00000000, 0x00000000}, | 593 | {0x0000989c, 0x00000000, 0x00000000}, |
594 | {0x0000989c, 0x00000000, 0x00000000}, | 594 | {0x0000989c, 0x00000000, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 874186bfda41..fd69376ecc83 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -470,16 +470,15 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah, | |||
470 | static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) | 470 | static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) |
471 | { | 471 | { |
472 | #define ATH_ALLOC_BANK(bank, size) do { \ | 472 | #define ATH_ALLOC_BANK(bank, size) do { \ |
473 | bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \ | 473 | bank = devm_kzalloc(ah->dev, sizeof(u32) * size, GFP_KERNEL); \ |
474 | if (!bank) { \ | 474 | if (!bank) \ |
475 | ath_err(common, "Cannot allocate RF banks\n"); \ | 475 | goto error; \ |
476 | return -ENOMEM; \ | ||
477 | } \ | ||
478 | } while (0); | 476 | } while (0); |
479 | 477 | ||
480 | struct ath_common *common = ath9k_hw_common(ah); | 478 | struct ath_common *common = ath9k_hw_common(ah); |
481 | 479 | ||
482 | BUG_ON(AR_SREV_9280_20_OR_LATER(ah)); | 480 | if (AR_SREV_9280_20_OR_LATER(ah)) |
481 | return 0; | ||
483 | 482 | ||
484 | ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); | 483 | ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); |
485 | ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); | 484 | ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); |
@@ -492,35 +491,12 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) | |||
492 | 491 | ||
493 | return 0; | 492 | return 0; |
494 | #undef ATH_ALLOC_BANK | 493 | #undef ATH_ALLOC_BANK |
494 | error: | ||
495 | ath_err(common, "Cannot allocate RF banks\n"); | ||
496 | return -ENOMEM; | ||
495 | } | 497 | } |
496 | 498 | ||
497 | 499 | ||
498 | /** | ||
499 | * ar5008_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers | ||
500 | * @ah: atheros hardware struture | ||
501 | * For the external AR2133/AR5133 radios banks. | ||
502 | */ | ||
503 | static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah) | ||
504 | { | ||
505 | #define ATH_FREE_BANK(bank) do { \ | ||
506 | kfree(bank); \ | ||
507 | bank = NULL; \ | ||
508 | } while (0); | ||
509 | |||
510 | BUG_ON(AR_SREV_9280_20_OR_LATER(ah)); | ||
511 | |||
512 | ATH_FREE_BANK(ah->analogBank0Data); | ||
513 | ATH_FREE_BANK(ah->analogBank1Data); | ||
514 | ATH_FREE_BANK(ah->analogBank2Data); | ||
515 | ATH_FREE_BANK(ah->analogBank3Data); | ||
516 | ATH_FREE_BANK(ah->analogBank6Data); | ||
517 | ATH_FREE_BANK(ah->analogBank6TPCData); | ||
518 | ATH_FREE_BANK(ah->analogBank7Data); | ||
519 | ATH_FREE_BANK(ah->bank6Temp); | ||
520 | |||
521 | #undef ATH_FREE_BANK | ||
522 | } | ||
523 | |||
524 | /* * | 500 | /* * |
525 | * ar5008_hw_set_rf_regs - programs rf registers based on EEPROM | 501 | * ar5008_hw_set_rf_regs - programs rf registers based on EEPROM |
526 | * @ah: atheros hardware structure | 502 | * @ah: atheros hardware structure |
@@ -1380,7 +1356,7 @@ static void ar5008_hw_set_radar_conf(struct ath_hw *ah) | |||
1380 | conf->radar_inband = 8; | 1356 | conf->radar_inband = 8; |
1381 | } | 1357 | } |
1382 | 1358 | ||
1383 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | 1359 | int ar5008_hw_attach_phy_ops(struct ath_hw *ah) |
1384 | { | 1360 | { |
1385 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1361 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
1386 | static const u32 ar5416_cca_regs[6] = { | 1362 | static const u32 ar5416_cca_regs[6] = { |
@@ -1391,12 +1367,15 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | |||
1391 | AR_PHY_CH1_EXT_CCA, | 1367 | AR_PHY_CH1_EXT_CCA, |
1392 | AR_PHY_CH2_EXT_CCA | 1368 | AR_PHY_CH2_EXT_CCA |
1393 | }; | 1369 | }; |
1370 | int ret; | ||
1371 | |||
1372 | ret = ar5008_hw_rf_alloc_ext_banks(ah); | ||
1373 | if (ret) | ||
1374 | return ret; | ||
1394 | 1375 | ||
1395 | priv_ops->rf_set_freq = ar5008_hw_set_channel; | 1376 | priv_ops->rf_set_freq = ar5008_hw_set_channel; |
1396 | priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate; | 1377 | priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate; |
1397 | 1378 | ||
1398 | priv_ops->rf_alloc_ext_banks = ar5008_hw_rf_alloc_ext_banks; | ||
1399 | priv_ops->rf_free_ext_banks = ar5008_hw_rf_free_ext_banks; | ||
1400 | priv_ops->set_rf_regs = ar5008_hw_set_rf_regs; | 1379 | priv_ops->set_rf_regs = ar5008_hw_set_rf_regs; |
1401 | priv_ops->set_channel_regs = ar5008_hw_set_channel_regs; | 1380 | priv_ops->set_channel_regs = ar5008_hw_set_channel_regs; |
1402 | priv_ops->init_bb = ar5008_hw_init_bb; | 1381 | priv_ops->init_bb = ar5008_hw_init_bb; |
@@ -1421,4 +1400,5 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | |||
1421 | ar5008_hw_set_nf_limits(ah); | 1400 | ar5008_hw_set_nf_limits(ah); |
1422 | ar5008_hw_set_radar_conf(ah); | 1401 | ar5008_hw_set_radar_conf(ah); |
1423 | memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs)); | 1402 | memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs)); |
1403 | return 0; | ||
1424 | } | 1404 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h index ea4a230997ac..59524e1d4678 100644 --- a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h | |||
@@ -460,7 +460,7 @@ static const u32 ar5416Common_9100[][2] = { | |||
460 | }; | 460 | }; |
461 | 461 | ||
462 | static const u32 ar5416Bank6_9100[][3] = { | 462 | static const u32 ar5416Bank6_9100[][3] = { |
463 | /* Addr 5G_HT20 5G_HT40 */ | 463 | /* Addr 5G 2G */ |
464 | {0x0000989c, 0x00000000, 0x00000000}, | 464 | {0x0000989c, 0x00000000, 0x00000000}, |
465 | {0x0000989c, 0x00000000, 0x00000000}, | 465 | {0x0000989c, 0x00000000, 0x00000000}, |
466 | {0x0000989c, 0x00000000, 0x00000000}, | 466 | {0x0000989c, 0x00000000, 0x00000000}, |
@@ -497,7 +497,7 @@ static const u32 ar5416Bank6_9100[][3] = { | |||
497 | }; | 497 | }; |
498 | 498 | ||
499 | static const u32 ar5416Bank6TPC_9100[][3] = { | 499 | static const u32 ar5416Bank6TPC_9100[][3] = { |
500 | /* Addr 5G_HT20 5G_HT40 */ | 500 | /* Addr 5G 2G */ |
501 | {0x0000989c, 0x00000000, 0x00000000}, | 501 | {0x0000989c, 0x00000000, 0x00000000}, |
502 | {0x0000989c, 0x00000000, 0x00000000}, | 502 | {0x0000989c, 0x00000000, 0x00000000}, |
503 | {0x0000989c, 0x00000000, 0x00000000}, | 503 | {0x0000989c, 0x00000000, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 648da3e885e9..f053d978540e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -23,13 +23,13 @@ | |||
23 | 23 | ||
24 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ | 24 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ |
25 | 25 | ||
26 | static void ar9002_hw_init_mode_regs(struct ath_hw *ah) | 26 | static int ar9002_hw_init_mode_regs(struct ath_hw *ah) |
27 | { | 27 | { |
28 | if (AR_SREV_9271(ah)) { | 28 | if (AR_SREV_9271(ah)) { |
29 | INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271); | 29 | INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271); |
30 | INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271); | 30 | INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271); |
31 | INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg); | 31 | INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg); |
32 | return; | 32 | return 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | if (ah->config.pcie_clock_req) | 35 | if (ah->config.pcie_clock_req) |
@@ -102,9 +102,9 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) | |||
102 | u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns; | 102 | u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns; |
103 | u32 *data; | 103 | u32 *data; |
104 | 104 | ||
105 | data = kmalloc(size, GFP_KERNEL); | 105 | data = devm_kzalloc(ah->dev, size, GFP_KERNEL); |
106 | if (!data) | 106 | if (!data) |
107 | return; | 107 | return -ENOMEM; |
108 | 108 | ||
109 | memcpy(data, addac->ia_array, size); | 109 | memcpy(data, addac->ia_array, size); |
110 | addac->ia_array = data; | 110 | addac->ia_array = data; |
@@ -120,6 +120,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) | |||
120 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | 120 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, |
121 | ar9287Common_japan_2484_cck_fir_coeff_9287_1_1); | 121 | ar9287Common_japan_2484_cck_fir_coeff_9287_1_1); |
122 | } | 122 | } |
123 | return 0; | ||
123 | } | 124 | } |
124 | 125 | ||
125 | static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah) | 126 | static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah) |
@@ -409,22 +410,30 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah) | |||
409 | } | 410 | } |
410 | 411 | ||
411 | /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ | 412 | /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ |
412 | void ar9002_hw_attach_ops(struct ath_hw *ah) | 413 | int ar9002_hw_attach_ops(struct ath_hw *ah) |
413 | { | 414 | { |
414 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 415 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
415 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | 416 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); |
417 | int ret; | ||
418 | |||
419 | ret = ar9002_hw_init_mode_regs(ah); | ||
420 | if (ret) | ||
421 | return ret; | ||
416 | 422 | ||
417 | priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; | ||
418 | priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; | 423 | priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; |
419 | 424 | ||
420 | ops->config_pci_powersave = ar9002_hw_configpcipowersave; | 425 | ops->config_pci_powersave = ar9002_hw_configpcipowersave; |
421 | 426 | ||
422 | ar5008_hw_attach_phy_ops(ah); | 427 | ret = ar5008_hw_attach_phy_ops(ah); |
428 | if (ret) | ||
429 | return ret; | ||
430 | |||
423 | if (AR_SREV_9280_20_OR_LATER(ah)) | 431 | if (AR_SREV_9280_20_OR_LATER(ah)) |
424 | ar9002_hw_attach_phy_ops(ah); | 432 | ar9002_hw_attach_phy_ops(ah); |
425 | 433 | ||
426 | ar9002_hw_attach_calib_ops(ah); | 434 | ar9002_hw_attach_calib_ops(ah); |
427 | ar9002_hw_attach_mac_ops(ah); | 435 | ar9002_hw_attach_mac_ops(ah); |
436 | return 0; | ||
428 | } | 437 | } |
429 | 438 | ||
430 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) | 439 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 846dd7974eb8..f4003512d8d5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
@@ -555,14 +555,73 @@ static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah, | |||
555 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); | 555 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); |
556 | } | 556 | } |
557 | 557 | ||
558 | static void ar9002_hw_spectral_scan_config(struct ath_hw *ah, | ||
559 | struct ath_spec_scan *param) | ||
560 | { | ||
561 | u8 count; | ||
562 | |||
563 | if (!param->enabled) { | ||
564 | REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, | ||
565 | AR_PHY_SPECTRAL_SCAN_ENABLE); | ||
566 | return; | ||
567 | } | ||
568 | REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA); | ||
569 | REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE); | ||
570 | |||
571 | if (param->short_repeat) | ||
572 | REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, | ||
573 | AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT); | ||
574 | else | ||
575 | REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, | ||
576 | AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT); | ||
577 | |||
578 | /* on AR92xx, the highest bit of count will make the the chip send | ||
579 | * spectral samples endlessly. Check if this really was intended, | ||
580 | * and fix otherwise. | ||
581 | */ | ||
582 | count = param->count; | ||
583 | if (param->endless) | ||
584 | count = 0x80; | ||
585 | else if (count & 0x80) | ||
586 | count = 0x7f; | ||
587 | |||
588 | REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, | ||
589 | AR_PHY_SPECTRAL_SCAN_COUNT, count); | ||
590 | REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, | ||
591 | AR_PHY_SPECTRAL_SCAN_PERIOD, param->period); | ||
592 | REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, | ||
593 | AR_PHY_SPECTRAL_SCAN_FFT_PERIOD, param->fft_period); | ||
594 | |||
595 | return; | ||
596 | } | ||
597 | |||
598 | static void ar9002_hw_spectral_scan_trigger(struct ath_hw *ah) | ||
599 | { | ||
600 | REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE); | ||
601 | /* Activate spectral scan */ | ||
602 | REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, | ||
603 | AR_PHY_SPECTRAL_SCAN_ACTIVE); | ||
604 | } | ||
605 | |||
606 | static void ar9002_hw_spectral_scan_wait(struct ath_hw *ah) | ||
607 | { | ||
608 | struct ath_common *common = ath9k_hw_common(ah); | ||
609 | |||
610 | /* Poll for spectral scan complete */ | ||
611 | if (!ath9k_hw_wait(ah, AR_PHY_SPECTRAL_SCAN, | ||
612 | AR_PHY_SPECTRAL_SCAN_ACTIVE, | ||
613 | 0, AH_WAIT_TIMEOUT)) { | ||
614 | ath_err(common, "spectral scan wait failed\n"); | ||
615 | return; | ||
616 | } | ||
617 | } | ||
618 | |||
558 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | 619 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah) |
559 | { | 620 | { |
560 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 621 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
561 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | 622 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); |
562 | 623 | ||
563 | priv_ops->set_rf_regs = NULL; | 624 | priv_ops->set_rf_regs = NULL; |
564 | priv_ops->rf_alloc_ext_banks = NULL; | ||
565 | priv_ops->rf_free_ext_banks = NULL; | ||
566 | priv_ops->rf_set_freq = ar9002_hw_set_channel; | 625 | priv_ops->rf_set_freq = ar9002_hw_set_channel; |
567 | priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate; | 626 | priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate; |
568 | priv_ops->olc_init = ar9002_olc_init; | 627 | priv_ops->olc_init = ar9002_olc_init; |
@@ -571,6 +630,9 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | |||
571 | 630 | ||
572 | ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get; | 631 | ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get; |
573 | ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set; | 632 | ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set; |
633 | ops->spectral_scan_config = ar9002_hw_spectral_scan_config; | ||
634 | ops->spectral_scan_trigger = ar9002_hw_spectral_scan_trigger; | ||
635 | ops->spectral_scan_wait = ar9002_hw_spectral_scan_wait; | ||
574 | 636 | ||
575 | ar9002_hw_set_nf_limits(ah); | 637 | ar9002_hw_set_nf_limits(ah); |
576 | } | 638 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 262e1e036fd7..db5ffada2217 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | |||
@@ -744,6 +744,186 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { | |||
744 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 744 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
745 | }; | 745 | }; |
746 | 746 | ||
747 | static const u32 ar9300Modes_mixed_ob_db_tx_gain_table_2p2[][5] = { | ||
748 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
749 | {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, | ||
750 | {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, | ||
751 | {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, | ||
752 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
753 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | ||
754 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
755 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | ||
756 | {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, | ||
757 | {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, | ||
758 | {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, | ||
759 | {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400}, | ||
760 | {0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402}, | ||
761 | {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, | ||
762 | {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603}, | ||
763 | {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02}, | ||
764 | {0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04}, | ||
765 | {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20}, | ||
766 | {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20}, | ||
767 | {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22}, | ||
768 | {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24}, | ||
769 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640}, | ||
770 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660}, | ||
771 | {0x0000a544, 0x52022470, 0x52022470, 0x3b001861, 0x3b001861}, | ||
772 | {0x0000a548, 0x55022490, 0x55022490, 0x3e001a81, 0x3e001a81}, | ||
773 | {0x0000a54c, 0x59022492, 0x59022492, 0x42001a83, 0x42001a83}, | ||
774 | {0x0000a550, 0x5d022692, 0x5d022692, 0x44001c84, 0x44001c84}, | ||
775 | {0x0000a554, 0x61022892, 0x61022892, 0x48001ce3, 0x48001ce3}, | ||
776 | {0x0000a558, 0x65024890, 0x65024890, 0x4c001ce5, 0x4c001ce5}, | ||
777 | {0x0000a55c, 0x69024892, 0x69024892, 0x50001ce9, 0x50001ce9}, | ||
778 | {0x0000a560, 0x6e024c92, 0x6e024c92, 0x54001ceb, 0x54001ceb}, | ||
779 | {0x0000a564, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec}, | ||
780 | {0x0000a568, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec}, | ||
781 | {0x0000a56c, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec}, | ||
782 | {0x0000a570, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec}, | ||
783 | {0x0000a574, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec}, | ||
784 | {0x0000a578, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec}, | ||
785 | {0x0000a57c, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec}, | ||
786 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | ||
787 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, | ||
788 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, | ||
789 | {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, | ||
790 | {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, | ||
791 | {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400}, | ||
792 | {0x0000a598, 0x21802220, 0x21802220, 0x15800402, 0x15800402}, | ||
793 | {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, | ||
794 | {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603}, | ||
795 | {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02}, | ||
796 | {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04}, | ||
797 | {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20}, | ||
798 | {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20}, | ||
799 | {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22}, | ||
800 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24}, | ||
801 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640}, | ||
802 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660}, | ||
803 | {0x0000a5c4, 0x52822470, 0x52822470, 0x3b801861, 0x3b801861}, | ||
804 | {0x0000a5c8, 0x55822490, 0x55822490, 0x3e801a81, 0x3e801a81}, | ||
805 | {0x0000a5cc, 0x59822492, 0x59822492, 0x42801a83, 0x42801a83}, | ||
806 | {0x0000a5d0, 0x5d822692, 0x5d822692, 0x44801c84, 0x44801c84}, | ||
807 | {0x0000a5d4, 0x61822892, 0x61822892, 0x48801ce3, 0x48801ce3}, | ||
808 | {0x0000a5d8, 0x65824890, 0x65824890, 0x4c801ce5, 0x4c801ce5}, | ||
809 | {0x0000a5dc, 0x69824892, 0x69824892, 0x50801ce9, 0x50801ce9}, | ||
810 | {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x54801ceb, 0x54801ceb}, | ||
811 | {0x0000a5e4, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec}, | ||
812 | {0x0000a5e8, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec}, | ||
813 | {0x0000a5ec, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec}, | ||
814 | {0x0000a5f0, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec}, | ||
815 | {0x0000a5f4, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec}, | ||
816 | {0x0000a5f8, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec}, | ||
817 | {0x0000a5fc, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec}, | ||
818 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
819 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
820 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
821 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
822 | {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
823 | {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, | ||
824 | {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, | ||
825 | {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, | ||
826 | {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, | ||
827 | {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, | ||
828 | {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, | ||
829 | {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
830 | {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
831 | {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
832 | {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
833 | {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
834 | {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, | ||
835 | {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, | ||
836 | {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, | ||
837 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
838 | {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, | ||
839 | {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, | ||
840 | {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, | ||
841 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
842 | {0x00016044, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, | ||
843 | {0x00016048, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, | ||
844 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
845 | {0x00016444, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, | ||
846 | {0x00016448, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, | ||
847 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
848 | {0x00016844, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, | ||
849 | {0x00016848, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, | ||
850 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
851 | }; | ||
852 | |||
853 | static const u32 ar9300Modes_type5_tx_gain_table_2p2[][5] = { | ||
854 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
855 | {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | ||
856 | {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | ||
857 | {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | ||
858 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
859 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | ||
860 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
861 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | ||
862 | {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, | ||
863 | {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, | ||
864 | {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, | ||
865 | {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, | ||
866 | {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, | ||
867 | {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, | ||
868 | {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, | ||
869 | {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, | ||
870 | {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, | ||
871 | {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, | ||
872 | {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, | ||
873 | {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, | ||
874 | {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, | ||
875 | {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, | ||
876 | {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, | ||
877 | {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, | ||
878 | {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, | ||
879 | {0x0000a54c, 0x5e08442e, 0x5e08442e, 0x47001a83, 0x47001a83}, | ||
880 | {0x0000a550, 0x620a4431, 0x620a4431, 0x4a001c84, 0x4a001c84}, | ||
881 | {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, | ||
882 | {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, | ||
883 | {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, | ||
884 | {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, | ||
885 | {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
886 | {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
887 | {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
888 | {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
889 | {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
890 | {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
891 | {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
892 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
893 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
894 | {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | ||
895 | {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | ||
896 | {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | ||
897 | {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, | ||
898 | {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, | ||
899 | {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, | ||
900 | {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, | ||
901 | {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, | ||
902 | {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, | ||
903 | {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
904 | {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
905 | {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
906 | {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
907 | {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
908 | {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | ||
909 | {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | ||
910 | {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | ||
911 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
912 | {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | ||
913 | {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | ||
914 | {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | ||
915 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
916 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
917 | {0x00016048, 0x65240001, 0x65240001, 0x66480001, 0x66480001}, | ||
918 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
919 | {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
920 | {0x00016448, 0x65240001, 0x65240001, 0x66480001, 0x66480001}, | ||
921 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
922 | {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
923 | {0x00016848, 0x65240001, 0x65240001, 0x66480001, 0x66480001}, | ||
924 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
925 | }; | ||
926 | |||
747 | static const u32 ar9300Common_rx_gain_table_2p2[][2] = { | 927 | static const u32 ar9300Common_rx_gain_table_2p2[][2] = { |
748 | /* Addr allmodes */ | 928 | /* Addr allmodes */ |
749 | {0x0000a000, 0x00010000}, | 929 | {0x0000a000, 0x00010000}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 8b0d8dcd7625..4cc13940c895 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -32,7 +32,6 @@ struct coeff { | |||
32 | 32 | ||
33 | enum ar9003_cal_types { | 33 | enum ar9003_cal_types { |
34 | IQ_MISMATCH_CAL = BIT(0), | 34 | IQ_MISMATCH_CAL = BIT(0), |
35 | TEMP_COMP_CAL = BIT(1), | ||
36 | }; | 35 | }; |
37 | 36 | ||
38 | static void ar9003_hw_setup_calibration(struct ath_hw *ah, | 37 | static void ar9003_hw_setup_calibration(struct ath_hw *ah, |
@@ -49,7 +48,7 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah, | |||
49 | */ | 48 | */ |
50 | REG_RMW_FIELD(ah, AR_PHY_TIMING4, | 49 | REG_RMW_FIELD(ah, AR_PHY_TIMING4, |
51 | AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX, | 50 | AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX, |
52 | currCal->calData->calCountMax); | 51 | currCal->calData->calCountMax); |
53 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); | 52 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); |
54 | 53 | ||
55 | ath_dbg(common, CALIBRATE, | 54 | ath_dbg(common, CALIBRATE, |
@@ -58,14 +57,8 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah, | |||
58 | /* Kick-off cal */ | 57 | /* Kick-off cal */ |
59 | REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL); | 58 | REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL); |
60 | break; | 59 | break; |
61 | case TEMP_COMP_CAL: | 60 | default: |
62 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, | 61 | ath_err(common, "Invalid calibration type\n"); |
63 | AR_PHY_65NM_CH0_THERM_LOCAL, 1); | ||
64 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, | ||
65 | AR_PHY_65NM_CH0_THERM_START, 1); | ||
66 | |||
67 | ath_dbg(common, CALIBRATE, | ||
68 | "starting Temperature Compensation Calibration\n"); | ||
69 | break; | 62 | break; |
70 | } | 63 | } |
71 | } | 64 | } |
@@ -323,6 +316,14 @@ static const struct ath9k_percal_data iq_cal_single_sample = { | |||
323 | static void ar9003_hw_init_cal_settings(struct ath_hw *ah) | 316 | static void ar9003_hw_init_cal_settings(struct ath_hw *ah) |
324 | { | 317 | { |
325 | ah->iq_caldata.calData = &iq_cal_single_sample; | 318 | ah->iq_caldata.calData = &iq_cal_single_sample; |
319 | |||
320 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
321 | ah->enabled_cals |= TX_IQ_CAL; | ||
322 | if (AR_SREV_9485_OR_LATER(ah) && !AR_SREV_9340(ah)) | ||
323 | ah->enabled_cals |= TX_IQ_ON_AGC_CAL; | ||
324 | } | ||
325 | |||
326 | ah->supp_cals = IQ_MISMATCH_CAL; | ||
326 | } | 327 | } |
327 | 328 | ||
328 | /* | 329 | /* |
@@ -959,22 +960,70 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) | |||
959 | AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0); | 960 | AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0); |
960 | } | 961 | } |
961 | 962 | ||
963 | static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah, | ||
964 | struct ath9k_channel *chan) | ||
965 | { | ||
966 | int i; | ||
967 | |||
968 | if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah)) | ||
969 | return; | ||
970 | |||
971 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
972 | if (!(ah->rxchainmask & (1 << i))) | ||
973 | continue; | ||
974 | ar9003_hw_manual_peak_cal(ah, i, IS_CHAN_2GHZ(chan)); | ||
975 | } | ||
976 | } | ||
977 | |||
978 | static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable) | ||
979 | { | ||
980 | u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0, | ||
981 | AR_PHY_CL_TAB_1, | ||
982 | AR_PHY_CL_TAB_2 }; | ||
983 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
984 | bool txclcal_done = false; | ||
985 | int i, j; | ||
986 | |||
987 | if (!caldata || !(ah->enabled_cals & TX_CL_CAL)) | ||
988 | return; | ||
989 | |||
990 | txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & | ||
991 | AR_PHY_AGC_CONTROL_CLC_SUCCESS); | ||
992 | |||
993 | if (caldata->done_txclcal_once) { | ||
994 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
995 | if (!(ah->txchainmask & (1 << i))) | ||
996 | continue; | ||
997 | for (j = 0; j < MAX_CL_TAB_ENTRY; j++) | ||
998 | REG_WRITE(ah, CL_TAB_ENTRY(cl_idx[i]), | ||
999 | caldata->tx_clcal[i][j]); | ||
1000 | } | ||
1001 | } else if (is_reusable && txclcal_done) { | ||
1002 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
1003 | if (!(ah->txchainmask & (1 << i))) | ||
1004 | continue; | ||
1005 | for (j = 0; j < MAX_CL_TAB_ENTRY; j++) | ||
1006 | caldata->tx_clcal[i][j] = | ||
1007 | REG_READ(ah, CL_TAB_ENTRY(cl_idx[i])); | ||
1008 | } | ||
1009 | caldata->done_txclcal_once = true; | ||
1010 | } | ||
1011 | } | ||
1012 | |||
962 | static bool ar9003_hw_init_cal(struct ath_hw *ah, | 1013 | static bool ar9003_hw_init_cal(struct ath_hw *ah, |
963 | struct ath9k_channel *chan) | 1014 | struct ath9k_channel *chan) |
964 | { | 1015 | { |
965 | struct ath_common *common = ath9k_hw_common(ah); | 1016 | struct ath_common *common = ath9k_hw_common(ah); |
966 | struct ath9k_hw_cal_data *caldata = ah->caldata; | 1017 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
967 | bool txiqcal_done = false, txclcal_done = false; | 1018 | bool txiqcal_done = false; |
968 | bool is_reusable = true, status = true; | 1019 | bool is_reusable = true, status = true; |
969 | bool run_rtt_cal = false, run_agc_cal; | 1020 | bool run_rtt_cal = false, run_agc_cal, sep_iq_cal = false; |
970 | bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); | 1021 | bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); |
971 | u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | | 1022 | u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | |
972 | AR_PHY_AGC_CONTROL_FLTR_CAL | | 1023 | AR_PHY_AGC_CONTROL_FLTR_CAL | |
973 | AR_PHY_AGC_CONTROL_PKDET_CAL; | 1024 | AR_PHY_AGC_CONTROL_PKDET_CAL; |
974 | int i, j; | 1025 | |
975 | u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0, | 1026 | ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); |
976 | AR_PHY_CL_TAB_1, | ||
977 | AR_PHY_CL_TAB_2 }; | ||
978 | 1027 | ||
979 | if (rtt) { | 1028 | if (rtt) { |
980 | if (!ar9003_hw_rtt_restore(ah, chan)) | 1029 | if (!ar9003_hw_rtt_restore(ah, chan)) |
@@ -1012,7 +1061,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
1012 | } | 1061 | } |
1013 | } | 1062 | } |
1014 | 1063 | ||
1015 | if (!(ah->enabled_cals & TX_IQ_CAL)) | 1064 | if ((IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) || |
1065 | !(ah->enabled_cals & TX_IQ_CAL)) | ||
1016 | goto skip_tx_iqcal; | 1066 | goto skip_tx_iqcal; |
1017 | 1067 | ||
1018 | /* Do Tx IQ Calibration */ | 1068 | /* Do Tx IQ Calibration */ |
@@ -1032,21 +1082,22 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
1032 | REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, | 1082 | REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, |
1033 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); | 1083 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); |
1034 | txiqcal_done = run_agc_cal = true; | 1084 | txiqcal_done = run_agc_cal = true; |
1035 | goto skip_tx_iqcal; | 1085 | } else if (caldata && !caldata->done_txiqcal_once) { |
1036 | } else if (caldata && !caldata->done_txiqcal_once) | ||
1037 | run_agc_cal = true; | 1086 | run_agc_cal = true; |
1087 | sep_iq_cal = true; | ||
1088 | } | ||
1038 | 1089 | ||
1090 | skip_tx_iqcal: | ||
1039 | if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) | 1091 | if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) |
1040 | ar9003_mci_init_cal_req(ah, &is_reusable); | 1092 | ar9003_mci_init_cal_req(ah, &is_reusable); |
1041 | 1093 | ||
1042 | if (!(IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))) { | 1094 | if (sep_iq_cal) { |
1043 | txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); | 1095 | txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); |
1044 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); | 1096 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); |
1045 | udelay(5); | 1097 | udelay(5); |
1046 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | 1098 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); |
1047 | } | 1099 | } |
1048 | 1100 | ||
1049 | skip_tx_iqcal: | ||
1050 | if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { | 1101 | if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { |
1051 | /* Calibrate the AGC */ | 1102 | /* Calibrate the AGC */ |
1052 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | 1103 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, |
@@ -1057,14 +1108,8 @@ skip_tx_iqcal: | |||
1057 | status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | 1108 | status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, |
1058 | AR_PHY_AGC_CONTROL_CAL, | 1109 | AR_PHY_AGC_CONTROL_CAL, |
1059 | 0, AH_WAIT_TIMEOUT); | 1110 | 0, AH_WAIT_TIMEOUT); |
1060 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | 1111 | |
1061 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | 1112 | ar9003_hw_do_manual_peak_cal(ah, chan); |
1062 | if (!(ah->rxchainmask & (1 << i))) | ||
1063 | continue; | ||
1064 | ar9003_hw_manual_peak_cal(ah, i, | ||
1065 | IS_CHAN_2GHZ(chan)); | ||
1066 | } | ||
1067 | } | ||
1068 | } | 1113 | } |
1069 | 1114 | ||
1070 | if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) | 1115 | if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) |
@@ -1089,31 +1134,7 @@ skip_tx_iqcal: | |||
1089 | else if (caldata && caldata->done_txiqcal_once) | 1134 | else if (caldata && caldata->done_txiqcal_once) |
1090 | ar9003_hw_tx_iq_cal_reload(ah); | 1135 | ar9003_hw_tx_iq_cal_reload(ah); |
1091 | 1136 | ||
1092 | #define CL_TAB_ENTRY(reg_base) (reg_base + (4 * j)) | 1137 | ar9003_hw_cl_cal_post_proc(ah, is_reusable); |
1093 | if (caldata && (ah->enabled_cals & TX_CL_CAL)) { | ||
1094 | txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & | ||
1095 | AR_PHY_AGC_CONTROL_CLC_SUCCESS); | ||
1096 | if (caldata->done_txclcal_once) { | ||
1097 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
1098 | if (!(ah->txchainmask & (1 << i))) | ||
1099 | continue; | ||
1100 | for (j = 0; j < MAX_CL_TAB_ENTRY; j++) | ||
1101 | REG_WRITE(ah, CL_TAB_ENTRY(cl_idx[i]), | ||
1102 | caldata->tx_clcal[i][j]); | ||
1103 | } | ||
1104 | } else if (is_reusable && txclcal_done) { | ||
1105 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
1106 | if (!(ah->txchainmask & (1 << i))) | ||
1107 | continue; | ||
1108 | for (j = 0; j < MAX_CL_TAB_ENTRY; j++) | ||
1109 | caldata->tx_clcal[i][j] = | ||
1110 | REG_READ(ah, | ||
1111 | CL_TAB_ENTRY(cl_idx[i])); | ||
1112 | } | ||
1113 | caldata->done_txclcal_once = true; | ||
1114 | } | ||
1115 | } | ||
1116 | #undef CL_TAB_ENTRY | ||
1117 | 1138 | ||
1118 | if (run_rtt_cal && caldata) { | 1139 | if (run_rtt_cal && caldata) { |
1119 | if (is_reusable) { | 1140 | if (is_reusable) { |
@@ -1131,20 +1152,10 @@ skip_tx_iqcal: | |||
1131 | 1152 | ||
1132 | /* Initialize list pointers */ | 1153 | /* Initialize list pointers */ |
1133 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | 1154 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
1134 | ah->supp_cals = IQ_MISMATCH_CAL; | ||
1135 | |||
1136 | if (ah->supp_cals & IQ_MISMATCH_CAL) { | ||
1137 | INIT_CAL(&ah->iq_caldata); | ||
1138 | INSERT_CAL(ah, &ah->iq_caldata); | ||
1139 | ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n"); | ||
1140 | } | ||
1141 | 1155 | ||
1142 | if (ah->supp_cals & TEMP_COMP_CAL) { | 1156 | INIT_CAL(&ah->iq_caldata); |
1143 | INIT_CAL(&ah->tempCompCalData); | 1157 | INSERT_CAL(ah, &ah->iq_caldata); |
1144 | INSERT_CAL(ah, &ah->tempCompCalData); | 1158 | ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n"); |
1145 | ath_dbg(common, CALIBRATE, | ||
1146 | "enabling Temperature Compensation Calibration\n"); | ||
1147 | } | ||
1148 | 1159 | ||
1149 | /* Initialize current pointer to first element in list */ | 1160 | /* Initialize current pointer to first element in list */ |
1150 | ah->cal_list_curr = ah->cal_list; | 1161 | ah->cal_list_curr = ah->cal_list; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 562186ca9b52..881e989ea470 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -4586,14 +4586,14 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah, | |||
4586 | return 0; | 4586 | return 0; |
4587 | } | 4587 | } |
4588 | 4588 | ||
4589 | static int ar9003_hw_power_control_override(struct ath_hw *ah, | 4589 | static void ar9003_hw_power_control_override(struct ath_hw *ah, |
4590 | int frequency, | 4590 | int frequency, |
4591 | int *correction, | 4591 | int *correction, |
4592 | int *voltage, int *temperature) | 4592 | int *voltage, int *temperature) |
4593 | { | 4593 | { |
4594 | int tempSlope = 0; | 4594 | int temp_slope = 0, temp_slope1 = 0, temp_slope2 = 0; |
4595 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | 4595 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
4596 | int f[8], t[8], i; | 4596 | int f[8], t[8], t1[3], t2[3], i; |
4597 | 4597 | ||
4598 | REG_RMW(ah, AR_PHY_TPC_11_B0, | 4598 | REG_RMW(ah, AR_PHY_TPC_11_B0, |
4599 | (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), | 4599 | (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), |
@@ -4624,38 +4624,108 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah, | |||
4624 | * enable temperature compensation | 4624 | * enable temperature compensation |
4625 | * Need to use register names | 4625 | * Need to use register names |
4626 | */ | 4626 | */ |
4627 | if (frequency < 4000) | 4627 | if (frequency < 4000) { |
4628 | tempSlope = eep->modalHeader2G.tempSlope; | 4628 | temp_slope = eep->modalHeader2G.tempSlope; |
4629 | else if ((eep->baseEepHeader.miscConfiguration & 0x20) != 0) { | 4629 | } else { |
4630 | for (i = 0; i < 8; i++) { | 4630 | if (AR_SREV_9550(ah)) { |
4631 | t[i] = eep->base_ext1.tempslopextension[i]; | 4631 | t[0] = eep->base_ext1.tempslopextension[2]; |
4632 | f[i] = FBIN2FREQ(eep->calFreqPier5G[i], 0); | 4632 | t1[0] = eep->base_ext1.tempslopextension[3]; |
4633 | t2[0] = eep->base_ext1.tempslopextension[4]; | ||
4634 | f[0] = 5180; | ||
4635 | |||
4636 | t[1] = eep->modalHeader5G.tempSlope; | ||
4637 | t1[1] = eep->base_ext1.tempslopextension[0]; | ||
4638 | t2[1] = eep->base_ext1.tempslopextension[1]; | ||
4639 | f[1] = 5500; | ||
4640 | |||
4641 | t[2] = eep->base_ext1.tempslopextension[5]; | ||
4642 | t1[2] = eep->base_ext1.tempslopextension[6]; | ||
4643 | t2[2] = eep->base_ext1.tempslopextension[7]; | ||
4644 | f[2] = 5785; | ||
4645 | |||
4646 | temp_slope = ar9003_hw_power_interpolate(frequency, | ||
4647 | f, t, 3); | ||
4648 | temp_slope1 = ar9003_hw_power_interpolate(frequency, | ||
4649 | f, t1, 3); | ||
4650 | temp_slope2 = ar9003_hw_power_interpolate(frequency, | ||
4651 | f, t2, 3); | ||
4652 | |||
4653 | goto tempslope; | ||
4633 | } | 4654 | } |
4634 | tempSlope = ar9003_hw_power_interpolate((s32) frequency, | ||
4635 | f, t, 8); | ||
4636 | } else if (eep->base_ext2.tempSlopeLow != 0) { | ||
4637 | t[0] = eep->base_ext2.tempSlopeLow; | ||
4638 | f[0] = 5180; | ||
4639 | t[1] = eep->modalHeader5G.tempSlope; | ||
4640 | f[1] = 5500; | ||
4641 | t[2] = eep->base_ext2.tempSlopeHigh; | ||
4642 | f[2] = 5785; | ||
4643 | tempSlope = ar9003_hw_power_interpolate((s32) frequency, | ||
4644 | f, t, 3); | ||
4645 | } else | ||
4646 | tempSlope = eep->modalHeader5G.tempSlope; | ||
4647 | 4655 | ||
4648 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope); | 4656 | if ((eep->baseEepHeader.miscConfiguration & 0x20) != 0) { |
4657 | for (i = 0; i < 8; i++) { | ||
4658 | t[i] = eep->base_ext1.tempslopextension[i]; | ||
4659 | f[i] = FBIN2FREQ(eep->calFreqPier5G[i], 0); | ||
4660 | } | ||
4661 | temp_slope = ar9003_hw_power_interpolate((s32) frequency, | ||
4662 | f, t, 8); | ||
4663 | } else if (eep->base_ext2.tempSlopeLow != 0) { | ||
4664 | t[0] = eep->base_ext2.tempSlopeLow; | ||
4665 | f[0] = 5180; | ||
4666 | t[1] = eep->modalHeader5G.tempSlope; | ||
4667 | f[1] = 5500; | ||
4668 | t[2] = eep->base_ext2.tempSlopeHigh; | ||
4669 | f[2] = 5785; | ||
4670 | temp_slope = ar9003_hw_power_interpolate((s32) frequency, | ||
4671 | f, t, 3); | ||
4672 | } else { | ||
4673 | temp_slope = eep->modalHeader5G.tempSlope; | ||
4674 | } | ||
4675 | } | ||
4676 | |||
4677 | tempslope: | ||
4678 | if (AR_SREV_9550(ah)) { | ||
4679 | /* | ||
4680 | * AR955x has tempSlope register for each chain. | ||
4681 | * Check whether temp_compensation feature is enabled or not. | ||
4682 | */ | ||
4683 | if (eep->baseEepHeader.featureEnable & 0x1) { | ||
4684 | if (frequency < 4000) { | ||
4685 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, | ||
4686 | AR_PHY_TPC_19_ALPHA_THERM, | ||
4687 | eep->base_ext2.tempSlopeLow); | ||
4688 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, | ||
4689 | AR_PHY_TPC_19_ALPHA_THERM, | ||
4690 | temp_slope); | ||
4691 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, | ||
4692 | AR_PHY_TPC_19_ALPHA_THERM, | ||
4693 | eep->base_ext2.tempSlopeHigh); | ||
4694 | } else { | ||
4695 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, | ||
4696 | AR_PHY_TPC_19_ALPHA_THERM, | ||
4697 | temp_slope); | ||
4698 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, | ||
4699 | AR_PHY_TPC_19_ALPHA_THERM, | ||
4700 | temp_slope1); | ||
4701 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, | ||
4702 | AR_PHY_TPC_19_ALPHA_THERM, | ||
4703 | temp_slope2); | ||
4704 | } | ||
4705 | } else { | ||
4706 | /* | ||
4707 | * If temp compensation is not enabled, | ||
4708 | * set all registers to 0. | ||
4709 | */ | ||
4710 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, | ||
4711 | AR_PHY_TPC_19_ALPHA_THERM, 0); | ||
4712 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, | ||
4713 | AR_PHY_TPC_19_ALPHA_THERM, 0); | ||
4714 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2, | ||
4715 | AR_PHY_TPC_19_ALPHA_THERM, 0); | ||
4716 | } | ||
4717 | } else { | ||
4718 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, | ||
4719 | AR_PHY_TPC_19_ALPHA_THERM, temp_slope); | ||
4720 | } | ||
4649 | 4721 | ||
4650 | if (AR_SREV_9462_20(ah)) | 4722 | if (AR_SREV_9462_20(ah)) |
4651 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, | 4723 | REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, |
4652 | AR_PHY_TPC_19_B1_ALPHA_THERM, tempSlope); | 4724 | AR_PHY_TPC_19_B1_ALPHA_THERM, temp_slope); |
4653 | 4725 | ||
4654 | 4726 | ||
4655 | REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE, | 4727 | REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE, |
4656 | temperature[0]); | 4728 | temperature[0]); |
4657 | |||
4658 | return 0; | ||
4659 | } | 4729 | } |
4660 | 4730 | ||
4661 | /* Apply the recorded correction values. */ | 4731 | /* Apply the recorded correction values. */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 59bf5f31e212..a3523c969a3a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -507,28 +507,59 @@ static void ar9003_tx_gain_table_mode4(struct ath_hw *ah) | |||
507 | else if (AR_SREV_9580(ah)) | 507 | else if (AR_SREV_9580(ah)) |
508 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 508 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
509 | ar9580_1p0_mixed_ob_db_tx_gain_table); | 509 | ar9580_1p0_mixed_ob_db_tx_gain_table); |
510 | else | ||
511 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
512 | ar9300Modes_mixed_ob_db_tx_gain_table_2p2); | ||
513 | } | ||
514 | |||
515 | static void ar9003_tx_gain_table_mode5(struct ath_hw *ah) | ||
516 | { | ||
517 | if (AR_SREV_9485_11(ah)) | ||
518 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
519 | ar9485Modes_green_ob_db_tx_gain_1_1); | ||
520 | else if (AR_SREV_9340(ah)) | ||
521 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
522 | ar9340Modes_ub124_tx_gain_table_1p0); | ||
523 | else if (AR_SREV_9580(ah)) | ||
524 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
525 | ar9580_1p0_type5_tx_gain_table); | ||
526 | else if (AR_SREV_9300_22(ah)) | ||
527 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
528 | ar9300Modes_type5_tx_gain_table_2p2); | ||
510 | } | 529 | } |
511 | 530 | ||
531 | static void ar9003_tx_gain_table_mode6(struct ath_hw *ah) | ||
532 | { | ||
533 | if (AR_SREV_9340(ah)) | ||
534 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
535 | ar9340Modes_low_ob_db_and_spur_tx_gain_table_1p0); | ||
536 | else if (AR_SREV_9485_11(ah)) | ||
537 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
538 | ar9485Modes_green_spur_ob_db_tx_gain_1_1); | ||
539 | else if (AR_SREV_9580(ah)) | ||
540 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
541 | ar9580_1p0_type6_tx_gain_table); | ||
542 | } | ||
543 | |||
544 | typedef void (*ath_txgain_tab)(struct ath_hw *ah); | ||
545 | |||
512 | static void ar9003_tx_gain_table_apply(struct ath_hw *ah) | 546 | static void ar9003_tx_gain_table_apply(struct ath_hw *ah) |
513 | { | 547 | { |
514 | switch (ar9003_hw_get_tx_gain_idx(ah)) { | 548 | static const ath_txgain_tab modes[] = { |
515 | case 0: | 549 | ar9003_tx_gain_table_mode0, |
516 | default: | 550 | ar9003_tx_gain_table_mode1, |
517 | ar9003_tx_gain_table_mode0(ah); | 551 | ar9003_tx_gain_table_mode2, |
518 | break; | 552 | ar9003_tx_gain_table_mode3, |
519 | case 1: | 553 | ar9003_tx_gain_table_mode4, |
520 | ar9003_tx_gain_table_mode1(ah); | 554 | ar9003_tx_gain_table_mode5, |
521 | break; | 555 | ar9003_tx_gain_table_mode6, |
522 | case 2: | 556 | }; |
523 | ar9003_tx_gain_table_mode2(ah); | 557 | int idx = ar9003_hw_get_tx_gain_idx(ah); |
524 | break; | 558 | |
525 | case 3: | 559 | if (idx >= ARRAY_SIZE(modes)) |
526 | ar9003_tx_gain_table_mode3(ah); | 560 | idx = 0; |
527 | break; | 561 | |
528 | case 4: | 562 | modes[idx](ah); |
529 | ar9003_tx_gain_table_mode4(ah); | ||
530 | break; | ||
531 | } | ||
532 | } | 563 | } |
533 | 564 | ||
534 | static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) | 565 | static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) |
@@ -673,7 +704,7 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) | |||
673 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 704 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
674 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | 705 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); |
675 | 706 | ||
676 | priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; | 707 | ar9003_hw_init_mode_regs(ah); |
677 | priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; | 708 | priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; |
678 | 709 | ||
679 | ops->config_pci_powersave = ar9003_hw_configpcipowersave; | 710 | ops->config_pci_powersave = ar9003_hw_configpcipowersave; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index ce19c09fa8e8..2bf6548dd143 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -68,7 +68,7 @@ static const int m2ThreshExt_off = 127; | |||
68 | static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | 68 | static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) |
69 | { | 69 | { |
70 | u16 bMode, fracMode = 0, aModeRefSel = 0; | 70 | u16 bMode, fracMode = 0, aModeRefSel = 0; |
71 | u32 freq, channelSel = 0, reg32 = 0; | 71 | u32 freq, chan_frac, div, channelSel = 0, reg32 = 0; |
72 | struct chan_centers centers; | 72 | struct chan_centers centers; |
73 | int loadSynthChannel; | 73 | int loadSynthChannel; |
74 | 74 | ||
@@ -77,9 +77,6 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
77 | 77 | ||
78 | if (freq < 4800) { /* 2 GHz, fractional mode */ | 78 | if (freq < 4800) { /* 2 GHz, fractional mode */ |
79 | if (AR_SREV_9330(ah)) { | 79 | if (AR_SREV_9330(ah)) { |
80 | u32 chan_frac; | ||
81 | u32 div; | ||
82 | |||
83 | if (ah->is_clk_25mhz) | 80 | if (ah->is_clk_25mhz) |
84 | div = 75; | 81 | div = 75; |
85 | else | 82 | else |
@@ -89,34 +86,40 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
89 | chan_frac = (((freq * 4) % div) * 0x20000) / div; | 86 | chan_frac = (((freq * 4) % div) * 0x20000) / div; |
90 | channelSel = (channelSel << 17) | chan_frac; | 87 | channelSel = (channelSel << 17) | chan_frac; |
91 | } else if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) { | 88 | } else if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) { |
92 | u32 chan_frac; | ||
93 | |||
94 | /* | 89 | /* |
95 | * freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0 | 90 | * freq_ref = 40 / (refdiva >> amoderefsel); |
91 | * where refdiva=1 and amoderefsel=0 | ||
96 | * ndiv = ((chan_mhz * 4) / 3) / freq_ref; | 92 | * ndiv = ((chan_mhz * 4) / 3) / freq_ref; |
97 | * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 | 93 | * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 |
98 | */ | 94 | */ |
99 | channelSel = (freq * 4) / 120; | 95 | channelSel = (freq * 4) / 120; |
100 | chan_frac = (((freq * 4) % 120) * 0x20000) / 120; | 96 | chan_frac = (((freq * 4) % 120) * 0x20000) / 120; |
101 | channelSel = (channelSel << 17) | chan_frac; | 97 | channelSel = (channelSel << 17) | chan_frac; |
102 | } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) { | 98 | } else if (AR_SREV_9340(ah)) { |
103 | if (ah->is_clk_25mhz) { | 99 | if (ah->is_clk_25mhz) { |
104 | u32 chan_frac; | ||
105 | |||
106 | channelSel = (freq * 2) / 75; | 100 | channelSel = (freq * 2) / 75; |
107 | chan_frac = (((freq * 2) % 75) * 0x20000) / 75; | 101 | chan_frac = (((freq * 2) % 75) * 0x20000) / 75; |
108 | channelSel = (channelSel << 17) | chan_frac; | 102 | channelSel = (channelSel << 17) | chan_frac; |
109 | } else | 103 | } else { |
110 | channelSel = CHANSEL_2G(freq) >> 1; | 104 | channelSel = CHANSEL_2G(freq) >> 1; |
111 | } else | 105 | } |
106 | } else if (AR_SREV_9550(ah)) { | ||
107 | if (ah->is_clk_25mhz) | ||
108 | div = 75; | ||
109 | else | ||
110 | div = 120; | ||
111 | |||
112 | channelSel = (freq * 4) / div; | ||
113 | chan_frac = (((freq * 4) % div) * 0x20000) / div; | ||
114 | channelSel = (channelSel << 17) | chan_frac; | ||
115 | } else { | ||
112 | channelSel = CHANSEL_2G(freq); | 116 | channelSel = CHANSEL_2G(freq); |
117 | } | ||
113 | /* Set to 2G mode */ | 118 | /* Set to 2G mode */ |
114 | bMode = 1; | 119 | bMode = 1; |
115 | } else { | 120 | } else { |
116 | if ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) && | 121 | if ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) && |
117 | ah->is_clk_25mhz) { | 122 | ah->is_clk_25mhz) { |
118 | u32 chan_frac; | ||
119 | |||
120 | channelSel = freq / 75; | 123 | channelSel = freq / 75; |
121 | chan_frac = ((freq % 75) * 0x20000) / 75; | 124 | chan_frac = ((freq % 75) * 0x20000) / 75; |
122 | channelSel = (channelSel << 17) | chan_frac; | 125 | channelSel = (channelSel << 17) | chan_frac; |
@@ -586,32 +589,19 @@ static void ar9003_hw_init_bb(struct ath_hw *ah, | |||
586 | ath9k_hw_synth_delay(ah, chan, synthDelay); | 589 | ath9k_hw_synth_delay(ah, chan, synthDelay); |
587 | } | 590 | } |
588 | 591 | ||
589 | static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) | 592 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) |
590 | { | 593 | { |
591 | switch (rx) { | 594 | if (ah->caps.tx_chainmask == 5 || ah->caps.rx_chainmask == 5) |
592 | case 0x5: | ||
593 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | 595 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, |
594 | AR_PHY_SWAP_ALT_CHAIN); | 596 | AR_PHY_SWAP_ALT_CHAIN); |
595 | case 0x3: | 597 | |
596 | case 0x1: | 598 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); |
597 | case 0x2: | 599 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); |
598 | case 0x7: | ||
599 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); | ||
600 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); | ||
601 | break; | ||
602 | default: | ||
603 | break; | ||
604 | } | ||
605 | 600 | ||
606 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) | 601 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) |
607 | REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); | 602 | tx = 3; |
608 | else | ||
609 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); | ||
610 | 603 | ||
611 | if (tx == 0x5) { | 604 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); |
612 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | ||
613 | AR_PHY_SWAP_ALT_CHAIN); | ||
614 | } | ||
615 | } | 605 | } |
616 | 606 | ||
617 | /* | 607 | /* |
@@ -1450,6 +1440,67 @@ set_rfmode: | |||
1450 | return 0; | 1440 | return 0; |
1451 | } | 1441 | } |
1452 | 1442 | ||
1443 | static void ar9003_hw_spectral_scan_config(struct ath_hw *ah, | ||
1444 | struct ath_spec_scan *param) | ||
1445 | { | ||
1446 | u8 count; | ||
1447 | |||
1448 | if (!param->enabled) { | ||
1449 | REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, | ||
1450 | AR_PHY_SPECTRAL_SCAN_ENABLE); | ||
1451 | return; | ||
1452 | } | ||
1453 | |||
1454 | REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA); | ||
1455 | REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE); | ||
1456 | |||
1457 | /* on AR93xx and newer, count = 0 will make the the chip send | ||
1458 | * spectral samples endlessly. Check if this really was intended, | ||
1459 | * and fix otherwise. | ||
1460 | */ | ||
1461 | count = param->count; | ||
1462 | if (param->endless) | ||
1463 | count = 0; | ||
1464 | else if (param->count == 0) | ||
1465 | count = 1; | ||
1466 | |||
1467 | if (param->short_repeat) | ||
1468 | REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, | ||
1469 | AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT); | ||
1470 | else | ||
1471 | REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, | ||
1472 | AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT); | ||
1473 | |||
1474 | REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, | ||
1475 | AR_PHY_SPECTRAL_SCAN_COUNT, count); | ||
1476 | REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, | ||
1477 | AR_PHY_SPECTRAL_SCAN_PERIOD, param->period); | ||
1478 | REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, | ||
1479 | AR_PHY_SPECTRAL_SCAN_FFT_PERIOD, param->fft_period); | ||
1480 | |||
1481 | return; | ||
1482 | } | ||
1483 | |||
1484 | static void ar9003_hw_spectral_scan_trigger(struct ath_hw *ah) | ||
1485 | { | ||
1486 | /* Activate spectral scan */ | ||
1487 | REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, | ||
1488 | AR_PHY_SPECTRAL_SCAN_ACTIVE); | ||
1489 | } | ||
1490 | |||
1491 | static void ar9003_hw_spectral_scan_wait(struct ath_hw *ah) | ||
1492 | { | ||
1493 | struct ath_common *common = ath9k_hw_common(ah); | ||
1494 | |||
1495 | /* Poll for spectral scan complete */ | ||
1496 | if (!ath9k_hw_wait(ah, AR_PHY_SPECTRAL_SCAN, | ||
1497 | AR_PHY_SPECTRAL_SCAN_ACTIVE, | ||
1498 | 0, AH_WAIT_TIMEOUT)) { | ||
1499 | ath_err(common, "spectral scan wait failed\n"); | ||
1500 | return; | ||
1501 | } | ||
1502 | } | ||
1503 | |||
1453 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 1504 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) |
1454 | { | 1505 | { |
1455 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1506 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
@@ -1483,6 +1534,9 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
1483 | ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; | 1534 | ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; |
1484 | ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; | 1535 | ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; |
1485 | ops->antctrl_shared_chain_lnadiv = ar9003_hw_antctrl_shared_chain_lnadiv; | 1536 | ops->antctrl_shared_chain_lnadiv = ar9003_hw_antctrl_shared_chain_lnadiv; |
1537 | ops->spectral_scan_config = ar9003_hw_spectral_scan_config; | ||
1538 | ops->spectral_scan_trigger = ar9003_hw_spectral_scan_trigger; | ||
1539 | ops->spectral_scan_wait = ar9003_hw_spectral_scan_wait; | ||
1486 | 1540 | ||
1487 | ar9003_hw_set_nf_limits(ah); | 1541 | ar9003_hw_set_nf_limits(ah); |
1488 | ar9003_hw_set_radar_conf(ah); | 1542 | ar9003_hw_set_radar_conf(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 107956298488..e71774196c01 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -1028,7 +1028,7 @@ | |||
1028 | #define AR_PHY_TPC_5_B2 (AR_SM2_BASE + 0x208) | 1028 | #define AR_PHY_TPC_5_B2 (AR_SM2_BASE + 0x208) |
1029 | #define AR_PHY_TPC_6_B2 (AR_SM2_BASE + 0x20c) | 1029 | #define AR_PHY_TPC_6_B2 (AR_SM2_BASE + 0x20c) |
1030 | #define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220) | 1030 | #define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220) |
1031 | #define AR_PHY_PDADC_TAB_2 (AR_SM2_BASE + 0x240) | 1031 | #define AR_PHY_TPC_19_B2 (AR_SM2_BASE + 0x240) |
1032 | #define AR_PHY_TX_IQCAL_STATUS_B2 (AR_SM2_BASE + 0x48c) | 1032 | #define AR_PHY_TX_IQCAL_STATUS_B2 (AR_SM2_BASE + 0x48c) |
1033 | #define AR_PHY_TX_IQCAL_CORR_COEFF_B2(_i) (AR_SM2_BASE + 0x450 + ((_i) << 2)) | 1033 | #define AR_PHY_TX_IQCAL_CORR_COEFF_B2(_i) (AR_SM2_BASE + 0x450 + ((_i) << 2)) |
1034 | 1034 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h index f69d292bdc02..25db9215985a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h | |||
@@ -1172,6 +1172,106 @@ static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = { | |||
1172 | {0x00016448, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266}, | 1172 | {0x00016448, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266}, |
1173 | }; | 1173 | }; |
1174 | 1174 | ||
1175 | static const u32 ar9340Modes_low_ob_db_and_spur_tx_gain_table_1p0[][5] = { | ||
1176 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
1177 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03eaac5a, 0x03eaac5a}, | ||
1178 | {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03f330ac, 0x03f330ac}, | ||
1179 | {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc3f00, 0x03fc3f00}, | ||
1180 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ffc000, 0x03ffc000}, | ||
1181 | {0x0000a394, 0x00000444, 0x00000444, 0x00000404, 0x00000404}, | ||
1182 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | ||
1183 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1184 | {0x0000a504, 0x06000003, 0x06000003, 0x02000001, 0x02000001}, | ||
1185 | {0x0000a508, 0x0a000020, 0x0a000020, 0x05000003, 0x05000003}, | ||
1186 | {0x0000a50c, 0x10000023, 0x10000023, 0x0a000005, 0x0a000005}, | ||
1187 | {0x0000a510, 0x16000220, 0x16000220, 0x0e000201, 0x0e000201}, | ||
1188 | {0x0000a514, 0x1c000223, 0x1c000223, 0x11000203, 0x11000203}, | ||
1189 | {0x0000a518, 0x21002220, 0x21002220, 0x14000401, 0x14000401}, | ||
1190 | {0x0000a51c, 0x27002223, 0x27002223, 0x18000403, 0x18000403}, | ||
1191 | {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000602, 0x1b000602}, | ||
1192 | {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000802, 0x1f000802}, | ||
1193 | {0x0000a528, 0x34022225, 0x34022225, 0x21000620, 0x21000620}, | ||
1194 | {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x25000820, 0x25000820}, | ||
1195 | {0x0000a530, 0x3e02222c, 0x3e02222c, 0x29000822, 0x29000822}, | ||
1196 | {0x0000a534, 0x4202242a, 0x4202242a, 0x2d000824, 0x2d000824}, | ||
1197 | {0x0000a538, 0x4702244a, 0x4702244a, 0x30000828, 0x30000828}, | ||
1198 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x3400082a, 0x3400082a}, | ||
1199 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38000849, 0x38000849}, | ||
1200 | {0x0000a544, 0x5302266c, 0x5302266c, 0x3b000a2c, 0x3b000a2c}, | ||
1201 | {0x0000a548, 0x5702286c, 0x5702286c, 0x3e000e2b, 0x3e000e2b}, | ||
1202 | {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42000e2d, 0x42000e2d}, | ||
1203 | {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4500124a, 0x4500124a}, | ||
1204 | {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4900124c, 0x4900124c}, | ||
1205 | {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c00126c, 0x4c00126c}, | ||
1206 | {0x0000a55c, 0x7002708c, 0x7002708c, 0x4f00128c, 0x4f00128c}, | ||
1207 | {0x0000a560, 0x7302b08a, 0x7302b08a, 0x52001290, 0x52001290}, | ||
1208 | {0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292}, | ||
1209 | {0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292}, | ||
1210 | {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292}, | ||
1211 | {0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292}, | ||
1212 | {0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292}, | ||
1213 | {0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292}, | ||
1214 | {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292}, | ||
1215 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | ||
1216 | {0x0000a584, 0x06800003, 0x06800003, 0x02800001, 0x02800001}, | ||
1217 | {0x0000a588, 0x0a800020, 0x0a800020, 0x05800003, 0x05800003}, | ||
1218 | {0x0000a58c, 0x10800023, 0x10800023, 0x0a800005, 0x0a800005}, | ||
1219 | {0x0000a590, 0x16800220, 0x16800220, 0x0e800201, 0x0e800201}, | ||
1220 | {0x0000a594, 0x1c800223, 0x1c800223, 0x11800203, 0x11800203}, | ||
1221 | {0x0000a598, 0x21820220, 0x21820220, 0x14800401, 0x14800401}, | ||
1222 | {0x0000a59c, 0x27820223, 0x27820223, 0x18800403, 0x18800403}, | ||
1223 | {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800602, 0x1b800602}, | ||
1224 | {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800802, 0x1f800802}, | ||
1225 | {0x0000a5a8, 0x34822225, 0x34822225, 0x21800620, 0x21800620}, | ||
1226 | {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x25800820, 0x25800820}, | ||
1227 | {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x29800822, 0x29800822}, | ||
1228 | {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2d800824, 0x2d800824}, | ||
1229 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x30800828, 0x30800828}, | ||
1230 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x3480082a, 0x3480082a}, | ||
1231 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38800849, 0x38800849}, | ||
1232 | {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b800a2c, 0x3b800a2c}, | ||
1233 | {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e800e2b, 0x3e800e2b}, | ||
1234 | {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42800e2d, 0x42800e2d}, | ||
1235 | {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4580124a, 0x4580124a}, | ||
1236 | {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4980124c, 0x4980124c}, | ||
1237 | {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c80126c, 0x4c80126c}, | ||
1238 | {0x0000a5dc, 0x7086308c, 0x7086308c, 0x4f80128c, 0x4f80128c}, | ||
1239 | {0x0000a5e0, 0x738a308a, 0x738a308a, 0x52801290, 0x52801290}, | ||
1240 | {0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292}, | ||
1241 | {0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292}, | ||
1242 | {0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292}, | ||
1243 | {0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292}, | ||
1244 | {0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292}, | ||
1245 | {0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292}, | ||
1246 | {0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292}, | ||
1247 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1248 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1249 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1250 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1251 | {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1252 | {0x0000a614, 0x01404000, 0x01404000, 0x01404501, 0x01404501}, | ||
1253 | {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, | ||
1254 | {0x0000a61c, 0x02008802, 0x02008802, 0x01404501, 0x01404501}, | ||
1255 | {0x0000a620, 0x0300cc03, 0x0300cc03, 0x03c0cf02, 0x03c0cf02}, | ||
1256 | {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03c0cf03, 0x03c0cf03}, | ||
1257 | {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04011004, 0x04011004}, | ||
1258 | {0x0000a62c, 0x03810c03, 0x03810c03, 0x05419405, 0x05419405}, | ||
1259 | {0x0000a630, 0x03810e04, 0x03810e04, 0x05419506, 0x05419506}, | ||
1260 | {0x0000a634, 0x03810e04, 0x03810e04, 0x05419506, 0x05419506}, | ||
1261 | {0x0000a638, 0x03810e04, 0x03810e04, 0x05419506, 0x05419506}, | ||
1262 | {0x0000a63c, 0x03810e04, 0x03810e04, 0x05419506, 0x05419506}, | ||
1263 | {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03eaac5a, 0x03eaac5a}, | ||
1264 | {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03f330ac, 0x03f330ac}, | ||
1265 | {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc3f00, 0x03fc3f00}, | ||
1266 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ffc000, 0x03ffc000}, | ||
1267 | {0x00016044, 0x022492db, 0x022492db, 0x022492db, 0x022492db}, | ||
1268 | {0x00016048, 0x24925666, 0x24925666, 0x24925266, 0x24925266}, | ||
1269 | {0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015}, | ||
1270 | {0x00016288, 0xf0318000, 0xf0318000, 0xf0318000, 0xf0318000}, | ||
1271 | {0x00016444, 0x022492db, 0x022492db, 0x022492db, 0x022492db}, | ||
1272 | {0x00016448, 0x24925666, 0x24925666, 0x24925266, 0x24925266}, | ||
1273 | }; | ||
1274 | |||
1175 | static const u32 ar9340_1p0_mac_core[][2] = { | 1275 | static const u32 ar9340_1p0_mac_core[][2] = { |
1176 | /* Addr allmodes */ | 1276 | /* Addr allmodes */ |
1177 | {0x00000008, 0x00000000}, | 1277 | {0x00000008, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index a3710f3bb90c..712f415b8c08 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h | |||
@@ -260,6 +260,79 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { | |||
260 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, | 260 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, |
261 | }; | 261 | }; |
262 | 262 | ||
263 | static const u32 ar9485Modes_green_ob_db_tx_gain_1_1[][5] = { | ||
264 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
265 | {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003}, | ||
266 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, | ||
267 | {0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000}, | ||
268 | {0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006}, | ||
269 | {0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201}, | ||
270 | {0x0000a508, 0x0c002e00, 0x0c002e00, 0x06000203, 0x06000203}, | ||
271 | {0x0000a50c, 0x11062202, 0x11062202, 0x0a000401, 0x0a000401}, | ||
272 | {0x0000a510, 0x17022e00, 0x17022e00, 0x0e000403, 0x0e000403}, | ||
273 | {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x12000405, 0x12000405}, | ||
274 | {0x0000a518, 0x25020ec0, 0x25020ec0, 0x15000604, 0x15000604}, | ||
275 | {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x18000605, 0x18000605}, | ||
276 | {0x0000a520, 0x2f001f04, 0x2f001f04, 0x1c000a04, 0x1c000a04}, | ||
277 | {0x0000a524, 0x35001fc4, 0x35001fc4, 0x21000a06, 0x21000a06}, | ||
278 | {0x0000a528, 0x3c022f04, 0x3c022f04, 0x29000a24, 0x29000a24}, | ||
279 | {0x0000a52c, 0x41023e85, 0x41023e85, 0x2f000e21, 0x2f000e21}, | ||
280 | {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000e20, 0x31000e20}, | ||
281 | {0x0000a534, 0x4d023f01, 0x4d023f01, 0x33000e20, 0x33000e20}, | ||
282 | {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62}, | ||
283 | {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63}, | ||
284 | {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65}, | ||
285 | {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66}, | ||
286 | {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645}, | ||
287 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | ||
288 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | ||
289 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | ||
290 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, | ||
291 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | ||
292 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
293 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | ||
294 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
295 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
296 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
297 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
298 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
299 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
300 | {0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
301 | {0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
302 | {0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
303 | {0x0000b50c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
304 | {0x0000b510, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
305 | {0x0000b514, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
306 | {0x0000b518, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
307 | {0x0000b51c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
308 | {0x0000b520, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
309 | {0x0000b524, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
310 | {0x0000b528, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
311 | {0x0000b52c, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a}, | ||
312 | {0x0000b530, 0x0000003a, 0x0000003a, 0x0000003a, 0x0000003a}, | ||
313 | {0x0000b534, 0x0000004a, 0x0000004a, 0x0000004a, 0x0000004a}, | ||
314 | {0x0000b538, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
315 | {0x0000b53c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
316 | {0x0000b540, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
317 | {0x0000b544, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
318 | {0x0000b548, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
319 | {0x0000b54c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
320 | {0x0000b550, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
321 | {0x0000b554, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
322 | {0x0000b558, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
323 | {0x0000b55c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
324 | {0x0000b560, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
325 | {0x0000b564, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
326 | {0x0000b568, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
327 | {0x0000b56c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
328 | {0x0000b570, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
329 | {0x0000b574, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
330 | {0x0000b578, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
331 | {0x0000b57c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
332 | {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db}, | ||
333 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, | ||
334 | }; | ||
335 | |||
263 | static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = { | 336 | static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = { |
264 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 337 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
265 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | 338 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, |
@@ -450,6 +523,79 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { | |||
450 | 523 | ||
451 | #define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1 | 524 | #define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1 |
452 | 525 | ||
526 | static const u32 ar9485Modes_green_spur_ob_db_tx_gain_1_1[][5] = { | ||
527 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
528 | {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003}, | ||
529 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, | ||
530 | {0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000}, | ||
531 | {0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006}, | ||
532 | {0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201}, | ||
533 | {0x0000a508, 0x0c002e00, 0x0c002e00, 0x07000203, 0x07000203}, | ||
534 | {0x0000a50c, 0x11062202, 0x11062202, 0x0a000401, 0x0a000401}, | ||
535 | {0x0000a510, 0x17022e00, 0x17022e00, 0x0e000403, 0x0e000403}, | ||
536 | {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x12000405, 0x12000405}, | ||
537 | {0x0000a518, 0x25020ec0, 0x25020ec0, 0x14000406, 0x14000406}, | ||
538 | {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1800040a, 0x1800040a}, | ||
539 | {0x0000a520, 0x2f001f04, 0x2f001f04, 0x1c000460, 0x1c000460}, | ||
540 | {0x0000a524, 0x35001fc4, 0x35001fc4, 0x22000463, 0x22000463}, | ||
541 | {0x0000a528, 0x3c022f04, 0x3c022f04, 0x26000465, 0x26000465}, | ||
542 | {0x0000a52c, 0x41023e85, 0x41023e85, 0x2e0006e0, 0x2e0006e0}, | ||
543 | {0x0000a530, 0x48023ec6, 0x48023ec6, 0x310006e0, 0x310006e0}, | ||
544 | {0x0000a534, 0x4d023f01, 0x4d023f01, 0x330006e0, 0x330006e0}, | ||
545 | {0x0000a538, 0x53023f4b, 0x53023f4b, 0x3e0008e3, 0x3e0008e3}, | ||
546 | {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x410008e5, 0x410008e5}, | ||
547 | {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x430008e6, 0x430008e6}, | ||
548 | {0x0000a544, 0x6502feca, 0x6502feca, 0x4a0008ec, 0x4a0008ec}, | ||
549 | {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4e0008f1, 0x4e0008f1}, | ||
550 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x520008f3, 0x520008f3}, | ||
551 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x54000eed, 0x54000eed}, | ||
552 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x58000ef1, 0x58000ef1}, | ||
553 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5c000ef3, 0x5c000ef3}, | ||
554 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x60000ef5, 0x60000ef5}, | ||
555 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x62000ef6, 0x62000ef6}, | ||
556 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x62000ef6, 0x62000ef6}, | ||
557 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | ||
558 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | ||
559 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | ||
560 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | ||
561 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | ||
562 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | ||
563 | {0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
564 | {0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
565 | {0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
566 | {0x0000b50c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
567 | {0x0000b510, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
568 | {0x0000b514, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
569 | {0x0000b518, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
570 | {0x0000b51c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
571 | {0x0000b520, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
572 | {0x0000b524, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
573 | {0x0000b528, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
574 | {0x0000b52c, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a}, | ||
575 | {0x0000b530, 0x0000003a, 0x0000003a, 0x0000003a, 0x0000003a}, | ||
576 | {0x0000b534, 0x0000004a, 0x0000004a, 0x0000004a, 0x0000004a}, | ||
577 | {0x0000b538, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
578 | {0x0000b53c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
579 | {0x0000b540, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
580 | {0x0000b544, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
581 | {0x0000b548, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
582 | {0x0000b54c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
583 | {0x0000b550, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
584 | {0x0000b554, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
585 | {0x0000b558, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
586 | {0x0000b55c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
587 | {0x0000b560, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
588 | {0x0000b564, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
589 | {0x0000b568, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
590 | {0x0000b56c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
591 | {0x0000b570, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
592 | {0x0000b574, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
593 | {0x0000b578, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
594 | {0x0000b57c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
595 | {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db}, | ||
596 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, | ||
597 | }; | ||
598 | |||
453 | static const u32 ar9485_1_1[][2] = { | 599 | static const u32 ar9485_1_1[][2] = { |
454 | /* Addr allmodes */ | 600 | /* Addr allmodes */ |
455 | {0x0000a580, 0x00000000}, | 601 | {0x0000a580, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h index df97f21c52dc..ccc5b6c99add 100644 --- a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h | |||
@@ -23,16 +23,16 @@ | |||
23 | static const u32 ar955x_1p0_radio_postamble[][5] = { | 23 | static const u32 ar955x_1p0_radio_postamble[][5] = { |
24 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 24 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
25 | {0x00016098, 0xd2dd5554, 0xd2dd5554, 0xd28b3330, 0xd28b3330}, | 25 | {0x00016098, 0xd2dd5554, 0xd2dd5554, 0xd28b3330, 0xd28b3330}, |
26 | {0x0001609c, 0x0a566f3a, 0x0a566f3a, 0x06345f2a, 0x06345f2a}, | 26 | {0x0001609c, 0x0a566f3a, 0x0a566f3a, 0x0a566f3a, 0x0a566f3a}, |
27 | {0x000160ac, 0xa4647c00, 0xa4647c00, 0xa4646800, 0xa4646800}, | 27 | {0x000160ac, 0xa4647c00, 0xa4647c00, 0x24647c00, 0x24647c00}, |
28 | {0x000160b0, 0x01885f52, 0x01885f52, 0x04accf3a, 0x04accf3a}, | 28 | {0x000160b0, 0x01885f52, 0x01885f52, 0x01885f52, 0x01885f52}, |
29 | {0x00016104, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001}, | 29 | {0x00016104, 0xb7a00000, 0xb7a00000, 0xb7a00001, 0xb7a00001}, |
30 | {0x0001610c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000}, | 30 | {0x0001610c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000}, |
31 | {0x00016140, 0x10804008, 0x10804008, 0x10804008, 0x10804008}, | 31 | {0x00016140, 0x10804008, 0x10804008, 0x10804008, 0x10804008}, |
32 | {0x00016504, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001}, | 32 | {0x00016504, 0xb7a00000, 0xb7a00000, 0xb7a00001, 0xb7a00001}, |
33 | {0x0001650c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000}, | 33 | {0x0001650c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000}, |
34 | {0x00016540, 0x10804008, 0x10804008, 0x10804008, 0x10804008}, | 34 | {0x00016540, 0x10804008, 0x10804008, 0x10804008, 0x10804008}, |
35 | {0x00016904, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001}, | 35 | {0x00016904, 0xb7a00000, 0xb7a00000, 0xb7a00001, 0xb7a00001}, |
36 | {0x0001690c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000}, | 36 | {0x0001690c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000}, |
37 | {0x00016940, 0x10804008, 0x10804008, 0x10804008, 0x10804008}, | 37 | {0x00016940, 0x10804008, 0x10804008, 0x10804008, 0x10804008}, |
38 | }; | 38 | }; |
@@ -69,15 +69,15 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = { | |||
69 | {0x0000a204, 0x005c0ec0, 0x005c0ec4, 0x005c0ec4, 0x005c0ec0}, | 69 | {0x0000a204, 0x005c0ec0, 0x005c0ec4, 0x005c0ec4, 0x005c0ec0}, |
70 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, | 70 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, |
71 | {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f}, | 71 | {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f}, |
72 | {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, | 72 | {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, |
73 | {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, | 73 | {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, |
74 | {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018}, | 74 | {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018}, |
75 | {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, | 75 | {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, |
76 | {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, | 76 | {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, |
77 | {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, | 77 | {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, |
78 | {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, | 78 | {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01010e0e, 0x01010e0e}, |
79 | {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, | 79 | {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, |
80 | {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, | 80 | {0x0000a264, 0x00000e0e, 0x00000e0e, 0x01000e0e, 0x01000e0e}, |
81 | {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, | 81 | {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, |
82 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, | 82 | {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, |
83 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, | 83 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, |
@@ -125,7 +125,7 @@ static const u32 ar955x_1p0_radio_core[][2] = { | |||
125 | {0x00016094, 0x00000000}, | 125 | {0x00016094, 0x00000000}, |
126 | {0x000160a0, 0x0a108ffe}, | 126 | {0x000160a0, 0x0a108ffe}, |
127 | {0x000160a4, 0x812fc370}, | 127 | {0x000160a4, 0x812fc370}, |
128 | {0x000160a8, 0x423c8000}, | 128 | {0x000160a8, 0x423c8100}, |
129 | {0x000160b4, 0x92480080}, | 129 | {0x000160b4, 0x92480080}, |
130 | {0x000160c0, 0x006db6d0}, | 130 | {0x000160c0, 0x006db6d0}, |
131 | {0x000160c4, 0x6db6db60}, | 131 | {0x000160c4, 0x6db6db60}, |
@@ -134,7 +134,7 @@ static const u32 ar955x_1p0_radio_core[][2] = { | |||
134 | {0x00016100, 0x11999601}, | 134 | {0x00016100, 0x11999601}, |
135 | {0x00016108, 0x00080010}, | 135 | {0x00016108, 0x00080010}, |
136 | {0x00016144, 0x02084080}, | 136 | {0x00016144, 0x02084080}, |
137 | {0x00016148, 0x000080c0}, | 137 | {0x00016148, 0x00008040}, |
138 | {0x00016280, 0x01800804}, | 138 | {0x00016280, 0x01800804}, |
139 | {0x00016284, 0x00038dc5}, | 139 | {0x00016284, 0x00038dc5}, |
140 | {0x00016288, 0x00000000}, | 140 | {0x00016288, 0x00000000}, |
@@ -178,7 +178,7 @@ static const u32 ar955x_1p0_radio_core[][2] = { | |||
178 | {0x00016500, 0x11999601}, | 178 | {0x00016500, 0x11999601}, |
179 | {0x00016508, 0x00080010}, | 179 | {0x00016508, 0x00080010}, |
180 | {0x00016544, 0x02084080}, | 180 | {0x00016544, 0x02084080}, |
181 | {0x00016548, 0x000080c0}, | 181 | {0x00016548, 0x00008040}, |
182 | {0x00016780, 0x00000000}, | 182 | {0x00016780, 0x00000000}, |
183 | {0x00016784, 0x00000000}, | 183 | {0x00016784, 0x00000000}, |
184 | {0x00016788, 0x00400705}, | 184 | {0x00016788, 0x00400705}, |
@@ -218,7 +218,7 @@ static const u32 ar955x_1p0_radio_core[][2] = { | |||
218 | {0x00016900, 0x11999601}, | 218 | {0x00016900, 0x11999601}, |
219 | {0x00016908, 0x00080010}, | 219 | {0x00016908, 0x00080010}, |
220 | {0x00016944, 0x02084080}, | 220 | {0x00016944, 0x02084080}, |
221 | {0x00016948, 0x000080c0}, | 221 | {0x00016948, 0x00008040}, |
222 | {0x00016b80, 0x00000000}, | 222 | {0x00016b80, 0x00000000}, |
223 | {0x00016b84, 0x00000000}, | 223 | {0x00016b84, 0x00000000}, |
224 | {0x00016b88, 0x00400705}, | 224 | {0x00016b88, 0x00400705}, |
@@ -245,9 +245,9 @@ static const u32 ar955x_1p0_radio_core[][2] = { | |||
245 | 245 | ||
246 | static const u32 ar955x_1p0_modes_xpa_tx_gain_table[][9] = { | 246 | static const u32 ar955x_1p0_modes_xpa_tx_gain_table[][9] = { |
247 | /* Addr 5G_HT20_L 5G_HT40_L 5G_HT20_M 5G_HT40_M 5G_HT20_H 5G_HT40_H 2G_HT40 2G_HT20 */ | 247 | /* Addr 5G_HT20_L 5G_HT40_L 5G_HT20_M 5G_HT40_M 5G_HT20_H 5G_HT40_H 2G_HT40 2G_HT20 */ |
248 | {0x0000a2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa}, | 248 | {0x0000a2dc, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xfffd5aaa, 0xfffd5aaa}, |
249 | {0x0000a2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc}, | 249 | {0x0000a2e0, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffe9ccc, 0xfffe9ccc}, |
250 | {0x0000a2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0}, | 250 | {0x0000a2e4, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffffe0f0, 0xffffe0f0}, |
251 | {0x0000a2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00}, | 251 | {0x0000a2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00}, |
252 | {0x0000a410, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050da, 0x000050da}, | 252 | {0x0000a410, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050da, 0x000050da}, |
253 | {0x0000a500, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000000, 0x00000000}, | 253 | {0x0000a500, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000000, 0x00000000}, |
@@ -256,63 +256,63 @@ static const u32 ar955x_1p0_modes_xpa_tx_gain_table[][9] = { | |||
256 | {0x0000a50c, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c000006, 0x0c000006}, | 256 | {0x0000a50c, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c000006, 0x0c000006}, |
257 | {0x0000a510, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x0f00000a, 0x0f00000a}, | 257 | {0x0000a510, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x0f00000a, 0x0f00000a}, |
258 | {0x0000a514, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x1300000c, 0x1300000c}, | 258 | {0x0000a514, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x1300000c, 0x1300000c}, |
259 | {0x0000a518, 0x19004008, 0x19004008, 0x19004008, 0x19004008, 0x18004008, 0x18004008, 0x1700000e, 0x1700000e}, | 259 | {0x0000a518, 0x1700002b, 0x1700002b, 0x1700002b, 0x1700002b, 0x1600002b, 0x1600002b, 0x1700000e, 0x1700000e}, |
260 | {0x0000a51c, 0x1d00400a, 0x1d00400a, 0x1d00400a, 0x1d00400a, 0x1c00400a, 0x1c00400a, 0x1b000064, 0x1b000064}, | 260 | {0x0000a51c, 0x1b00002d, 0x1b00002d, 0x1b00002d, 0x1b00002d, 0x1a00002d, 0x1a00002d, 0x1b000064, 0x1b000064}, |
261 | {0x0000a520, 0x230020a2, 0x230020a2, 0x210020a2, 0x210020a2, 0x200020a2, 0x200020a2, 0x1f000242, 0x1f000242}, | 261 | {0x0000a520, 0x20000031, 0x20000031, 0x1f000031, 0x1f000031, 0x1e000031, 0x1e000031, 0x1f000242, 0x1f000242}, |
262 | {0x0000a524, 0x2500006e, 0x2500006e, 0x2500006e, 0x2500006e, 0x2400006e, 0x2400006e, 0x23000229, 0x23000229}, | 262 | {0x0000a524, 0x24000051, 0x24000051, 0x23000051, 0x23000051, 0x23000051, 0x23000051, 0x23000229, 0x23000229}, |
263 | {0x0000a528, 0x29022221, 0x29022221, 0x28022221, 0x28022221, 0x27022221, 0x27022221, 0x270002a2, 0x270002a2}, | 263 | {0x0000a528, 0x27000071, 0x27000071, 0x27000071, 0x27000071, 0x26000071, 0x26000071, 0x270002a2, 0x270002a2}, |
264 | {0x0000a52c, 0x2d00062a, 0x2d00062a, 0x2c00062a, 0x2c00062a, 0x2a00062a, 0x2a00062a, 0x2c001203, 0x2c001203}, | 264 | {0x0000a52c, 0x2b000092, 0x2b000092, 0x2b000092, 0x2b000092, 0x2b000092, 0x2b000092, 0x2c001203, 0x2c001203}, |
265 | {0x0000a530, 0x340220a5, 0x340220a5, 0x320220a5, 0x320220a5, 0x2f0220a5, 0x2f0220a5, 0x30001803, 0x30001803}, | 265 | {0x0000a530, 0x3000028c, 0x3000028c, 0x2f00028c, 0x2f00028c, 0x2e00028c, 0x2e00028c, 0x30001803, 0x30001803}, |
266 | {0x0000a534, 0x380022c5, 0x380022c5, 0x350022c5, 0x350022c5, 0x320022c5, 0x320022c5, 0x33000881, 0x33000881}, | 266 | {0x0000a534, 0x34000290, 0x34000290, 0x33000290, 0x33000290, 0x32000290, 0x32000290, 0x33000881, 0x33000881}, |
267 | {0x0000a538, 0x3b002486, 0x3b002486, 0x39002486, 0x39002486, 0x36002486, 0x36002486, 0x38001809, 0x38001809}, | 267 | {0x0000a538, 0x37000292, 0x37000292, 0x36000292, 0x36000292, 0x35000292, 0x35000292, 0x38001809, 0x38001809}, |
268 | {0x0000a53c, 0x3f00248a, 0x3f00248a, 0x3d00248a, 0x3d00248a, 0x3a00248a, 0x3a00248a, 0x3a000814, 0x3a000814}, | 268 | {0x0000a53c, 0x3b02028d, 0x3b02028d, 0x3a02028d, 0x3a02028d, 0x3902028d, 0x3902028d, 0x3a000814, 0x3a000814}, |
269 | {0x0000a540, 0x4202242c, 0x4202242c, 0x4102242c, 0x4102242c, 0x3f02242c, 0x3f02242c, 0x3f001a0c, 0x3f001a0c}, | 269 | {0x0000a540, 0x3f020291, 0x3f020291, 0x3e020291, 0x3e020291, 0x3d020291, 0x3d020291, 0x3f001a0c, 0x3f001a0c}, |
270 | {0x0000a544, 0x490044c6, 0x490044c6, 0x460044c6, 0x460044c6, 0x420044c6, 0x420044c6, 0x43001a0e, 0x43001a0e}, | 270 | {0x0000a544, 0x44020490, 0x44020490, 0x43020490, 0x43020490, 0x42020490, 0x42020490, 0x43001a0e, 0x43001a0e}, |
271 | {0x0000a548, 0x4d024485, 0x4d024485, 0x4a024485, 0x4a024485, 0x46024485, 0x46024485, 0x46001812, 0x46001812}, | 271 | {0x0000a548, 0x48020492, 0x48020492, 0x47020492, 0x47020492, 0x46020492, 0x46020492, 0x46001812, 0x46001812}, |
272 | {0x0000a54c, 0x51044483, 0x51044483, 0x4e044483, 0x4e044483, 0x4a044483, 0x4a044483, 0x49001884, 0x49001884}, | 272 | {0x0000a54c, 0x4c020692, 0x4c020692, 0x4b020692, 0x4b020692, 0x4a020692, 0x4a020692, 0x49001884, 0x49001884}, |
273 | {0x0000a550, 0x5404a40c, 0x5404a40c, 0x5204a40c, 0x5204a40c, 0x4d04a40c, 0x4d04a40c, 0x4d001e84, 0x4d001e84}, | 273 | {0x0000a550, 0x50020892, 0x50020892, 0x4f020892, 0x4f020892, 0x4e020892, 0x4e020892, 0x4d001e84, 0x4d001e84}, |
274 | {0x0000a554, 0x57024632, 0x57024632, 0x55024632, 0x55024632, 0x52024632, 0x52024632, 0x50001e69, 0x50001e69}, | 274 | {0x0000a554, 0x53040891, 0x53040891, 0x53040891, 0x53040891, 0x52040891, 0x52040891, 0x50001e69, 0x50001e69}, |
275 | {0x0000a558, 0x5c00a634, 0x5c00a634, 0x5900a634, 0x5900a634, 0x5600a634, 0x5600a634, 0x550006f4, 0x550006f4}, | 275 | {0x0000a558, 0x58040893, 0x58040893, 0x57040893, 0x57040893, 0x56040893, 0x56040893, 0x550006f4, 0x550006f4}, |
276 | {0x0000a55c, 0x5f026832, 0x5f026832, 0x5d026832, 0x5d026832, 0x5a026832, 0x5a026832, 0x59000ad3, 0x59000ad3}, | 276 | {0x0000a55c, 0x5c0408b4, 0x5c0408b4, 0x5a0408b4, 0x5a0408b4, 0x5a0408b4, 0x5a0408b4, 0x59000ad3, 0x59000ad3}, |
277 | {0x0000a560, 0x6602b012, 0x6602b012, 0x6202b012, 0x6202b012, 0x5d02b012, 0x5d02b012, 0x5e000ad5, 0x5e000ad5}, | 277 | {0x0000a560, 0x610408b6, 0x610408b6, 0x5e0408b6, 0x5e0408b6, 0x5e0408b6, 0x5e0408b6, 0x5e000ad5, 0x5e000ad5}, |
278 | {0x0000a564, 0x6e02d0e1, 0x6e02d0e1, 0x6802d0e1, 0x6802d0e1, 0x6002d0e1, 0x6002d0e1, 0x61001ced, 0x61001ced}, | 278 | {0x0000a564, 0x670408f6, 0x670408f6, 0x620408f6, 0x620408f6, 0x620408f6, 0x620408f6, 0x61001ced, 0x61001ced}, |
279 | {0x0000a568, 0x7202b4c4, 0x7202b4c4, 0x6c02b4c4, 0x6c02b4c4, 0x6502b4c4, 0x6502b4c4, 0x660018d4, 0x660018d4}, | 279 | {0x0000a568, 0x6a040cf6, 0x6a040cf6, 0x66040cf6, 0x66040cf6, 0x66040cf6, 0x66040cf6, 0x660018d4, 0x660018d4}, |
280 | {0x0000a56c, 0x75007894, 0x75007894, 0x70007894, 0x70007894, 0x6b007894, 0x6b007894, 0x660018d4, 0x660018d4}, | 280 | {0x0000a56c, 0x6d040d76, 0x6d040d76, 0x6a040d76, 0x6a040d76, 0x6a040d76, 0x6a040d76, 0x660018d4, 0x660018d4}, |
281 | {0x0000a570, 0x7b025c74, 0x7b025c74, 0x75025c74, 0x75025c74, 0x70025c74, 0x70025c74, 0x660018d4, 0x660018d4}, | 281 | {0x0000a570, 0x70060db6, 0x70060db6, 0x6e060db6, 0x6e060db6, 0x6e060db6, 0x6e060db6, 0x660018d4, 0x660018d4}, |
282 | {0x0000a574, 0x8300bcb5, 0x8300bcb5, 0x7a00bcb5, 0x7a00bcb5, 0x7600bcb5, 0x7600bcb5, 0x660018d4, 0x660018d4}, | 282 | {0x0000a574, 0x730a0df6, 0x730a0df6, 0x720a0df6, 0x720a0df6, 0x720a0df6, 0x720a0df6, 0x660018d4, 0x660018d4}, |
283 | {0x0000a578, 0x8a04dc74, 0x8a04dc74, 0x7f04dc74, 0x7f04dc74, 0x7c04dc74, 0x7c04dc74, 0x660018d4, 0x660018d4}, | 283 | {0x0000a578, 0x770a13f6, 0x770a13f6, 0x760a13f6, 0x760a13f6, 0x760a13f6, 0x760a13f6, 0x660018d4, 0x660018d4}, |
284 | {0x0000a57c, 0x8a04dc74, 0x8a04dc74, 0x7f04dc74, 0x7f04dc74, 0x7c04dc74, 0x7c04dc74, 0x660018d4, 0x660018d4}, | 284 | {0x0000a57c, 0x770a13f6, 0x770a13f6, 0x760a13f6, 0x760a13f6, 0x760a13f6, 0x760a13f6, 0x660018d4, 0x660018d4}, |
285 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 285 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
286 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 286 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
287 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 287 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
288 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x03804000, 0x03804000}, | 288 | {0x0000a60c, 0x02c04b01, 0x02c04b01, 0x02c04b01, 0x02c04b01, 0x02c04b01, 0x02c04b01, 0x03804000, 0x03804000}, |
289 | {0x0000a610, 0x04c08c01, 0x04c08c01, 0x04808b01, 0x04808b01, 0x04808a01, 0x04808a01, 0x0300ca02, 0x0300ca02}, | 289 | {0x0000a610, 0x04008b01, 0x04008b01, 0x04008b01, 0x04008b01, 0x03c08b01, 0x03c08b01, 0x0300ca02, 0x0300ca02}, |
290 | {0x0000a614, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00000e04, 0x00000e04}, | 290 | {0x0000a614, 0x05811403, 0x05811403, 0x05411303, 0x05411303, 0x05411303, 0x05411303, 0x00000e04, 0x00000e04}, |
291 | {0x0000a618, 0x04010c01, 0x04010c01, 0x03c10b01, 0x03c10b01, 0x03810a01, 0x03810a01, 0x03014000, 0x03014000}, | 291 | {0x0000a618, 0x05811604, 0x05811604, 0x05411504, 0x05411504, 0x05411504, 0x05411504, 0x03014000, 0x03014000}, |
292 | {0x0000a61c, 0x03814e05, 0x03814e05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03414d05, 0x00000000, 0x00000000}, | 292 | {0x0000a61c, 0x05811604, 0x05811604, 0x05411504, 0x05411504, 0x05411504, 0x05411504, 0x00000000, 0x00000000}, |
293 | {0x0000a620, 0x04010303, 0x04010303, 0x03c10303, 0x03c10303, 0x03810303, 0x03810303, 0x00000000, 0x00000000}, | 293 | {0x0000a620, 0x05811604, 0x05811604, 0x05411504, 0x05411504, 0x05411504, 0x05411504, 0x00000000, 0x00000000}, |
294 | {0x0000a624, 0x03814e05, 0x03814e05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03014000, 0x03014000}, | 294 | {0x0000a624, 0x05811604, 0x05811604, 0x05411504, 0x05411504, 0x05411504, 0x05411504, 0x03014000, 0x03014000}, |
295 | {0x0000a628, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x03804c05, 0x03804c05}, | 295 | {0x0000a628, 0x05811604, 0x05811604, 0x05411504, 0x05411504, 0x05411504, 0x05411504, 0x03804c05, 0x03804c05}, |
296 | {0x0000a62c, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x0701de06, 0x0701de06}, | 296 | {0x0000a62c, 0x06815604, 0x06815604, 0x06415504, 0x06415504, 0x06015504, 0x06015504, 0x0701de06, 0x0701de06}, |
297 | {0x0000a630, 0x03418000, 0x03418000, 0x03018000, 0x03018000, 0x02c18000, 0x02c18000, 0x07819c07, 0x07819c07}, | 297 | {0x0000a630, 0x07819a05, 0x07819a05, 0x07419905, 0x07419905, 0x07019805, 0x07019805, 0x07819c07, 0x07819c07}, |
298 | {0x0000a634, 0x03815004, 0x03815004, 0x03414f04, 0x03414f04, 0x03414e04, 0x03414e04, 0x0701dc07, 0x0701dc07}, | 298 | {0x0000a634, 0x07819e06, 0x07819e06, 0x07419d06, 0x07419d06, 0x07019c06, 0x07019c06, 0x0701dc07, 0x0701dc07}, |
299 | {0x0000a638, 0x03005302, 0x03005302, 0x02c05202, 0x02c05202, 0x02805202, 0x02805202, 0x0701dc07, 0x0701dc07}, | 299 | {0x0000a638, 0x07819e06, 0x07819e06, 0x07419d06, 0x07419d06, 0x07019c06, 0x07019c06, 0x0701dc07, 0x0701dc07}, |
300 | {0x0000a63c, 0x04c09302, 0x04c09302, 0x04809202, 0x04809202, 0x04809202, 0x04809202, 0x0701dc07, 0x0701dc07}, | 300 | {0x0000a63c, 0x07819e06, 0x07819e06, 0x07419d06, 0x07419d06, 0x07019c06, 0x07019c06, 0x0701dc07, 0x0701dc07}, |
301 | {0x0000b2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa}, | 301 | {0x0000b2dc, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xfffd5aaa, 0xfffd5aaa}, |
302 | {0x0000b2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc}, | 302 | {0x0000b2e0, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffe9ccc, 0xfffe9ccc}, |
303 | {0x0000b2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0}, | 303 | {0x0000b2e4, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffffe0f0, 0xffffe0f0}, |
304 | {0x0000b2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00}, | 304 | {0x0000b2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00}, |
305 | {0x0000c2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa}, | 305 | {0x0000c2dc, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xfffd5aaa, 0xfffd5aaa}, |
306 | {0x0000c2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc}, | 306 | {0x0000c2e0, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffe9ccc, 0xfffe9ccc}, |
307 | {0x0000c2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0}, | 307 | {0x0000c2e4, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffffe0f0, 0xffffe0f0}, |
308 | {0x0000c2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00}, | 308 | {0x0000c2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00}, |
309 | {0x00016044, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4}, | 309 | {0x00016044, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4}, |
310 | {0x00016048, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401}, | 310 | {0x00016048, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401}, |
311 | {0x00016280, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01808e84, 0x01808e84}, | 311 | {0x00016280, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01808e84, 0x01808e84}, |
312 | {0x00016444, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4}, | 312 | {0x00016444, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4}, |
313 | {0x00016448, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401}, | 313 | {0x00016448, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401}, |
314 | {0x00016844, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4}, | 314 | {0x00016844, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4}, |
315 | {0x00016848, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401}, | 315 | {0x00016848, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401}, |
316 | }; | 316 | }; |
317 | 317 | ||
318 | static const u32 ar955x_1p0_mac_core[][2] = { | 318 | static const u32 ar955x_1p0_mac_core[][2] = { |
@@ -846,7 +846,7 @@ static const u32 ar955x_1p0_baseband_core[][2] = { | |||
846 | {0x0000a44c, 0x00000001}, | 846 | {0x0000a44c, 0x00000001}, |
847 | {0x0000a450, 0x00010000}, | 847 | {0x0000a450, 0x00010000}, |
848 | {0x0000a458, 0x00000000}, | 848 | {0x0000a458, 0x00000000}, |
849 | {0x0000a644, 0x3fad9d74}, | 849 | {0x0000a644, 0xbfad9d74}, |
850 | {0x0000a648, 0x0048060a}, | 850 | {0x0000a648, 0x0048060a}, |
851 | {0x0000a64c, 0x00003c37}, | 851 | {0x0000a64c, 0x00003c37}, |
852 | {0x0000a670, 0x03020100}, | 852 | {0x0000a670, 0x03020100}, |
@@ -1277,7 +1277,7 @@ static const u32 ar955x_1p0_modes_fast_clock[][3] = { | |||
1277 | {0x0000801c, 0x148ec02b, 0x148ec057}, | 1277 | {0x0000801c, 0x148ec02b, 0x148ec057}, |
1278 | {0x00008318, 0x000044c0, 0x00008980}, | 1278 | {0x00008318, 0x000044c0, 0x00008980}, |
1279 | {0x00009e00, 0x0372131c, 0x0372131c}, | 1279 | {0x00009e00, 0x0372131c, 0x0372131c}, |
1280 | {0x0000a230, 0x0000000b, 0x00000016}, | 1280 | {0x0000a230, 0x0000400b, 0x00004016}, |
1281 | {0x0000a254, 0x00000898, 0x00001130}, | 1281 | {0x0000a254, 0x00000898, 0x00001130}, |
1282 | }; | 1282 | }; |
1283 | 1283 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h index 6e1915aee712..28fd99203f64 100644 --- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h | |||
@@ -685,6 +685,82 @@ static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = { | |||
685 | 685 | ||
686 | #define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2 | 686 | #define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2 |
687 | 687 | ||
688 | #define ar9580_1p0_type5_tx_gain_table ar9300Modes_type5_tx_gain_table_2p2 | ||
689 | |||
690 | static const u32 ar9580_1p0_type6_tx_gain_table[][5] = { | ||
691 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
692 | {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | ||
693 | {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | ||
694 | {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | ||
695 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
696 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | ||
697 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
698 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | ||
699 | {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, | ||
700 | {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, | ||
701 | {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, | ||
702 | {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, | ||
703 | {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, | ||
704 | {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, | ||
705 | {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, | ||
706 | {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, | ||
707 | {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, | ||
708 | {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, | ||
709 | {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, | ||
710 | {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, | ||
711 | {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, | ||
712 | {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, | ||
713 | {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, | ||
714 | {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, | ||
715 | {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, | ||
716 | {0x0000a54c, 0x5e08442e, 0x5e08442e, 0x47001a83, 0x47001a83}, | ||
717 | {0x0000a550, 0x620a4431, 0x620a4431, 0x4a001c84, 0x4a001c84}, | ||
718 | {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, | ||
719 | {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, | ||
720 | {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, | ||
721 | {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, | ||
722 | {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
723 | {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
724 | {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
725 | {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
726 | {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
727 | {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
728 | {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | ||
729 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
730 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
731 | {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | ||
732 | {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | ||
733 | {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | ||
734 | {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, | ||
735 | {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, | ||
736 | {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, | ||
737 | {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, | ||
738 | {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, | ||
739 | {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, | ||
740 | {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
741 | {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
742 | {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
743 | {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
744 | {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | ||
745 | {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | ||
746 | {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | ||
747 | {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | ||
748 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
749 | {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | ||
750 | {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | ||
751 | {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | ||
752 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
753 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
754 | {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, | ||
755 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
756 | {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
757 | {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, | ||
758 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
759 | {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
760 | {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, | ||
761 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
762 | }; | ||
763 | |||
688 | static const u32 ar9580_1p0_soc_preamble[][2] = { | 764 | static const u32 ar9580_1p0_soc_preamble[][2] = { |
689 | /* Addr allmodes */ | 765 | /* Addr allmodes */ |
690 | {0x000040a4, 0x00a0c1c9}, | 766 | {0x000040a4, 0x00a0c1c9}, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 86e26a19efda..b2d6c18d1678 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -109,14 +109,11 @@ struct ath_descdma { | |||
109 | void *dd_desc; | 109 | void *dd_desc; |
110 | dma_addr_t dd_desc_paddr; | 110 | dma_addr_t dd_desc_paddr; |
111 | u32 dd_desc_len; | 111 | u32 dd_desc_len; |
112 | struct ath_buf *dd_bufptr; | ||
113 | }; | 112 | }; |
114 | 113 | ||
115 | int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | 114 | int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, |
116 | struct list_head *head, const char *name, | 115 | struct list_head *head, const char *name, |
117 | int nbuf, int ndesc, bool is_tx); | 116 | int nbuf, int ndesc, bool is_tx); |
118 | void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | ||
119 | struct list_head *head); | ||
120 | 117 | ||
121 | /***********/ | 118 | /***********/ |
122 | /* RX / TX */ | 119 | /* RX / TX */ |
@@ -317,10 +314,8 @@ struct ath_rx { | |||
317 | u32 *rxlink; | 314 | u32 *rxlink; |
318 | u32 num_pkts; | 315 | u32 num_pkts; |
319 | unsigned int rxfilter; | 316 | unsigned int rxfilter; |
320 | spinlock_t rxbuflock; | ||
321 | struct list_head rxbuf; | 317 | struct list_head rxbuf; |
322 | struct ath_descdma rxdma; | 318 | struct ath_descdma rxdma; |
323 | struct ath_buf *rx_bufptr; | ||
324 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; | 319 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; |
325 | 320 | ||
326 | struct sk_buff *frag; | 321 | struct sk_buff *frag; |
@@ -328,7 +323,6 @@ struct ath_rx { | |||
328 | 323 | ||
329 | int ath_startrecv(struct ath_softc *sc); | 324 | int ath_startrecv(struct ath_softc *sc); |
330 | bool ath_stoprecv(struct ath_softc *sc); | 325 | bool ath_stoprecv(struct ath_softc *sc); |
331 | void ath_flushrecv(struct ath_softc *sc); | ||
332 | u32 ath_calcrxfilter(struct ath_softc *sc); | 326 | u32 ath_calcrxfilter(struct ath_softc *sc); |
333 | int ath_rx_init(struct ath_softc *sc, int nbufs); | 327 | int ath_rx_init(struct ath_softc *sc, int nbufs); |
334 | void ath_rx_cleanup(struct ath_softc *sc); | 328 | void ath_rx_cleanup(struct ath_softc *sc); |
@@ -338,14 +332,12 @@ void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq); | |||
338 | void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq); | 332 | void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq); |
339 | void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq); | 333 | void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq); |
340 | void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); | 334 | void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); |
341 | bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); | 335 | bool ath_drain_all_txq(struct ath_softc *sc); |
342 | void ath_draintxq(struct ath_softc *sc, | 336 | void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq); |
343 | struct ath_txq *txq, bool retry_tx); | ||
344 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); | 337 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); |
345 | void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); | 338 | void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); |
346 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); | 339 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); |
347 | int ath_tx_init(struct ath_softc *sc, int nbufs); | 340 | int ath_tx_init(struct ath_softc *sc, int nbufs); |
348 | void ath_tx_cleanup(struct ath_softc *sc); | ||
349 | int ath_txq_update(struct ath_softc *sc, int qnum, | 341 | int ath_txq_update(struct ath_softc *sc, int qnum, |
350 | struct ath9k_tx_queue_info *q); | 342 | struct ath9k_tx_queue_info *q); |
351 | void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop); | 343 | void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop); |
@@ -646,7 +638,6 @@ void ath_ant_comb_update(struct ath_softc *sc); | |||
646 | enum sc_op_flags { | 638 | enum sc_op_flags { |
647 | SC_OP_INVALID, | 639 | SC_OP_INVALID, |
648 | SC_OP_BEACONS, | 640 | SC_OP_BEACONS, |
649 | SC_OP_RXFLUSH, | ||
650 | SC_OP_ANI_RUN, | 641 | SC_OP_ANI_RUN, |
651 | SC_OP_PRIM_STA_VIF, | 642 | SC_OP_PRIM_STA_VIF, |
652 | SC_OP_HW_RESET, | 643 | SC_OP_HW_RESET, |
@@ -675,6 +666,23 @@ struct ath9k_vif_iter_data { | |||
675 | int nadhocs; /* number of adhoc vifs */ | 666 | int nadhocs; /* number of adhoc vifs */ |
676 | }; | 667 | }; |
677 | 668 | ||
669 | /* enum spectral_mode: | ||
670 | * | ||
671 | * @SPECTRAL_DISABLED: spectral mode is disabled | ||
672 | * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with | ||
673 | * something else. | ||
674 | * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples | ||
675 | * is performed manually. | ||
676 | * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels | ||
677 | * during a channel scan. | ||
678 | */ | ||
679 | enum spectral_mode { | ||
680 | SPECTRAL_DISABLED = 0, | ||
681 | SPECTRAL_BACKGROUND, | ||
682 | SPECTRAL_MANUAL, | ||
683 | SPECTRAL_CHANSCAN, | ||
684 | }; | ||
685 | |||
678 | struct ath_softc { | 686 | struct ath_softc { |
679 | struct ieee80211_hw *hw; | 687 | struct ieee80211_hw *hw; |
680 | struct device *dev; | 688 | struct device *dev; |
@@ -743,6 +751,10 @@ struct ath_softc { | |||
743 | u8 ant_tx, ant_rx; | 751 | u8 ant_tx, ant_rx; |
744 | struct dfs_pattern_detector *dfs_detector; | 752 | struct dfs_pattern_detector *dfs_detector; |
745 | u32 wow_enabled; | 753 | u32 wow_enabled; |
754 | /* relay(fs) channel for spectral scan */ | ||
755 | struct rchan *rfs_chan_spec_scan; | ||
756 | enum spectral_mode spectral_mode; | ||
757 | int scanning; | ||
746 | 758 | ||
747 | #ifdef CONFIG_PM_SLEEP | 759 | #ifdef CONFIG_PM_SLEEP |
748 | atomic_t wow_got_bmiss_intr; | 760 | atomic_t wow_got_bmiss_intr; |
@@ -751,6 +763,133 @@ struct ath_softc { | |||
751 | #endif | 763 | #endif |
752 | }; | 764 | }; |
753 | 765 | ||
766 | #define SPECTRAL_SCAN_BITMASK 0x10 | ||
767 | /* Radar info packet format, used for DFS and spectral formats. */ | ||
768 | struct ath_radar_info { | ||
769 | u8 pulse_length_pri; | ||
770 | u8 pulse_length_ext; | ||
771 | u8 pulse_bw_info; | ||
772 | } __packed; | ||
773 | |||
774 | /* The HT20 spectral data has 4 bytes of additional information at it's end. | ||
775 | * | ||
776 | * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]} | ||
777 | * [7:0]: all bins max_magnitude[9:2] | ||
778 | * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]} | ||
779 | * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) | ||
780 | */ | ||
781 | struct ath_ht20_mag_info { | ||
782 | u8 all_bins[3]; | ||
783 | u8 max_exp; | ||
784 | } __packed; | ||
785 | |||
786 | #define SPECTRAL_HT20_NUM_BINS 56 | ||
787 | |||
788 | /* WARNING: don't actually use this struct! MAC may vary the amount of | ||
789 | * data by -1/+2. This struct is for reference only. | ||
790 | */ | ||
791 | struct ath_ht20_fft_packet { | ||
792 | u8 data[SPECTRAL_HT20_NUM_BINS]; | ||
793 | struct ath_ht20_mag_info mag_info; | ||
794 | struct ath_radar_info radar_info; | ||
795 | } __packed; | ||
796 | |||
797 | #define SPECTRAL_HT20_TOTAL_DATA_LEN (sizeof(struct ath_ht20_fft_packet)) | ||
798 | |||
799 | /* Dynamic 20/40 mode: | ||
800 | * | ||
801 | * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]} | ||
802 | * [7:0]: lower bins max_magnitude[9:2] | ||
803 | * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]} | ||
804 | * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]} | ||
805 | * [7:0]: upper bins max_magnitude[9:2] | ||
806 | * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]} | ||
807 | * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned) | ||
808 | */ | ||
809 | struct ath_ht20_40_mag_info { | ||
810 | u8 lower_bins[3]; | ||
811 | u8 upper_bins[3]; | ||
812 | u8 max_exp; | ||
813 | } __packed; | ||
814 | |||
815 | #define SPECTRAL_HT20_40_NUM_BINS 128 | ||
816 | |||
817 | /* WARNING: don't actually use this struct! MAC may vary the amount of | ||
818 | * data. This struct is for reference only. | ||
819 | */ | ||
820 | struct ath_ht20_40_fft_packet { | ||
821 | u8 data[SPECTRAL_HT20_40_NUM_BINS]; | ||
822 | struct ath_ht20_40_mag_info mag_info; | ||
823 | struct ath_radar_info radar_info; | ||
824 | } __packed; | ||
825 | |||
826 | |||
827 | #define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) | ||
828 | |||
829 | /* grabs the max magnitude from the all/upper/lower bins */ | ||
830 | static inline u16 spectral_max_magnitude(u8 *bins) | ||
831 | { | ||
832 | return (bins[0] & 0xc0) >> 6 | | ||
833 | (bins[1] & 0xff) << 2 | | ||
834 | (bins[2] & 0x03) << 10; | ||
835 | } | ||
836 | |||
837 | /* return the max magnitude from the all/upper/lower bins */ | ||
838 | static inline u8 spectral_max_index(u8 *bins) | ||
839 | { | ||
840 | s8 m = (bins[2] & 0xfc) >> 2; | ||
841 | |||
842 | /* TODO: this still doesn't always report the right values ... */ | ||
843 | if (m > 32) | ||
844 | m |= 0xe0; | ||
845 | else | ||
846 | m &= ~0xe0; | ||
847 | |||
848 | return m + 29; | ||
849 | } | ||
850 | |||
851 | /* return the bitmap weight from the all/upper/lower bins */ | ||
852 | static inline u8 spectral_bitmap_weight(u8 *bins) | ||
853 | { | ||
854 | return bins[0] & 0x3f; | ||
855 | } | ||
856 | |||
857 | /* FFT sample format given to userspace via debugfs. | ||
858 | * | ||
859 | * Please keep the type/length at the front position and change | ||
860 | * other fields after adding another sample type | ||
861 | * | ||
862 | * TODO: this might need rework when switching to nl80211-based | ||
863 | * interface. | ||
864 | */ | ||
865 | enum ath_fft_sample_type { | ||
866 | ATH_FFT_SAMPLE_HT20 = 0, | ||
867 | }; | ||
868 | |||
869 | struct fft_sample_tlv { | ||
870 | u8 type; /* see ath_fft_sample */ | ||
871 | u16 length; | ||
872 | /* type dependent data follows */ | ||
873 | } __packed; | ||
874 | |||
875 | struct fft_sample_ht20 { | ||
876 | struct fft_sample_tlv tlv; | ||
877 | |||
878 | u8 __alignment; | ||
879 | |||
880 | u16 freq; | ||
881 | s8 rssi; | ||
882 | s8 noise; | ||
883 | |||
884 | u16 max_magnitude; | ||
885 | u8 max_index; | ||
886 | u8 bitmap_weight; | ||
887 | |||
888 | u64 tsf; | ||
889 | |||
890 | u16 data[SPECTRAL_HT20_NUM_BINS]; | ||
891 | } __packed; | ||
892 | |||
754 | void ath9k_tasklet(unsigned long data); | 893 | void ath9k_tasklet(unsigned long data); |
755 | int ath_cabq_update(struct ath_softc *); | 894 | int ath_cabq_update(struct ath_softc *); |
756 | 895 | ||
@@ -773,6 +912,10 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); | |||
773 | void ath9k_reload_chainmask_settings(struct ath_softc *sc); | 912 | void ath9k_reload_chainmask_settings(struct ath_softc *sc); |
774 | 913 | ||
775 | bool ath9k_uses_beacons(int type); | 914 | bool ath9k_uses_beacons(int type); |
915 | void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); | ||
916 | int ath9k_spectral_scan_config(struct ieee80211_hw *hw, | ||
917 | enum spectral_mode spectral_mode); | ||
918 | |||
776 | 919 | ||
777 | #ifdef CONFIG_ATH9K_PCI | 920 | #ifdef CONFIG_ATH9K_PCI |
778 | int ath_pci_init(void); | 921 | int ath_pci_init(void); |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 531fffd801a3..dd3771954bd7 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -147,6 +147,7 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, | |||
147 | skb->len, DMA_TO_DEVICE); | 147 | skb->len, DMA_TO_DEVICE); |
148 | dev_kfree_skb_any(skb); | 148 | dev_kfree_skb_any(skb); |
149 | bf->bf_buf_addr = 0; | 149 | bf->bf_buf_addr = 0; |
150 | bf->bf_mpdu = NULL; | ||
150 | } | 151 | } |
151 | 152 | ||
152 | skb = ieee80211_beacon_get(hw, vif); | 153 | skb = ieee80211_beacon_get(hw, vif); |
@@ -198,7 +199,7 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, | |||
198 | if (sc->nvifs > 1) { | 199 | if (sc->nvifs > 1) { |
199 | ath_dbg(common, BEACON, | 200 | ath_dbg(common, BEACON, |
200 | "Flushing previous cabq traffic\n"); | 201 | "Flushing previous cabq traffic\n"); |
201 | ath_draintxq(sc, cabq, false); | 202 | ath_draintxq(sc, cabq); |
202 | } | 203 | } |
203 | } | 204 | } |
204 | 205 | ||
@@ -359,7 +360,6 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
359 | return; | 360 | return; |
360 | 361 | ||
361 | bf = ath9k_beacon_generate(sc->hw, vif); | 362 | bf = ath9k_beacon_generate(sc->hw, vif); |
362 | WARN_ON(!bf); | ||
363 | 363 | ||
364 | if (sc->beacon.bmisscnt != 0) { | 364 | if (sc->beacon.bmisscnt != 0) { |
365 | ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n", | 365 | ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n", |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 13ff9edc2401..6c5d313ebcb7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/vmalloc.h> | 18 | #include <linux/vmalloc.h> |
19 | #include <linux/export.h> | 19 | #include <linux/export.h> |
20 | #include <linux/relay.h> | ||
20 | #include <asm/unaligned.h> | 21 | #include <asm/unaligned.h> |
21 | 22 | ||
22 | #include "ath9k.h" | 23 | #include "ath9k.h" |
@@ -861,7 +862,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
861 | RXS_ERR("RX-LENGTH-ERR", rx_len_err); | 862 | RXS_ERR("RX-LENGTH-ERR", rx_len_err); |
862 | RXS_ERR("RX-OOM-ERR", rx_oom_err); | 863 | RXS_ERR("RX-OOM-ERR", rx_oom_err); |
863 | RXS_ERR("RX-RATE-ERR", rx_rate_err); | 864 | RXS_ERR("RX-RATE-ERR", rx_rate_err); |
864 | RXS_ERR("RX-DROP-RXFLUSH", rx_drop_rxflush); | ||
865 | RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err); | 865 | RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err); |
866 | 866 | ||
867 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); | 867 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); |
@@ -966,6 +966,112 @@ static const struct file_operations fops_recv = { | |||
966 | .llseek = default_llseek, | 966 | .llseek = default_llseek, |
967 | }; | 967 | }; |
968 | 968 | ||
969 | static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, | ||
970 | size_t count, loff_t *ppos) | ||
971 | { | ||
972 | struct ath_softc *sc = file->private_data; | ||
973 | char *mode = ""; | ||
974 | unsigned int len; | ||
975 | |||
976 | switch (sc->spectral_mode) { | ||
977 | case SPECTRAL_DISABLED: | ||
978 | mode = "disable"; | ||
979 | break; | ||
980 | case SPECTRAL_BACKGROUND: | ||
981 | mode = "background"; | ||
982 | break; | ||
983 | case SPECTRAL_CHANSCAN: | ||
984 | mode = "chanscan"; | ||
985 | break; | ||
986 | case SPECTRAL_MANUAL: | ||
987 | mode = "manual"; | ||
988 | break; | ||
989 | } | ||
990 | len = strlen(mode); | ||
991 | return simple_read_from_buffer(user_buf, count, ppos, mode, len); | ||
992 | } | ||
993 | |||
994 | static ssize_t write_file_spec_scan_ctl(struct file *file, | ||
995 | const char __user *user_buf, | ||
996 | size_t count, loff_t *ppos) | ||
997 | { | ||
998 | struct ath_softc *sc = file->private_data; | ||
999 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1000 | char buf[32]; | ||
1001 | ssize_t len; | ||
1002 | |||
1003 | len = min(count, sizeof(buf) - 1); | ||
1004 | if (copy_from_user(buf, user_buf, len)) | ||
1005 | return -EFAULT; | ||
1006 | |||
1007 | buf[len] = '\0'; | ||
1008 | |||
1009 | if (strncmp("trigger", buf, 7) == 0) { | ||
1010 | ath9k_spectral_scan_trigger(sc->hw); | ||
1011 | } else if (strncmp("background", buf, 9) == 0) { | ||
1012 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND); | ||
1013 | ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n"); | ||
1014 | } else if (strncmp("chanscan", buf, 8) == 0) { | ||
1015 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN); | ||
1016 | ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n"); | ||
1017 | } else if (strncmp("manual", buf, 6) == 0) { | ||
1018 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL); | ||
1019 | ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); | ||
1020 | } else if (strncmp("disable", buf, 7) == 0) { | ||
1021 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED); | ||
1022 | ath_dbg(common, CONFIG, "spectral scan: disabled\n"); | ||
1023 | } else { | ||
1024 | return -EINVAL; | ||
1025 | } | ||
1026 | |||
1027 | return count; | ||
1028 | } | ||
1029 | |||
1030 | static const struct file_operations fops_spec_scan_ctl = { | ||
1031 | .read = read_file_spec_scan_ctl, | ||
1032 | .write = write_file_spec_scan_ctl, | ||
1033 | .open = simple_open, | ||
1034 | .owner = THIS_MODULE, | ||
1035 | .llseek = default_llseek, | ||
1036 | }; | ||
1037 | |||
1038 | static struct dentry *create_buf_file_handler(const char *filename, | ||
1039 | struct dentry *parent, | ||
1040 | umode_t mode, | ||
1041 | struct rchan_buf *buf, | ||
1042 | int *is_global) | ||
1043 | { | ||
1044 | struct dentry *buf_file; | ||
1045 | |||
1046 | buf_file = debugfs_create_file(filename, mode, parent, buf, | ||
1047 | &relay_file_operations); | ||
1048 | *is_global = 1; | ||
1049 | return buf_file; | ||
1050 | } | ||
1051 | |||
1052 | static int remove_buf_file_handler(struct dentry *dentry) | ||
1053 | { | ||
1054 | debugfs_remove(dentry); | ||
1055 | |||
1056 | return 0; | ||
1057 | } | ||
1058 | |||
1059 | void ath_debug_send_fft_sample(struct ath_softc *sc, | ||
1060 | struct fft_sample_tlv *fft_sample_tlv) | ||
1061 | { | ||
1062 | if (!sc->rfs_chan_spec_scan) | ||
1063 | return; | ||
1064 | |||
1065 | relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, | ||
1066 | fft_sample_tlv->length + sizeof(*fft_sample_tlv)); | ||
1067 | } | ||
1068 | |||
1069 | static struct rchan_callbacks rfs_spec_scan_cb = { | ||
1070 | .create_buf_file = create_buf_file_handler, | ||
1071 | .remove_buf_file = remove_buf_file_handler, | ||
1072 | }; | ||
1073 | |||
1074 | |||
969 | static ssize_t read_file_regidx(struct file *file, char __user *user_buf, | 1075 | static ssize_t read_file_regidx(struct file *file, char __user *user_buf, |
970 | size_t count, loff_t *ppos) | 1076 | size_t count, loff_t *ppos) |
971 | { | 1077 | { |
@@ -1780,6 +1886,14 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1780 | &fops_base_eeprom); | 1886 | &fops_base_eeprom); |
1781 | debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, | 1887 | debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, |
1782 | &fops_modal_eeprom); | 1888 | &fops_modal_eeprom); |
1889 | sc->rfs_chan_spec_scan = relay_open("spectral_scan", | ||
1890 | sc->debug.debugfs_phy, | ||
1891 | 262144, 4, &rfs_spec_scan_cb, | ||
1892 | NULL); | ||
1893 | debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, | ||
1894 | sc->debug.debugfs_phy, sc, | ||
1895 | &fops_spec_scan_ctl); | ||
1896 | |||
1783 | #ifdef CONFIG_ATH9K_MAC_DEBUG | 1897 | #ifdef CONFIG_ATH9K_MAC_DEBUG |
1784 | debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc, | 1898 | debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc, |
1785 | &fops_samps); | 1899 | &fops_samps); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 375c3b46411e..a22c0d780700 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | struct ath_txq; | 24 | struct ath_txq; |
25 | struct ath_buf; | 25 | struct ath_buf; |
26 | struct fft_sample_tlv; | ||
26 | 27 | ||
27 | #ifdef CONFIG_ATH9K_DEBUGFS | 28 | #ifdef CONFIG_ATH9K_DEBUGFS |
28 | #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ | 29 | #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ |
@@ -216,7 +217,6 @@ struct ath_tx_stats { | |||
216 | * @rx_oom_err: No. of frames dropped due to OOM issues. | 217 | * @rx_oom_err: No. of frames dropped due to OOM issues. |
217 | * @rx_rate_err: No. of frames dropped due to rate errors. | 218 | * @rx_rate_err: No. of frames dropped due to rate errors. |
218 | * @rx_too_many_frags_err: Frames dropped due to too-many-frags received. | 219 | * @rx_too_many_frags_err: Frames dropped due to too-many-frags received. |
219 | * @rx_drop_rxflush: No. of frames dropped due to RX-FLUSH. | ||
220 | * @rx_beacons: No. of beacons received. | 220 | * @rx_beacons: No. of beacons received. |
221 | * @rx_frags: No. of rx-fragements received. | 221 | * @rx_frags: No. of rx-fragements received. |
222 | */ | 222 | */ |
@@ -235,7 +235,6 @@ struct ath_rx_stats { | |||
235 | u32 rx_oom_err; | 235 | u32 rx_oom_err; |
236 | u32 rx_rate_err; | 236 | u32 rx_rate_err; |
237 | u32 rx_too_many_frags_err; | 237 | u32 rx_too_many_frags_err; |
238 | u32 rx_drop_rxflush; | ||
239 | u32 rx_beacons; | 238 | u32 rx_beacons; |
240 | u32 rx_frags; | 239 | u32 rx_frags; |
241 | }; | 240 | }; |
@@ -323,6 +322,10 @@ void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw, | |||
323 | struct ieee80211_vif *vif, | 322 | struct ieee80211_vif *vif, |
324 | struct ieee80211_sta *sta, | 323 | struct ieee80211_sta *sta, |
325 | struct dentry *dir); | 324 | struct dentry *dir); |
325 | |||
326 | void ath_debug_send_fft_sample(struct ath_softc *sc, | ||
327 | struct fft_sample_tlv *fft_sample); | ||
328 | |||
326 | #else | 329 | #else |
327 | 330 | ||
328 | #define RX_STAT_INC(c) /* NOP */ | 331 | #define RX_STAT_INC(c) /* NOP */ |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index b2f85cb5ed30..716058b67557 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -280,14 +280,14 @@ err: | |||
280 | return ret; | 280 | return ret; |
281 | } | 281 | } |
282 | 282 | ||
283 | static int ath9k_reg_notifier(struct wiphy *wiphy, | 283 | static void ath9k_reg_notifier(struct wiphy *wiphy, |
284 | struct regulatory_request *request) | 284 | struct regulatory_request *request) |
285 | { | 285 | { |
286 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 286 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
287 | struct ath9k_htc_priv *priv = hw->priv; | 287 | struct ath9k_htc_priv *priv = hw->priv; |
288 | 288 | ||
289 | return ath_reg_notifier_apply(wiphy, request, | 289 | ath_reg_notifier_apply(wiphy, request, |
290 | ath9k_hw_regulatory(priv->ah)); | 290 | ath9k_hw_regulatory(priv->ah)); |
291 | } | 291 | } |
292 | 292 | ||
293 | static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset) | 293 | static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset) |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 9c07a8fa5134..a8016d70088a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1628,7 +1628,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1628 | if (!ret) | 1628 | if (!ret) |
1629 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1629 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1630 | break; | 1630 | break; |
1631 | case IEEE80211_AMPDU_TX_STOP: | 1631 | case IEEE80211_AMPDU_TX_STOP_CONT: |
1632 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
1633 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
1632 | ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid); | 1634 | ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid); |
1633 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1635 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1634 | break; | 1636 | break; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 4a9570dfba72..aac4a406a513 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c | |||
@@ -344,6 +344,8 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, | |||
344 | endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, | 344 | endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, |
345 | skb, htc_hdr->endpoint_id, | 345 | skb, htc_hdr->endpoint_id, |
346 | txok); | 346 | txok); |
347 | } else { | ||
348 | kfree_skb(skb); | ||
347 | } | 349 | } |
348 | } | 350 | } |
349 | 351 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 0f2b97f6b739..14b701140b49 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -101,22 +101,6 @@ static inline void ath9k_hw_spur_mitigate_freq(struct ath_hw *ah, | |||
101 | ath9k_hw_private_ops(ah)->spur_mitigate_freq(ah, chan); | 101 | ath9k_hw_private_ops(ah)->spur_mitigate_freq(ah, chan); |
102 | } | 102 | } |
103 | 103 | ||
104 | static inline int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah) | ||
105 | { | ||
106 | if (!ath9k_hw_private_ops(ah)->rf_alloc_ext_banks) | ||
107 | return 0; | ||
108 | |||
109 | return ath9k_hw_private_ops(ah)->rf_alloc_ext_banks(ah); | ||
110 | } | ||
111 | |||
112 | static inline void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah) | ||
113 | { | ||
114 | if (!ath9k_hw_private_ops(ah)->rf_free_ext_banks) | ||
115 | return; | ||
116 | |||
117 | ath9k_hw_private_ops(ah)->rf_free_ext_banks(ah); | ||
118 | } | ||
119 | |||
120 | static inline bool ath9k_hw_set_rf_regs(struct ath_hw *ah, | 104 | static inline bool ath9k_hw_set_rf_regs(struct ath_hw *ah, |
121 | struct ath9k_channel *chan, | 105 | struct ath9k_channel *chan, |
122 | u16 modesIndex) | 106 | u16 modesIndex) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7cb787065913..42cf3c7f1e25 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -54,11 +54,6 @@ static void ath9k_hw_init_cal_settings(struct ath_hw *ah) | |||
54 | ath9k_hw_private_ops(ah)->init_cal_settings(ah); | 54 | ath9k_hw_private_ops(ah)->init_cal_settings(ah); |
55 | } | 55 | } |
56 | 56 | ||
57 | static void ath9k_hw_init_mode_regs(struct ath_hw *ah) | ||
58 | { | ||
59 | ath9k_hw_private_ops(ah)->init_mode_regs(ah); | ||
60 | } | ||
61 | |||
62 | static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, | 57 | static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, |
63 | struct ath9k_channel *chan) | 58 | struct ath9k_channel *chan) |
64 | { | 59 | { |
@@ -208,7 +203,7 @@ void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan, | |||
208 | udelay(hw_delay + BASE_ACTIVATE_DELAY); | 203 | udelay(hw_delay + BASE_ACTIVATE_DELAY); |
209 | } | 204 | } |
210 | 205 | ||
211 | void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array, | 206 | void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array, |
212 | int column, unsigned int *writecnt) | 207 | int column, unsigned int *writecnt) |
213 | { | 208 | { |
214 | int r; | 209 | int r; |
@@ -554,28 +549,19 @@ static int ath9k_hw_post_init(struct ath_hw *ah) | |||
554 | ah->eep_ops->get_eeprom_ver(ah), | 549 | ah->eep_ops->get_eeprom_ver(ah), |
555 | ah->eep_ops->get_eeprom_rev(ah)); | 550 | ah->eep_ops->get_eeprom_rev(ah)); |
556 | 551 | ||
557 | ecode = ath9k_hw_rf_alloc_ext_banks(ah); | 552 | if (ah->config.enable_ani) |
558 | if (ecode) { | ||
559 | ath_err(ath9k_hw_common(ah), | ||
560 | "Failed allocating banks for external radio\n"); | ||
561 | ath9k_hw_rf_free_ext_banks(ah); | ||
562 | return ecode; | ||
563 | } | ||
564 | |||
565 | if (ah->config.enable_ani) { | ||
566 | ath9k_hw_ani_setup(ah); | ||
567 | ath9k_hw_ani_init(ah); | 553 | ath9k_hw_ani_init(ah); |
568 | } | ||
569 | 554 | ||
570 | return 0; | 555 | return 0; |
571 | } | 556 | } |
572 | 557 | ||
573 | static void ath9k_hw_attach_ops(struct ath_hw *ah) | 558 | static int ath9k_hw_attach_ops(struct ath_hw *ah) |
574 | { | 559 | { |
575 | if (AR_SREV_9300_20_OR_LATER(ah)) | 560 | if (!AR_SREV_9300_20_OR_LATER(ah)) |
576 | ar9003_hw_attach_ops(ah); | 561 | return ar9002_hw_attach_ops(ah); |
577 | else | 562 | |
578 | ar9002_hw_attach_ops(ah); | 563 | ar9003_hw_attach_ops(ah); |
564 | return 0; | ||
579 | } | 565 | } |
580 | 566 | ||
581 | /* Called for all hardware families */ | 567 | /* Called for all hardware families */ |
@@ -611,7 +597,9 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
611 | ath9k_hw_init_defaults(ah); | 597 | ath9k_hw_init_defaults(ah); |
612 | ath9k_hw_init_config(ah); | 598 | ath9k_hw_init_config(ah); |
613 | 599 | ||
614 | ath9k_hw_attach_ops(ah); | 600 | r = ath9k_hw_attach_ops(ah); |
601 | if (r) | ||
602 | return r; | ||
615 | 603 | ||
616 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { | 604 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { |
617 | ath_err(common, "Couldn't wakeup chip\n"); | 605 | ath_err(common, "Couldn't wakeup chip\n"); |
@@ -675,8 +663,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
675 | if (!AR_SREV_9300_20_OR_LATER(ah)) | 663 | if (!AR_SREV_9300_20_OR_LATER(ah)) |
676 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; | 664 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; |
677 | 665 | ||
678 | ath9k_hw_init_mode_regs(ah); | ||
679 | |||
680 | if (!ah->is_pciexpress) | 666 | if (!ah->is_pciexpress) |
681 | ath9k_hw_disablepcie(ah); | 667 | ath9k_hw_disablepcie(ah); |
682 | 668 | ||
@@ -1153,12 +1139,9 @@ void ath9k_hw_deinit(struct ath_hw *ah) | |||
1153 | struct ath_common *common = ath9k_hw_common(ah); | 1139 | struct ath_common *common = ath9k_hw_common(ah); |
1154 | 1140 | ||
1155 | if (common->state < ATH_HW_INITIALIZED) | 1141 | if (common->state < ATH_HW_INITIALIZED) |
1156 | goto free_hw; | 1142 | return; |
1157 | 1143 | ||
1158 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); | 1144 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); |
1159 | |||
1160 | free_hw: | ||
1161 | ath9k_hw_rf_free_ext_banks(ah); | ||
1162 | } | 1145 | } |
1163 | EXPORT_SYMBOL(ath9k_hw_deinit); | 1146 | EXPORT_SYMBOL(ath9k_hw_deinit); |
1164 | 1147 | ||
@@ -2576,12 +2559,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2576 | rx_chainmask >>= 1; | 2559 | rx_chainmask >>= 1; |
2577 | } | 2560 | } |
2578 | 2561 | ||
2579 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
2580 | ah->enabled_cals |= TX_IQ_CAL; | ||
2581 | if (AR_SREV_9485_OR_LATER(ah)) | ||
2582 | ah->enabled_cals |= TX_IQ_ON_AGC_CAL; | ||
2583 | } | ||
2584 | |||
2585 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | 2562 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { |
2586 | if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE)) | 2563 | if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE)) |
2587 | pCap->hw_caps |= ATH9K_HW_CAP_MCI; | 2564 | pCap->hw_caps |= ATH9K_HW_CAP_MCI; |
@@ -2590,7 +2567,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2590 | pCap->hw_caps |= ATH9K_HW_CAP_RTT; | 2567 | pCap->hw_caps |= ATH9K_HW_CAP_RTT; |
2591 | } | 2568 | } |
2592 | 2569 | ||
2593 | |||
2594 | if (AR_SREV_9280_20_OR_LATER(ah)) { | 2570 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
2595 | pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE | | 2571 | pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE | |
2596 | ATH9K_HW_WOW_PATTERN_MATCH_EXACT; | 2572 | ATH9K_HW_WOW_PATTERN_MATCH_EXACT; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7f1a8e91c908..784e81ccb903 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -397,6 +397,7 @@ enum ath9k_int { | |||
397 | #define MAX_RTT_TABLE_ENTRY 6 | 397 | #define MAX_RTT_TABLE_ENTRY 6 |
398 | #define MAX_IQCAL_MEASUREMENT 8 | 398 | #define MAX_IQCAL_MEASUREMENT 8 |
399 | #define MAX_CL_TAB_ENTRY 16 | 399 | #define MAX_CL_TAB_ENTRY 16 |
400 | #define CL_TAB_ENTRY(reg_base) (reg_base + (4 * j)) | ||
400 | 401 | ||
401 | struct ath9k_hw_cal_data { | 402 | struct ath9k_hw_cal_data { |
402 | u16 channel; | 403 | u16 channel; |
@@ -599,13 +600,10 @@ struct ath_hw_radar_conf { | |||
599 | * @init_cal_settings: setup types of calibrations supported | 600 | * @init_cal_settings: setup types of calibrations supported |
600 | * @init_cal: starts actual calibration | 601 | * @init_cal: starts actual calibration |
601 | * | 602 | * |
602 | * @init_mode_regs: Initializes mode registers | ||
603 | * @init_mode_gain_regs: Initialize TX/RX gain registers | 603 | * @init_mode_gain_regs: Initialize TX/RX gain registers |
604 | * | 604 | * |
605 | * @rf_set_freq: change frequency | 605 | * @rf_set_freq: change frequency |
606 | * @spur_mitigate_freq: spur mitigation | 606 | * @spur_mitigate_freq: spur mitigation |
607 | * @rf_alloc_ext_banks: | ||
608 | * @rf_free_ext_banks: | ||
609 | * @set_rf_regs: | 607 | * @set_rf_regs: |
610 | * @compute_pll_control: compute the PLL control value to use for | 608 | * @compute_pll_control: compute the PLL control value to use for |
611 | * AR_RTC_PLL_CONTROL for a given channel | 609 | * AR_RTC_PLL_CONTROL for a given channel |
@@ -620,7 +618,6 @@ struct ath_hw_private_ops { | |||
620 | void (*init_cal_settings)(struct ath_hw *ah); | 618 | void (*init_cal_settings)(struct ath_hw *ah); |
621 | bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan); | 619 | bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan); |
622 | 620 | ||
623 | void (*init_mode_regs)(struct ath_hw *ah); | ||
624 | void (*init_mode_gain_regs)(struct ath_hw *ah); | 621 | void (*init_mode_gain_regs)(struct ath_hw *ah); |
625 | void (*setup_calibration)(struct ath_hw *ah, | 622 | void (*setup_calibration)(struct ath_hw *ah, |
626 | struct ath9k_cal_list *currCal); | 623 | struct ath9k_cal_list *currCal); |
@@ -630,8 +627,6 @@ struct ath_hw_private_ops { | |||
630 | struct ath9k_channel *chan); | 627 | struct ath9k_channel *chan); |
631 | void (*spur_mitigate_freq)(struct ath_hw *ah, | 628 | void (*spur_mitigate_freq)(struct ath_hw *ah, |
632 | struct ath9k_channel *chan); | 629 | struct ath9k_channel *chan); |
633 | int (*rf_alloc_ext_banks)(struct ath_hw *ah); | ||
634 | void (*rf_free_ext_banks)(struct ath_hw *ah); | ||
635 | bool (*set_rf_regs)(struct ath_hw *ah, | 630 | bool (*set_rf_regs)(struct ath_hw *ah, |
636 | struct ath9k_channel *chan, | 631 | struct ath9k_channel *chan, |
637 | u16 modesIndex); | 632 | u16 modesIndex); |
@@ -661,6 +656,37 @@ struct ath_hw_private_ops { | |||
661 | }; | 656 | }; |
662 | 657 | ||
663 | /** | 658 | /** |
659 | * struct ath_spec_scan - parameters for Atheros spectral scan | ||
660 | * | ||
661 | * @enabled: enable/disable spectral scan | ||
662 | * @short_repeat: controls whether the chip is in spectral scan mode | ||
663 | * for 4 usec (enabled) or 204 usec (disabled) | ||
664 | * @count: number of scan results requested. There are special meanings | ||
665 | * in some chip revisions: | ||
666 | * AR92xx: highest bit set (>=128) for endless mode | ||
667 | * (spectral scan won't stopped until explicitly disabled) | ||
668 | * AR9300 and newer: 0 for endless mode | ||
669 | * @endless: true if endless mode is intended. Otherwise, count value is | ||
670 | * corrected to the next possible value. | ||
671 | * @period: time duration between successive spectral scan entry points | ||
672 | * (period*256*Tclk). Tclk = ath_common->clockrate | ||
673 | * @fft_period: PHY passes FFT frames to MAC every (fft_period+1)*4uS | ||
674 | * | ||
675 | * Note: Tclk = 40MHz or 44MHz depending upon operating mode. | ||
676 | * Typically it's 44MHz in 2/5GHz on later chips, but there's | ||
677 | * a "fast clock" check for this in 5GHz. | ||
678 | * | ||
679 | */ | ||
680 | struct ath_spec_scan { | ||
681 | bool enabled; | ||
682 | bool short_repeat; | ||
683 | bool endless; | ||
684 | u8 count; | ||
685 | u8 period; | ||
686 | u8 fft_period; | ||
687 | }; | ||
688 | |||
689 | /** | ||
664 | * struct ath_hw_ops - callbacks used by hardware code and driver code | 690 | * struct ath_hw_ops - callbacks used by hardware code and driver code |
665 | * | 691 | * |
666 | * This structure contains callbacks designed to to be used internally by | 692 | * This structure contains callbacks designed to to be used internally by |
@@ -668,6 +694,10 @@ struct ath_hw_private_ops { | |||
668 | * | 694 | * |
669 | * @config_pci_powersave: | 695 | * @config_pci_powersave: |
670 | * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC | 696 | * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC |
697 | * | ||
698 | * @spectral_scan_config: set parameters for spectral scan and enable/disable it | ||
699 | * @spectral_scan_trigger: trigger a spectral scan run | ||
700 | * @spectral_scan_wait: wait for a spectral scan run to finish | ||
671 | */ | 701 | */ |
672 | struct ath_hw_ops { | 702 | struct ath_hw_ops { |
673 | void (*config_pci_powersave)(struct ath_hw *ah, | 703 | void (*config_pci_powersave)(struct ath_hw *ah, |
@@ -688,6 +718,10 @@ struct ath_hw_ops { | |||
688 | void (*antdiv_comb_conf_set)(struct ath_hw *ah, | 718 | void (*antdiv_comb_conf_set)(struct ath_hw *ah, |
689 | struct ath_hw_antcomb_conf *antconf); | 719 | struct ath_hw_antcomb_conf *antconf); |
690 | void (*antctrl_shared_chain_lnadiv)(struct ath_hw *hw, bool enable); | 720 | void (*antctrl_shared_chain_lnadiv)(struct ath_hw *hw, bool enable); |
721 | void (*spectral_scan_config)(struct ath_hw *ah, | ||
722 | struct ath_spec_scan *param); | ||
723 | void (*spectral_scan_trigger)(struct ath_hw *ah); | ||
724 | void (*spectral_scan_wait)(struct ath_hw *ah); | ||
691 | }; | 725 | }; |
692 | 726 | ||
693 | struct ath_nf_limits { | 727 | struct ath_nf_limits { |
@@ -710,6 +744,7 @@ enum ath_cal_list { | |||
710 | struct ath_hw { | 744 | struct ath_hw { |
711 | struct ath_ops reg_ops; | 745 | struct ath_ops reg_ops; |
712 | 746 | ||
747 | struct device *dev; | ||
713 | struct ieee80211_hw *hw; | 748 | struct ieee80211_hw *hw; |
714 | struct ath_common common; | 749 | struct ath_common common; |
715 | struct ath9k_hw_version hw_version; | 750 | struct ath9k_hw_version hw_version; |
@@ -771,7 +806,6 @@ struct ath_hw { | |||
771 | struct ath9k_cal_list iq_caldata; | 806 | struct ath9k_cal_list iq_caldata; |
772 | struct ath9k_cal_list adcgain_caldata; | 807 | struct ath9k_cal_list adcgain_caldata; |
773 | struct ath9k_cal_list adcdc_caldata; | 808 | struct ath9k_cal_list adcdc_caldata; |
774 | struct ath9k_cal_list tempCompCalData; | ||
775 | struct ath9k_cal_list *cal_list; | 809 | struct ath9k_cal_list *cal_list; |
776 | struct ath9k_cal_list *cal_list_last; | 810 | struct ath9k_cal_list *cal_list_last; |
777 | struct ath9k_cal_list *cal_list_curr; | 811 | struct ath9k_cal_list *cal_list_curr; |
@@ -830,10 +864,6 @@ struct ath_hw { | |||
830 | /* ANI */ | 864 | /* ANI */ |
831 | u32 proc_phyerr; | 865 | u32 proc_phyerr; |
832 | u32 aniperiod; | 866 | u32 aniperiod; |
833 | int totalSizeDesired[5]; | ||
834 | int coarse_high[5]; | ||
835 | int coarse_low[5]; | ||
836 | int firpwr[5]; | ||
837 | enum ath9k_ani_cmd ani_function; | 867 | enum ath9k_ani_cmd ani_function; |
838 | u32 ani_skip_count; | 868 | u32 ani_skip_count; |
839 | 869 | ||
@@ -979,7 +1009,7 @@ void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); | |||
979 | void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan, | 1009 | void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan, |
980 | int hw_delay); | 1010 | int hw_delay); |
981 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); | 1011 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); |
982 | void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array, | 1012 | void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array, |
983 | int column, unsigned int *writecnt); | 1013 | int column, unsigned int *writecnt); |
984 | u32 ath9k_hw_reverse_bits(u32 val, u32 n); | 1014 | u32 ath9k_hw_reverse_bits(u32 val, u32 n); |
985 | u16 ath9k_hw_computetxtime(struct ath_hw *ah, | 1015 | u16 ath9k_hw_computetxtime(struct ath_hw *ah, |
@@ -1066,16 +1096,17 @@ void ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); | |||
1066 | int ar9003_paprd_init_table(struct ath_hw *ah); | 1096 | int ar9003_paprd_init_table(struct ath_hw *ah); |
1067 | bool ar9003_paprd_is_done(struct ath_hw *ah); | 1097 | bool ar9003_paprd_is_done(struct ath_hw *ah); |
1068 | bool ar9003_is_paprd_enabled(struct ath_hw *ah); | 1098 | bool ar9003_is_paprd_enabled(struct ath_hw *ah); |
1099 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); | ||
1069 | 1100 | ||
1070 | /* Hardware family op attach helpers */ | 1101 | /* Hardware family op attach helpers */ |
1071 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah); | 1102 | int ar5008_hw_attach_phy_ops(struct ath_hw *ah); |
1072 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah); | 1103 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah); |
1073 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah); | 1104 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah); |
1074 | 1105 | ||
1075 | void ar9002_hw_attach_calib_ops(struct ath_hw *ah); | 1106 | void ar9002_hw_attach_calib_ops(struct ath_hw *ah); |
1076 | void ar9003_hw_attach_calib_ops(struct ath_hw *ah); | 1107 | void ar9003_hw_attach_calib_ops(struct ath_hw *ah); |
1077 | 1108 | ||
1078 | void ar9002_hw_attach_ops(struct ath_hw *ah); | 1109 | int ar9002_hw_attach_ops(struct ath_hw *ah); |
1079 | void ar9003_hw_attach_ops(struct ath_hw *ah); | 1110 | void ar9003_hw_attach_ops(struct ath_hw *ah); |
1080 | 1111 | ||
1081 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan); | 1112 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan); |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index f69ef5d48c7b..4b1abc7da98c 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/ath9k_platform.h> | 21 | #include <linux/ath9k_platform.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/relay.h> | ||
23 | 24 | ||
24 | #include "ath9k.h" | 25 | #include "ath9k.h" |
25 | 26 | ||
@@ -302,16 +303,15 @@ static void setup_ht_cap(struct ath_softc *sc, | |||
302 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; | 303 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; |
303 | } | 304 | } |
304 | 305 | ||
305 | static int ath9k_reg_notifier(struct wiphy *wiphy, | 306 | static void ath9k_reg_notifier(struct wiphy *wiphy, |
306 | struct regulatory_request *request) | 307 | struct regulatory_request *request) |
307 | { | 308 | { |
308 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 309 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
309 | struct ath_softc *sc = hw->priv; | 310 | struct ath_softc *sc = hw->priv; |
310 | struct ath_hw *ah = sc->sc_ah; | 311 | struct ath_hw *ah = sc->sc_ah; |
311 | struct ath_regulatory *reg = ath9k_hw_regulatory(ah); | 312 | struct ath_regulatory *reg = ath9k_hw_regulatory(ah); |
312 | int ret; | ||
313 | 313 | ||
314 | ret = ath_reg_notifier_apply(wiphy, request, reg); | 314 | ath_reg_notifier_apply(wiphy, request, reg); |
315 | 315 | ||
316 | /* Set tx power */ | 316 | /* Set tx power */ |
317 | if (ah->curchan) { | 317 | if (ah->curchan) { |
@@ -321,8 +321,6 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, | |||
321 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; | 321 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; |
322 | ath9k_ps_restore(sc); | 322 | ath9k_ps_restore(sc); |
323 | } | 323 | } |
324 | |||
325 | return ret; | ||
326 | } | 324 | } |
327 | 325 | ||
328 | /* | 326 | /* |
@@ -337,7 +335,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
337 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 335 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
338 | u8 *ds; | 336 | u8 *ds; |
339 | struct ath_buf *bf; | 337 | struct ath_buf *bf; |
340 | int i, bsize, error, desc_len; | 338 | int i, bsize, desc_len; |
341 | 339 | ||
342 | ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n", | 340 | ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n", |
343 | name, nbuf, ndesc); | 341 | name, nbuf, ndesc); |
@@ -353,8 +351,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
353 | if ((desc_len % 4) != 0) { | 351 | if ((desc_len % 4) != 0) { |
354 | ath_err(common, "ath_desc not DWORD aligned\n"); | 352 | ath_err(common, "ath_desc not DWORD aligned\n"); |
355 | BUG_ON((desc_len % 4) != 0); | 353 | BUG_ON((desc_len % 4) != 0); |
356 | error = -ENOMEM; | 354 | return -ENOMEM; |
357 | goto fail; | ||
358 | } | 355 | } |
359 | 356 | ||
360 | dd->dd_desc_len = desc_len * nbuf * ndesc; | 357 | dd->dd_desc_len = desc_len * nbuf * ndesc; |
@@ -378,12 +375,11 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
378 | } | 375 | } |
379 | 376 | ||
380 | /* allocate descriptors */ | 377 | /* allocate descriptors */ |
381 | dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, | 378 | dd->dd_desc = dmam_alloc_coherent(sc->dev, dd->dd_desc_len, |
382 | &dd->dd_desc_paddr, GFP_KERNEL); | 379 | &dd->dd_desc_paddr, GFP_KERNEL); |
383 | if (dd->dd_desc == NULL) { | 380 | if (!dd->dd_desc) |
384 | error = -ENOMEM; | 381 | return -ENOMEM; |
385 | goto fail; | 382 | |
386 | } | ||
387 | ds = (u8 *) dd->dd_desc; | 383 | ds = (u8 *) dd->dd_desc; |
388 | ath_dbg(common, CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", | 384 | ath_dbg(common, CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", |
389 | name, ds, (u32) dd->dd_desc_len, | 385 | name, ds, (u32) dd->dd_desc_len, |
@@ -391,12 +387,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
391 | 387 | ||
392 | /* allocate buffers */ | 388 | /* allocate buffers */ |
393 | bsize = sizeof(struct ath_buf) * nbuf; | 389 | bsize = sizeof(struct ath_buf) * nbuf; |
394 | bf = kzalloc(bsize, GFP_KERNEL); | 390 | bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); |
395 | if (bf == NULL) { | 391 | if (!bf) |
396 | error = -ENOMEM; | 392 | return -ENOMEM; |
397 | goto fail2; | ||
398 | } | ||
399 | dd->dd_bufptr = bf; | ||
400 | 393 | ||
401 | for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { | 394 | for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { |
402 | bf->bf_desc = ds; | 395 | bf->bf_desc = ds; |
@@ -422,12 +415,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
422 | list_add_tail(&bf->list, head); | 415 | list_add_tail(&bf->list, head); |
423 | } | 416 | } |
424 | return 0; | 417 | return 0; |
425 | fail2: | ||
426 | dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, | ||
427 | dd->dd_desc_paddr); | ||
428 | fail: | ||
429 | memset(dd, 0, sizeof(*dd)); | ||
430 | return error; | ||
431 | } | 418 | } |
432 | 419 | ||
433 | static int ath9k_init_queues(struct ath_softc *sc) | 420 | static int ath9k_init_queues(struct ath_softc *sc) |
@@ -457,11 +444,13 @@ static int ath9k_init_channels_rates(struct ath_softc *sc) | |||
457 | ATH9K_NUM_CHANNELS); | 444 | ATH9K_NUM_CHANNELS); |
458 | 445 | ||
459 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { | 446 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { |
460 | channels = kmemdup(ath9k_2ghz_chantable, | 447 | channels = devm_kzalloc(sc->dev, |
461 | sizeof(ath9k_2ghz_chantable), GFP_KERNEL); | 448 | sizeof(ath9k_2ghz_chantable), GFP_KERNEL); |
462 | if (!channels) | 449 | if (!channels) |
463 | return -ENOMEM; | 450 | return -ENOMEM; |
464 | 451 | ||
452 | memcpy(channels, ath9k_2ghz_chantable, | ||
453 | sizeof(ath9k_2ghz_chantable)); | ||
465 | sc->sbands[IEEE80211_BAND_2GHZ].channels = channels; | 454 | sc->sbands[IEEE80211_BAND_2GHZ].channels = channels; |
466 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | 455 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; |
467 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = | 456 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = |
@@ -472,14 +461,13 @@ static int ath9k_init_channels_rates(struct ath_softc *sc) | |||
472 | } | 461 | } |
473 | 462 | ||
474 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { | 463 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { |
475 | channels = kmemdup(ath9k_5ghz_chantable, | 464 | channels = devm_kzalloc(sc->dev, |
476 | sizeof(ath9k_5ghz_chantable), GFP_KERNEL); | 465 | sizeof(ath9k_5ghz_chantable), GFP_KERNEL); |
477 | if (!channels) { | 466 | if (!channels) |
478 | if (sc->sbands[IEEE80211_BAND_2GHZ].channels) | ||
479 | kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); | ||
480 | return -ENOMEM; | 467 | return -ENOMEM; |
481 | } | ||
482 | 468 | ||
469 | memcpy(channels, ath9k_5ghz_chantable, | ||
470 | sizeof(ath9k_5ghz_chantable)); | ||
483 | sc->sbands[IEEE80211_BAND_5GHZ].channels = channels; | 471 | sc->sbands[IEEE80211_BAND_5GHZ].channels = channels; |
484 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; | 472 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; |
485 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = | 473 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = |
@@ -565,10 +553,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
565 | int ret = 0, i; | 553 | int ret = 0, i; |
566 | int csz = 0; | 554 | int csz = 0; |
567 | 555 | ||
568 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); | 556 | ah = devm_kzalloc(sc->dev, sizeof(struct ath_hw), GFP_KERNEL); |
569 | if (!ah) | 557 | if (!ah) |
570 | return -ENOMEM; | 558 | return -ENOMEM; |
571 | 559 | ||
560 | ah->dev = sc->dev; | ||
572 | ah->hw = sc->hw; | 561 | ah->hw = sc->hw; |
573 | ah->hw_version.devid = devid; | 562 | ah->hw_version.devid = devid; |
574 | ah->reg_ops.read = ath9k_ioread32; | 563 | ah->reg_ops.read = ath9k_ioread32; |
@@ -636,7 +625,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
636 | if (pdata && pdata->eeprom_name) { | 625 | if (pdata && pdata->eeprom_name) { |
637 | ret = ath9k_eeprom_request(sc, pdata->eeprom_name); | 626 | ret = ath9k_eeprom_request(sc, pdata->eeprom_name); |
638 | if (ret) | 627 | if (ret) |
639 | goto err_eeprom; | 628 | return ret; |
640 | } | 629 | } |
641 | 630 | ||
642 | /* Initializes the hardware for all supported chipsets */ | 631 | /* Initializes the hardware for all supported chipsets */ |
@@ -676,10 +665,6 @@ err_queues: | |||
676 | ath9k_hw_deinit(ah); | 665 | ath9k_hw_deinit(ah); |
677 | err_hw: | 666 | err_hw: |
678 | ath9k_eeprom_release(sc); | 667 | ath9k_eeprom_release(sc); |
679 | err_eeprom: | ||
680 | kfree(ah); | ||
681 | sc->sc_ah = NULL; | ||
682 | |||
683 | return ret; | 668 | return ret; |
684 | } | 669 | } |
685 | 670 | ||
@@ -844,8 +829,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, | |||
844 | 829 | ||
845 | /* Bring up device */ | 830 | /* Bring up device */ |
846 | error = ath9k_init_softc(devid, sc, bus_ops); | 831 | error = ath9k_init_softc(devid, sc, bus_ops); |
847 | if (error != 0) | 832 | if (error) |
848 | goto error_init; | 833 | return error; |
849 | 834 | ||
850 | ah = sc->sc_ah; | 835 | ah = sc->sc_ah; |
851 | common = ath9k_hw_common(ah); | 836 | common = ath9k_hw_common(ah); |
@@ -855,19 +840,19 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, | |||
855 | error = ath_regd_init(&common->regulatory, sc->hw->wiphy, | 840 | error = ath_regd_init(&common->regulatory, sc->hw->wiphy, |
856 | ath9k_reg_notifier); | 841 | ath9k_reg_notifier); |
857 | if (error) | 842 | if (error) |
858 | goto error_regd; | 843 | goto deinit; |
859 | 844 | ||
860 | reg = &common->regulatory; | 845 | reg = &common->regulatory; |
861 | 846 | ||
862 | /* Setup TX DMA */ | 847 | /* Setup TX DMA */ |
863 | error = ath_tx_init(sc, ATH_TXBUF); | 848 | error = ath_tx_init(sc, ATH_TXBUF); |
864 | if (error != 0) | 849 | if (error != 0) |
865 | goto error_tx; | 850 | goto deinit; |
866 | 851 | ||
867 | /* Setup RX DMA */ | 852 | /* Setup RX DMA */ |
868 | error = ath_rx_init(sc, ATH_RXBUF); | 853 | error = ath_rx_init(sc, ATH_RXBUF); |
869 | if (error != 0) | 854 | if (error != 0) |
870 | goto error_rx; | 855 | goto deinit; |
871 | 856 | ||
872 | ath9k_init_txpower_limits(sc); | 857 | ath9k_init_txpower_limits(sc); |
873 | 858 | ||
@@ -881,19 +866,19 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, | |||
881 | /* Register with mac80211 */ | 866 | /* Register with mac80211 */ |
882 | error = ieee80211_register_hw(hw); | 867 | error = ieee80211_register_hw(hw); |
883 | if (error) | 868 | if (error) |
884 | goto error_register; | 869 | goto rx_cleanup; |
885 | 870 | ||
886 | error = ath9k_init_debug(ah); | 871 | error = ath9k_init_debug(ah); |
887 | if (error) { | 872 | if (error) { |
888 | ath_err(common, "Unable to create debugfs files\n"); | 873 | ath_err(common, "Unable to create debugfs files\n"); |
889 | goto error_world; | 874 | goto unregister; |
890 | } | 875 | } |
891 | 876 | ||
892 | /* Handle world regulatory */ | 877 | /* Handle world regulatory */ |
893 | if (!ath_is_world_regd(reg)) { | 878 | if (!ath_is_world_regd(reg)) { |
894 | error = regulatory_hint(hw->wiphy, reg->alpha2); | 879 | error = regulatory_hint(hw->wiphy, reg->alpha2); |
895 | if (error) | 880 | if (error) |
896 | goto error_world; | 881 | goto unregister; |
897 | } | 882 | } |
898 | 883 | ||
899 | ath_init_leds(sc); | 884 | ath_init_leds(sc); |
@@ -901,17 +886,12 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, | |||
901 | 886 | ||
902 | return 0; | 887 | return 0; |
903 | 888 | ||
904 | error_world: | 889 | unregister: |
905 | ieee80211_unregister_hw(hw); | 890 | ieee80211_unregister_hw(hw); |
906 | error_register: | 891 | rx_cleanup: |
907 | ath_rx_cleanup(sc); | 892 | ath_rx_cleanup(sc); |
908 | error_rx: | 893 | deinit: |
909 | ath_tx_cleanup(sc); | ||
910 | error_tx: | ||
911 | /* Nothing */ | ||
912 | error_regd: | ||
913 | ath9k_deinit_softc(sc); | 894 | ath9k_deinit_softc(sc); |
914 | error_init: | ||
915 | return error; | 895 | return error; |
916 | } | 896 | } |
917 | 897 | ||
@@ -923,12 +903,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
923 | { | 903 | { |
924 | int i = 0; | 904 | int i = 0; |
925 | 905 | ||
926 | if (sc->sbands[IEEE80211_BAND_2GHZ].channels) | ||
927 | kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); | ||
928 | |||
929 | if (sc->sbands[IEEE80211_BAND_5GHZ].channels) | ||
930 | kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels); | ||
931 | |||
932 | ath9k_deinit_btcoex(sc); | 906 | ath9k_deinit_btcoex(sc); |
933 | 907 | ||
934 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | 908 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) |
@@ -940,8 +914,11 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
940 | sc->dfs_detector->exit(sc->dfs_detector); | 914 | sc->dfs_detector->exit(sc->dfs_detector); |
941 | 915 | ||
942 | ath9k_eeprom_release(sc); | 916 | ath9k_eeprom_release(sc); |
943 | kfree(sc->sc_ah); | 917 | |
944 | sc->sc_ah = NULL; | 918 | if (sc->rfs_chan_spec_scan) { |
919 | relay_close(sc->rfs_chan_spec_scan); | ||
920 | sc->rfs_chan_spec_scan = NULL; | ||
921 | } | ||
945 | } | 922 | } |
946 | 923 | ||
947 | void ath9k_deinit_device(struct ath_softc *sc) | 924 | void ath9k_deinit_device(struct ath_softc *sc) |
@@ -957,22 +934,9 @@ void ath9k_deinit_device(struct ath_softc *sc) | |||
957 | 934 | ||
958 | ieee80211_unregister_hw(hw); | 935 | ieee80211_unregister_hw(hw); |
959 | ath_rx_cleanup(sc); | 936 | ath_rx_cleanup(sc); |
960 | ath_tx_cleanup(sc); | ||
961 | ath9k_deinit_softc(sc); | 937 | ath9k_deinit_softc(sc); |
962 | } | 938 | } |
963 | 939 | ||
964 | void ath_descdma_cleanup(struct ath_softc *sc, | ||
965 | struct ath_descdma *dd, | ||
966 | struct list_head *head) | ||
967 | { | ||
968 | dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, | ||
969 | dd->dd_desc_paddr); | ||
970 | |||
971 | INIT_LIST_HEAD(head); | ||
972 | kfree(dd->dd_bufptr); | ||
973 | memset(dd, 0, sizeof(*dd)); | ||
974 | } | ||
975 | |||
976 | /************************/ | 940 | /************************/ |
977 | /* Module Hooks */ | 941 | /* Module Hooks */ |
978 | /************************/ | 942 | /************************/ |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 4a745e68dd94..1ff817061ebc 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -226,7 +226,8 @@ enum ath9k_phyerr { | |||
226 | ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35, | 226 | ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35, |
227 | ATH9K_PHYERR_HT_RATE_ILLEGAL = 36, | 227 | ATH9K_PHYERR_HT_RATE_ILLEGAL = 36, |
228 | 228 | ||
229 | ATH9K_PHYERR_MAX = 37, | 229 | ATH9K_PHYERR_SPECTRAL = 38, |
230 | ATH9K_PHYERR_MAX = 39, | ||
230 | }; | 231 | }; |
231 | 232 | ||
232 | struct ath_desc { | 233 | struct ath_desc { |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index be30a9af1528..4b72b660f180 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -182,7 +182,7 @@ static void ath_restart_work(struct ath_softc *sc) | |||
182 | ath_start_ani(sc); | 182 | ath_start_ani(sc); |
183 | } | 183 | } |
184 | 184 | ||
185 | static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) | 185 | static bool ath_prepare_reset(struct ath_softc *sc) |
186 | { | 186 | { |
187 | struct ath_hw *ah = sc->sc_ah; | 187 | struct ath_hw *ah = sc->sc_ah; |
188 | bool ret = true; | 188 | bool ret = true; |
@@ -196,20 +196,12 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) | |||
196 | ath9k_debug_samp_bb_mac(sc); | 196 | ath9k_debug_samp_bb_mac(sc); |
197 | ath9k_hw_disable_interrupts(ah); | 197 | ath9k_hw_disable_interrupts(ah); |
198 | 198 | ||
199 | if (!ath_stoprecv(sc)) | 199 | if (!ath_drain_all_txq(sc)) |
200 | ret = false; | 200 | ret = false; |
201 | 201 | ||
202 | if (!ath_drain_all_txq(sc, retry_tx)) | 202 | if (!ath_stoprecv(sc)) |
203 | ret = false; | 203 | ret = false; |
204 | 204 | ||
205 | if (!flush) { | ||
206 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | ||
207 | ath_rx_tasklet(sc, 1, true); | ||
208 | ath_rx_tasklet(sc, 1, false); | ||
209 | } else { | ||
210 | ath_flushrecv(sc); | ||
211 | } | ||
212 | |||
213 | return ret; | 205 | return ret; |
214 | } | 206 | } |
215 | 207 | ||
@@ -255,18 +247,17 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
255 | return true; | 247 | return true; |
256 | } | 248 | } |
257 | 249 | ||
258 | static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, | 250 | static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) |
259 | bool retry_tx) | ||
260 | { | 251 | { |
261 | struct ath_hw *ah = sc->sc_ah; | 252 | struct ath_hw *ah = sc->sc_ah; |
262 | struct ath_common *common = ath9k_hw_common(ah); | 253 | struct ath_common *common = ath9k_hw_common(ah); |
263 | struct ath9k_hw_cal_data *caldata = NULL; | 254 | struct ath9k_hw_cal_data *caldata = NULL; |
264 | bool fastcc = true; | 255 | bool fastcc = true; |
265 | bool flush = false; | ||
266 | int r; | 256 | int r; |
267 | 257 | ||
268 | __ath_cancel_work(sc); | 258 | __ath_cancel_work(sc); |
269 | 259 | ||
260 | tasklet_disable(&sc->intr_tq); | ||
270 | spin_lock_bh(&sc->sc_pcu_lock); | 261 | spin_lock_bh(&sc->sc_pcu_lock); |
271 | 262 | ||
272 | if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { | 263 | if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { |
@@ -276,11 +267,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, | |||
276 | 267 | ||
277 | if (!hchan) { | 268 | if (!hchan) { |
278 | fastcc = false; | 269 | fastcc = false; |
279 | flush = true; | ||
280 | hchan = ah->curchan; | 270 | hchan = ah->curchan; |
281 | } | 271 | } |
282 | 272 | ||
283 | if (!ath_prepare_reset(sc, retry_tx, flush)) | 273 | if (!ath_prepare_reset(sc)) |
284 | fastcc = false; | 274 | fastcc = false; |
285 | 275 | ||
286 | ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n", | 276 | ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n", |
@@ -302,6 +292,8 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, | |||
302 | 292 | ||
303 | out: | 293 | out: |
304 | spin_unlock_bh(&sc->sc_pcu_lock); | 294 | spin_unlock_bh(&sc->sc_pcu_lock); |
295 | tasklet_enable(&sc->intr_tq); | ||
296 | |||
305 | return r; | 297 | return r; |
306 | } | 298 | } |
307 | 299 | ||
@@ -319,7 +311,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
319 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) | 311 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) |
320 | return -EIO; | 312 | return -EIO; |
321 | 313 | ||
322 | r = ath_reset_internal(sc, hchan, false); | 314 | r = ath_reset_internal(sc, hchan); |
323 | 315 | ||
324 | return r; | 316 | return r; |
325 | } | 317 | } |
@@ -549,23 +541,21 @@ chip_reset: | |||
549 | #undef SCHED_INTR | 541 | #undef SCHED_INTR |
550 | } | 542 | } |
551 | 543 | ||
552 | static int ath_reset(struct ath_softc *sc, bool retry_tx) | 544 | static int ath_reset(struct ath_softc *sc) |
553 | { | 545 | { |
554 | int r; | 546 | int i, r; |
555 | 547 | ||
556 | ath9k_ps_wakeup(sc); | 548 | ath9k_ps_wakeup(sc); |
557 | 549 | ||
558 | r = ath_reset_internal(sc, NULL, retry_tx); | 550 | r = ath_reset_internal(sc, NULL); |
559 | 551 | ||
560 | if (retry_tx) { | 552 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { |
561 | int i; | 553 | if (!ATH_TXQ_SETUP(sc, i)) |
562 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | 554 | continue; |
563 | if (ATH_TXQ_SETUP(sc, i)) { | 555 | |
564 | spin_lock_bh(&sc->tx.txq[i].axq_lock); | 556 | spin_lock_bh(&sc->tx.txq[i].axq_lock); |
565 | ath_txq_schedule(sc, &sc->tx.txq[i]); | 557 | ath_txq_schedule(sc, &sc->tx.txq[i]); |
566 | spin_unlock_bh(&sc->tx.txq[i].axq_lock); | 558 | spin_unlock_bh(&sc->tx.txq[i].axq_lock); |
567 | } | ||
568 | } | ||
569 | } | 559 | } |
570 | 560 | ||
571 | ath9k_ps_restore(sc); | 561 | ath9k_ps_restore(sc); |
@@ -586,7 +576,7 @@ void ath_reset_work(struct work_struct *work) | |||
586 | { | 576 | { |
587 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); | 577 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); |
588 | 578 | ||
589 | ath_reset(sc, true); | 579 | ath_reset(sc); |
590 | } | 580 | } |
591 | 581 | ||
592 | /**********************/ | 582 | /**********************/ |
@@ -804,7 +794,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
804 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); | 794 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); |
805 | } | 795 | } |
806 | 796 | ||
807 | ath_prepare_reset(sc, false, true); | 797 | ath_prepare_reset(sc); |
808 | 798 | ||
809 | if (sc->rx.frag) { | 799 | if (sc->rx.frag) { |
810 | dev_kfree_skb_any(sc->rx.frag); | 800 | dev_kfree_skb_any(sc->rx.frag); |
@@ -1075,6 +1065,86 @@ static void ath9k_disable_ps(struct ath_softc *sc) | |||
1075 | ath_dbg(common, PS, "PowerSave disabled\n"); | 1065 | ath_dbg(common, PS, "PowerSave disabled\n"); |
1076 | } | 1066 | } |
1077 | 1067 | ||
1068 | void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw) | ||
1069 | { | ||
1070 | struct ath_softc *sc = hw->priv; | ||
1071 | struct ath_hw *ah = sc->sc_ah; | ||
1072 | struct ath_common *common = ath9k_hw_common(ah); | ||
1073 | u32 rxfilter; | ||
1074 | |||
1075 | if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { | ||
1076 | ath_err(common, "spectrum analyzer not implemented on this hardware\n"); | ||
1077 | return; | ||
1078 | } | ||
1079 | |||
1080 | ath9k_ps_wakeup(sc); | ||
1081 | rxfilter = ath9k_hw_getrxfilter(ah); | ||
1082 | ath9k_hw_setrxfilter(ah, rxfilter | | ||
1083 | ATH9K_RX_FILTER_PHYRADAR | | ||
1084 | ATH9K_RX_FILTER_PHYERR); | ||
1085 | |||
1086 | /* TODO: usually this should not be neccesary, but for some reason | ||
1087 | * (or in some mode?) the trigger must be called after the | ||
1088 | * configuration, otherwise the register will have its values reset | ||
1089 | * (on my ar9220 to value 0x01002310) | ||
1090 | */ | ||
1091 | ath9k_spectral_scan_config(hw, sc->spectral_mode); | ||
1092 | ath9k_hw_ops(ah)->spectral_scan_trigger(ah); | ||
1093 | ath9k_ps_restore(sc); | ||
1094 | } | ||
1095 | |||
1096 | int ath9k_spectral_scan_config(struct ieee80211_hw *hw, | ||
1097 | enum spectral_mode spectral_mode) | ||
1098 | { | ||
1099 | struct ath_softc *sc = hw->priv; | ||
1100 | struct ath_hw *ah = sc->sc_ah; | ||
1101 | struct ath_common *common = ath9k_hw_common(ah); | ||
1102 | struct ath_spec_scan param; | ||
1103 | |||
1104 | if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { | ||
1105 | ath_err(common, "spectrum analyzer not implemented on this hardware\n"); | ||
1106 | return -1; | ||
1107 | } | ||
1108 | |||
1109 | /* NOTE: this will generate a few samples ... | ||
1110 | * | ||
1111 | * TODO: review default parameters, and/or define an interface to set | ||
1112 | * them. | ||
1113 | */ | ||
1114 | param.enabled = 1; | ||
1115 | param.short_repeat = true; | ||
1116 | param.count = 8; | ||
1117 | param.endless = false; | ||
1118 | param.period = 0xFF; | ||
1119 | param.fft_period = 0xF; | ||
1120 | |||
1121 | switch (spectral_mode) { | ||
1122 | case SPECTRAL_DISABLED: | ||
1123 | param.enabled = 0; | ||
1124 | break; | ||
1125 | case SPECTRAL_BACKGROUND: | ||
1126 | /* send endless samples. | ||
1127 | * TODO: is this really useful for "background"? | ||
1128 | */ | ||
1129 | param.endless = 1; | ||
1130 | break; | ||
1131 | case SPECTRAL_CHANSCAN: | ||
1132 | break; | ||
1133 | case SPECTRAL_MANUAL: | ||
1134 | break; | ||
1135 | default: | ||
1136 | return -1; | ||
1137 | } | ||
1138 | |||
1139 | ath9k_ps_wakeup(sc); | ||
1140 | ath9k_hw_ops(ah)->spectral_scan_config(ah, ¶m); | ||
1141 | ath9k_ps_restore(sc); | ||
1142 | |||
1143 | sc->spectral_mode = spectral_mode; | ||
1144 | |||
1145 | return 0; | ||
1146 | } | ||
1147 | |||
1078 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | 1148 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) |
1079 | { | 1149 | { |
1080 | struct ath_softc *sc = hw->priv; | 1150 | struct ath_softc *sc = hw->priv; |
@@ -1188,6 +1258,11 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1188 | */ | 1258 | */ |
1189 | if (old_pos >= 0) | 1259 | if (old_pos >= 0) |
1190 | ath_update_survey_nf(sc, old_pos); | 1260 | ath_update_survey_nf(sc, old_pos); |
1261 | |||
1262 | /* perform spectral scan if requested. */ | ||
1263 | if (sc->scanning && sc->spectral_mode == SPECTRAL_CHANSCAN) | ||
1264 | ath9k_spectral_scan_trigger(hw); | ||
1265 | |||
1191 | } | 1266 | } |
1192 | 1267 | ||
1193 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1268 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
@@ -1610,7 +1685,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1610 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1685 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1611 | ath9k_ps_restore(sc); | 1686 | ath9k_ps_restore(sc); |
1612 | break; | 1687 | break; |
1613 | case IEEE80211_AMPDU_TX_STOP: | 1688 | case IEEE80211_AMPDU_TX_STOP_CONT: |
1689 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
1690 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
1614 | ath9k_ps_wakeup(sc); | 1691 | ath9k_ps_wakeup(sc); |
1615 | ath_tx_aggr_stop(sc, sta, tid); | 1692 | ath_tx_aggr_stop(sc, sta, tid); |
1616 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1693 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
@@ -1729,11 +1806,11 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) | |||
1729 | if (drop) { | 1806 | if (drop) { |
1730 | ath9k_ps_wakeup(sc); | 1807 | ath9k_ps_wakeup(sc); |
1731 | spin_lock_bh(&sc->sc_pcu_lock); | 1808 | spin_lock_bh(&sc->sc_pcu_lock); |
1732 | drain_txq = ath_drain_all_txq(sc, false); | 1809 | drain_txq = ath_drain_all_txq(sc); |
1733 | spin_unlock_bh(&sc->sc_pcu_lock); | 1810 | spin_unlock_bh(&sc->sc_pcu_lock); |
1734 | 1811 | ||
1735 | if (!drain_txq) | 1812 | if (!drain_txq) |
1736 | ath_reset(sc, false); | 1813 | ath_reset(sc); |
1737 | 1814 | ||
1738 | ath9k_ps_restore(sc); | 1815 | ath9k_ps_restore(sc); |
1739 | ieee80211_wake_queues(hw); | 1816 | ieee80211_wake_queues(hw); |
@@ -1833,6 +1910,9 @@ static u32 fill_chainmask(u32 cap, u32 new) | |||
1833 | 1910 | ||
1834 | static bool validate_antenna_mask(struct ath_hw *ah, u32 val) | 1911 | static bool validate_antenna_mask(struct ath_hw *ah, u32 val) |
1835 | { | 1912 | { |
1913 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
1914 | return true; | ||
1915 | |||
1836 | switch (val & 0x7) { | 1916 | switch (val & 0x7) { |
1837 | case 0x1: | 1917 | case 0x1: |
1838 | case 0x3: | 1918 | case 0x3: |
@@ -2238,6 +2318,19 @@ static void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) | |||
2238 | } | 2318 | } |
2239 | 2319 | ||
2240 | #endif | 2320 | #endif |
2321 | static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | ||
2322 | { | ||
2323 | struct ath_softc *sc = hw->priv; | ||
2324 | |||
2325 | sc->scanning = 1; | ||
2326 | } | ||
2327 | |||
2328 | static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | ||
2329 | { | ||
2330 | struct ath_softc *sc = hw->priv; | ||
2331 | |||
2332 | sc->scanning = 0; | ||
2333 | } | ||
2241 | 2334 | ||
2242 | struct ieee80211_ops ath9k_ops = { | 2335 | struct ieee80211_ops ath9k_ops = { |
2243 | .tx = ath9k_tx, | 2336 | .tx = ath9k_tx, |
@@ -2284,4 +2377,6 @@ struct ieee80211_ops ath9k_ops = { | |||
2284 | .sta_add_debugfs = ath9k_sta_add_debugfs, | 2377 | .sta_add_debugfs = ath9k_sta_add_debugfs, |
2285 | .sta_remove_debugfs = ath9k_sta_remove_debugfs, | 2378 | .sta_remove_debugfs = ath9k_sta_remove_debugfs, |
2286 | #endif | 2379 | #endif |
2380 | .sw_scan_start = ath9k_sw_scan_start, | ||
2381 | .sw_scan_complete = ath9k_sw_scan_complete, | ||
2287 | }; | 2382 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 5c02702f21e7..d2074334ec9b 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -438,7 +438,7 @@ int ath_mci_setup(struct ath_softc *sc) | |||
438 | struct ath_mci_buf *buf = &mci->sched_buf; | 438 | struct ath_mci_buf *buf = &mci->sched_buf; |
439 | int ret; | 439 | int ret; |
440 | 440 | ||
441 | buf->bf_addr = dma_alloc_coherent(sc->dev, | 441 | buf->bf_addr = dmam_alloc_coherent(sc->dev, |
442 | ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE, | 442 | ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE, |
443 | &buf->bf_paddr, GFP_KERNEL); | 443 | &buf->bf_paddr, GFP_KERNEL); |
444 | 444 | ||
@@ -477,11 +477,6 @@ void ath_mci_cleanup(struct ath_softc *sc) | |||
477 | struct ath_mci_coex *mci = &sc->mci_coex; | 477 | struct ath_mci_coex *mci = &sc->mci_coex; |
478 | struct ath_mci_buf *buf = &mci->sched_buf; | 478 | struct ath_mci_buf *buf = &mci->sched_buf; |
479 | 479 | ||
480 | if (buf->bf_addr) | ||
481 | dma_free_coherent(sc->dev, | ||
482 | ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE, | ||
483 | buf->bf_addr, buf->bf_paddr); | ||
484 | |||
485 | ar9003_mci_cleanup(ah); | 480 | ar9003_mci_cleanup(ah); |
486 | 481 | ||
487 | ath_dbg(common, MCI, "MCI De-Initialized\n"); | 482 | ath_dbg(common, MCI, "MCI De-Initialized\n"); |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 7ae73fbd9136..0e0d39583837 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -147,7 +147,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = { | |||
147 | 147 | ||
148 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 148 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
149 | { | 149 | { |
150 | void __iomem *mem; | ||
151 | struct ath_softc *sc; | 150 | struct ath_softc *sc; |
152 | struct ieee80211_hw *hw; | 151 | struct ieee80211_hw *hw; |
153 | u8 csz; | 152 | u8 csz; |
@@ -155,19 +154,19 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
155 | int ret = 0; | 154 | int ret = 0; |
156 | char hw_name[64]; | 155 | char hw_name[64]; |
157 | 156 | ||
158 | if (pci_enable_device(pdev)) | 157 | if (pcim_enable_device(pdev)) |
159 | return -EIO; | 158 | return -EIO; |
160 | 159 | ||
161 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | 160 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
162 | if (ret) { | 161 | if (ret) { |
163 | pr_err("32-bit DMA not available\n"); | 162 | pr_err("32-bit DMA not available\n"); |
164 | goto err_dma; | 163 | return ret; |
165 | } | 164 | } |
166 | 165 | ||
167 | ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | 166 | ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); |
168 | if (ret) { | 167 | if (ret) { |
169 | pr_err("32-bit DMA consistent DMA enable failed\n"); | 168 | pr_err("32-bit DMA consistent DMA enable failed\n"); |
170 | goto err_dma; | 169 | return ret; |
171 | } | 170 | } |
172 | 171 | ||
173 | /* | 172 | /* |
@@ -203,25 +202,16 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
203 | if ((val & 0x0000ff00) != 0) | 202 | if ((val & 0x0000ff00) != 0) |
204 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | 203 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); |
205 | 204 | ||
206 | ret = pci_request_region(pdev, 0, "ath9k"); | 205 | ret = pcim_iomap_regions(pdev, BIT(0), "ath9k"); |
207 | if (ret) { | 206 | if (ret) { |
208 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); | 207 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); |
209 | ret = -ENODEV; | 208 | return -ENODEV; |
210 | goto err_region; | ||
211 | } | ||
212 | |||
213 | mem = pci_iomap(pdev, 0, 0); | ||
214 | if (!mem) { | ||
215 | pr_err("PCI memory map error\n") ; | ||
216 | ret = -EIO; | ||
217 | goto err_iomap; | ||
218 | } | 209 | } |
219 | 210 | ||
220 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); | 211 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); |
221 | if (!hw) { | 212 | if (!hw) { |
222 | dev_err(&pdev->dev, "No memory for ieee80211_hw\n"); | 213 | dev_err(&pdev->dev, "No memory for ieee80211_hw\n"); |
223 | ret = -ENOMEM; | 214 | return -ENOMEM; |
224 | goto err_alloc_hw; | ||
225 | } | 215 | } |
226 | 216 | ||
227 | SET_IEEE80211_DEV(hw, &pdev->dev); | 217 | SET_IEEE80211_DEV(hw, &pdev->dev); |
@@ -230,7 +220,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
230 | sc = hw->priv; | 220 | sc = hw->priv; |
231 | sc->hw = hw; | 221 | sc->hw = hw; |
232 | sc->dev = &pdev->dev; | 222 | sc->dev = &pdev->dev; |
233 | sc->mem = mem; | 223 | sc->mem = pcim_iomap_table(pdev)[0]; |
234 | 224 | ||
235 | /* Will be cleared in ath9k_start() */ | 225 | /* Will be cleared in ath9k_start() */ |
236 | set_bit(SC_OP_INVALID, &sc->sc_flags); | 226 | set_bit(SC_OP_INVALID, &sc->sc_flags); |
@@ -251,7 +241,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
251 | 241 | ||
252 | ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name)); | 242 | ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name)); |
253 | wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", | 243 | wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", |
254 | hw_name, (unsigned long)mem, pdev->irq); | 244 | hw_name, (unsigned long)sc->mem, pdev->irq); |
255 | 245 | ||
256 | return 0; | 246 | return 0; |
257 | 247 | ||
@@ -259,14 +249,6 @@ err_init: | |||
259 | free_irq(sc->irq, sc); | 249 | free_irq(sc->irq, sc); |
260 | err_irq: | 250 | err_irq: |
261 | ieee80211_free_hw(hw); | 251 | ieee80211_free_hw(hw); |
262 | err_alloc_hw: | ||
263 | pci_iounmap(pdev, mem); | ||
264 | err_iomap: | ||
265 | pci_release_region(pdev, 0); | ||
266 | err_region: | ||
267 | /* Nothing */ | ||
268 | err_dma: | ||
269 | pci_disable_device(pdev); | ||
270 | return ret; | 252 | return ret; |
271 | } | 253 | } |
272 | 254 | ||
@@ -274,17 +256,12 @@ static void ath_pci_remove(struct pci_dev *pdev) | |||
274 | { | 256 | { |
275 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 257 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
276 | struct ath_softc *sc = hw->priv; | 258 | struct ath_softc *sc = hw->priv; |
277 | void __iomem *mem = sc->mem; | ||
278 | 259 | ||
279 | if (!is_ath9k_unloaded) | 260 | if (!is_ath9k_unloaded) |
280 | sc->sc_ah->ah_flags |= AH_UNPLUGGED; | 261 | sc->sc_ah->ah_flags |= AH_UNPLUGGED; |
281 | ath9k_deinit_device(sc); | 262 | ath9k_deinit_device(sc); |
282 | free_irq(sc->irq, sc); | 263 | free_irq(sc->irq, sc); |
283 | ieee80211_free_hw(sc->hw); | 264 | ieee80211_free_hw(sc->hw); |
284 | |||
285 | pci_iounmap(pdev, mem); | ||
286 | pci_disable_device(pdev); | ||
287 | pci_release_region(pdev, 0); | ||
288 | } | 265 | } |
289 | 266 | ||
290 | #ifdef CONFIG_PM_SLEEP | 267 | #ifdef CONFIG_PM_SLEEP |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index d4df98a938bf..d7c129bb571b 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/dma-mapping.h> | 17 | #include <linux/dma-mapping.h> |
18 | #include <linux/relay.h> | ||
18 | #include "ath9k.h" | 19 | #include "ath9k.h" |
19 | #include "ar9003_mac.h" | 20 | #include "ar9003_mac.h" |
20 | 21 | ||
@@ -180,11 +181,6 @@ static void ath_rx_edma_cleanup(struct ath_softc *sc) | |||
180 | bf->bf_mpdu = NULL; | 181 | bf->bf_mpdu = NULL; |
181 | } | 182 | } |
182 | } | 183 | } |
183 | |||
184 | INIT_LIST_HEAD(&sc->rx.rxbuf); | ||
185 | |||
186 | kfree(sc->rx.rx_bufptr); | ||
187 | sc->rx.rx_bufptr = NULL; | ||
188 | } | 184 | } |
189 | 185 | ||
190 | static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size) | 186 | static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size) |
@@ -211,12 +207,11 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) | |||
211 | ah->caps.rx_hp_qdepth); | 207 | ah->caps.rx_hp_qdepth); |
212 | 208 | ||
213 | size = sizeof(struct ath_buf) * nbufs; | 209 | size = sizeof(struct ath_buf) * nbufs; |
214 | bf = kzalloc(size, GFP_KERNEL); | 210 | bf = devm_kzalloc(sc->dev, size, GFP_KERNEL); |
215 | if (!bf) | 211 | if (!bf) |
216 | return -ENOMEM; | 212 | return -ENOMEM; |
217 | 213 | ||
218 | INIT_LIST_HEAD(&sc->rx.rxbuf); | 214 | INIT_LIST_HEAD(&sc->rx.rxbuf); |
219 | sc->rx.rx_bufptr = bf; | ||
220 | 215 | ||
221 | for (i = 0; i < nbufs; i++, bf++) { | 216 | for (i = 0; i < nbufs; i++, bf++) { |
222 | skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_KERNEL); | 217 | skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_KERNEL); |
@@ -254,8 +249,6 @@ rx_init_fail: | |||
254 | 249 | ||
255 | static void ath_edma_start_recv(struct ath_softc *sc) | 250 | static void ath_edma_start_recv(struct ath_softc *sc) |
256 | { | 251 | { |
257 | spin_lock_bh(&sc->rx.rxbuflock); | ||
258 | |||
259 | ath9k_hw_rxena(sc->sc_ah); | 252 | ath9k_hw_rxena(sc->sc_ah); |
260 | 253 | ||
261 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP, | 254 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP, |
@@ -267,8 +260,6 @@ static void ath_edma_start_recv(struct ath_softc *sc) | |||
267 | ath_opmode_init(sc); | 260 | ath_opmode_init(sc); |
268 | 261 | ||
269 | ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); | 262 | ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); |
270 | |||
271 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
272 | } | 263 | } |
273 | 264 | ||
274 | static void ath_edma_stop_recv(struct ath_softc *sc) | 265 | static void ath_edma_stop_recv(struct ath_softc *sc) |
@@ -285,8 +276,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
285 | int error = 0; | 276 | int error = 0; |
286 | 277 | ||
287 | spin_lock_init(&sc->sc_pcu_lock); | 278 | spin_lock_init(&sc->sc_pcu_lock); |
288 | spin_lock_init(&sc->rx.rxbuflock); | ||
289 | clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); | ||
290 | 279 | ||
291 | common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + | 280 | common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + |
292 | sc->sc_ah->caps.rx_status_len; | 281 | sc->sc_ah->caps.rx_status_len; |
@@ -363,9 +352,6 @@ void ath_rx_cleanup(struct ath_softc *sc) | |||
363 | bf->bf_mpdu = NULL; | 352 | bf->bf_mpdu = NULL; |
364 | } | 353 | } |
365 | } | 354 | } |
366 | |||
367 | if (sc->rx.rxdma.dd_desc_len != 0) | ||
368 | ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf); | ||
369 | } | 355 | } |
370 | } | 356 | } |
371 | 357 | ||
@@ -447,7 +433,6 @@ int ath_startrecv(struct ath_softc *sc) | |||
447 | return 0; | 433 | return 0; |
448 | } | 434 | } |
449 | 435 | ||
450 | spin_lock_bh(&sc->rx.rxbuflock); | ||
451 | if (list_empty(&sc->rx.rxbuf)) | 436 | if (list_empty(&sc->rx.rxbuf)) |
452 | goto start_recv; | 437 | goto start_recv; |
453 | 438 | ||
@@ -468,26 +453,31 @@ start_recv: | |||
468 | ath_opmode_init(sc); | 453 | ath_opmode_init(sc); |
469 | ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); | 454 | ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); |
470 | 455 | ||
471 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
472 | |||
473 | return 0; | 456 | return 0; |
474 | } | 457 | } |
475 | 458 | ||
459 | static void ath_flushrecv(struct ath_softc *sc) | ||
460 | { | ||
461 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | ||
462 | ath_rx_tasklet(sc, 1, true); | ||
463 | ath_rx_tasklet(sc, 1, false); | ||
464 | } | ||
465 | |||
476 | bool ath_stoprecv(struct ath_softc *sc) | 466 | bool ath_stoprecv(struct ath_softc *sc) |
477 | { | 467 | { |
478 | struct ath_hw *ah = sc->sc_ah; | 468 | struct ath_hw *ah = sc->sc_ah; |
479 | bool stopped, reset = false; | 469 | bool stopped, reset = false; |
480 | 470 | ||
481 | spin_lock_bh(&sc->rx.rxbuflock); | ||
482 | ath9k_hw_abortpcurecv(ah); | 471 | ath9k_hw_abortpcurecv(ah); |
483 | ath9k_hw_setrxfilter(ah, 0); | 472 | ath9k_hw_setrxfilter(ah, 0); |
484 | stopped = ath9k_hw_stopdmarecv(ah, &reset); | 473 | stopped = ath9k_hw_stopdmarecv(ah, &reset); |
485 | 474 | ||
475 | ath_flushrecv(sc); | ||
476 | |||
486 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 477 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
487 | ath_edma_stop_recv(sc); | 478 | ath_edma_stop_recv(sc); |
488 | else | 479 | else |
489 | sc->rx.rxlink = NULL; | 480 | sc->rx.rxlink = NULL; |
490 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
491 | 481 | ||
492 | if (!(ah->ah_flags & AH_UNPLUGGED) && | 482 | if (!(ah->ah_flags & AH_UNPLUGGED) && |
493 | unlikely(!stopped)) { | 483 | unlikely(!stopped)) { |
@@ -499,15 +489,6 @@ bool ath_stoprecv(struct ath_softc *sc) | |||
499 | return stopped && !reset; | 489 | return stopped && !reset; |
500 | } | 490 | } |
501 | 491 | ||
502 | void ath_flushrecv(struct ath_softc *sc) | ||
503 | { | ||
504 | set_bit(SC_OP_RXFLUSH, &sc->sc_flags); | ||
505 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | ||
506 | ath_rx_tasklet(sc, 1, true); | ||
507 | ath_rx_tasklet(sc, 1, false); | ||
508 | clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); | ||
509 | } | ||
510 | |||
511 | static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) | 492 | static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) |
512 | { | 493 | { |
513 | /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */ | 494 | /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */ |
@@ -744,6 +725,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | |||
744 | return NULL; | 725 | return NULL; |
745 | } | 726 | } |
746 | 727 | ||
728 | list_del(&bf->list); | ||
747 | if (!bf->bf_mpdu) | 729 | if (!bf->bf_mpdu) |
748 | return bf; | 730 | return bf; |
749 | 731 | ||
@@ -1034,6 +1016,108 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common, | |||
1034 | rxs->flag &= ~RX_FLAG_DECRYPTED; | 1016 | rxs->flag &= ~RX_FLAG_DECRYPTED; |
1035 | } | 1017 | } |
1036 | 1018 | ||
1019 | static s8 fix_rssi_inv_only(u8 rssi_val) | ||
1020 | { | ||
1021 | if (rssi_val == 128) | ||
1022 | rssi_val = 0; | ||
1023 | return (s8) rssi_val; | ||
1024 | } | ||
1025 | |||
1026 | |||
1027 | static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | ||
1028 | struct ath_rx_status *rs, u64 tsf) | ||
1029 | { | ||
1030 | #ifdef CONFIG_ATH_DEBUG | ||
1031 | struct ath_hw *ah = sc->sc_ah; | ||
1032 | u8 bins[SPECTRAL_HT20_NUM_BINS]; | ||
1033 | u8 *vdata = (u8 *)hdr; | ||
1034 | struct fft_sample_ht20 fft_sample; | ||
1035 | struct ath_radar_info *radar_info; | ||
1036 | struct ath_ht20_mag_info *mag_info; | ||
1037 | int len = rs->rs_datalen; | ||
1038 | int i, dc_pos; | ||
1039 | |||
1040 | /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer | ||
1041 | * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT | ||
1042 | * yet, but this is supposed to be possible as well. | ||
1043 | */ | ||
1044 | if (rs->rs_phyerr != ATH9K_PHYERR_RADAR && | ||
1045 | rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT && | ||
1046 | rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL) | ||
1047 | return; | ||
1048 | |||
1049 | /* Variation in the data length is possible and will be fixed later. | ||
1050 | * Note that we only support HT20 for now. | ||
1051 | * | ||
1052 | * TODO: add HT20_40 support as well. | ||
1053 | */ | ||
1054 | if ((len > SPECTRAL_HT20_TOTAL_DATA_LEN + 2) || | ||
1055 | (len < SPECTRAL_HT20_TOTAL_DATA_LEN - 1)) | ||
1056 | return; | ||
1057 | |||
1058 | /* check if spectral scan bit is set. This does not have to be checked | ||
1059 | * if received through a SPECTRAL phy error, but shouldn't hurt. | ||
1060 | */ | ||
1061 | radar_info = ((struct ath_radar_info *)&vdata[len]) - 1; | ||
1062 | if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) | ||
1063 | return; | ||
1064 | |||
1065 | fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20; | ||
1066 | fft_sample.tlv.length = sizeof(fft_sample) - sizeof(fft_sample.tlv); | ||
1067 | |||
1068 | fft_sample.freq = ah->curchan->chan->center_freq; | ||
1069 | fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | ||
1070 | fft_sample.noise = ah->noise; | ||
1071 | |||
1072 | switch (len - SPECTRAL_HT20_TOTAL_DATA_LEN) { | ||
1073 | case 0: | ||
1074 | /* length correct, nothing to do. */ | ||
1075 | memcpy(bins, vdata, SPECTRAL_HT20_NUM_BINS); | ||
1076 | break; | ||
1077 | case -1: | ||
1078 | /* first byte missing, duplicate it. */ | ||
1079 | memcpy(&bins[1], vdata, SPECTRAL_HT20_NUM_BINS - 1); | ||
1080 | bins[0] = vdata[0]; | ||
1081 | break; | ||
1082 | case 2: | ||
1083 | /* MAC added 2 extra bytes at bin 30 and 32, remove them. */ | ||
1084 | memcpy(bins, vdata, 30); | ||
1085 | bins[30] = vdata[31]; | ||
1086 | memcpy(&bins[31], &vdata[33], SPECTRAL_HT20_NUM_BINS - 31); | ||
1087 | break; | ||
1088 | case 1: | ||
1089 | /* MAC added 2 extra bytes AND first byte is missing. */ | ||
1090 | bins[0] = vdata[0]; | ||
1091 | memcpy(&bins[0], vdata, 30); | ||
1092 | bins[31] = vdata[31]; | ||
1093 | memcpy(&bins[32], &vdata[33], SPECTRAL_HT20_NUM_BINS - 32); | ||
1094 | break; | ||
1095 | default: | ||
1096 | return; | ||
1097 | } | ||
1098 | |||
1099 | /* DC value (value in the middle) is the blind spot of the spectral | ||
1100 | * sample and invalid, interpolate it. | ||
1101 | */ | ||
1102 | dc_pos = SPECTRAL_HT20_NUM_BINS / 2; | ||
1103 | bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2; | ||
1104 | |||
1105 | /* mag data is at the end of the frame, in front of radar_info */ | ||
1106 | mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1; | ||
1107 | |||
1108 | /* Apply exponent and grab further auxiliary information. */ | ||
1109 | for (i = 0; i < SPECTRAL_HT20_NUM_BINS; i++) | ||
1110 | fft_sample.data[i] = bins[i] << mag_info->max_exp; | ||
1111 | |||
1112 | fft_sample.max_magnitude = spectral_max_magnitude(mag_info->all_bins); | ||
1113 | fft_sample.max_index = spectral_max_index(mag_info->all_bins); | ||
1114 | fft_sample.bitmap_weight = spectral_bitmap_weight(mag_info->all_bins); | ||
1115 | fft_sample.tsf = tsf; | ||
1116 | |||
1117 | ath_debug_send_fft_sample(sc, &fft_sample.tlv); | ||
1118 | #endif | ||
1119 | } | ||
1120 | |||
1037 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 1121 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) |
1038 | { | 1122 | { |
1039 | struct ath_buf *bf; | 1123 | struct ath_buf *bf; |
@@ -1059,16 +1143,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1059 | dma_type = DMA_FROM_DEVICE; | 1143 | dma_type = DMA_FROM_DEVICE; |
1060 | 1144 | ||
1061 | qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; | 1145 | qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; |
1062 | spin_lock_bh(&sc->rx.rxbuflock); | ||
1063 | 1146 | ||
1064 | tsf = ath9k_hw_gettsf64(ah); | 1147 | tsf = ath9k_hw_gettsf64(ah); |
1065 | tsf_lower = tsf & 0xffffffff; | 1148 | tsf_lower = tsf & 0xffffffff; |
1066 | 1149 | ||
1067 | do { | 1150 | do { |
1068 | bool decrypt_error = false; | 1151 | bool decrypt_error = false; |
1069 | /* If handling rx interrupt and flush is in progress => exit */ | ||
1070 | if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0)) | ||
1071 | break; | ||
1072 | 1152 | ||
1073 | memset(&rs, 0, sizeof(rs)); | 1153 | memset(&rs, 0, sizeof(rs)); |
1074 | if (edma) | 1154 | if (edma) |
@@ -1111,15 +1191,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1111 | 1191 | ||
1112 | ath_debug_stat_rx(sc, &rs); | 1192 | ath_debug_stat_rx(sc, &rs); |
1113 | 1193 | ||
1114 | /* | ||
1115 | * If we're asked to flush receive queue, directly | ||
1116 | * chain it back at the queue without processing it. | ||
1117 | */ | ||
1118 | if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) { | ||
1119 | RX_STAT_INC(rx_drop_rxflush); | ||
1120 | goto requeue_drop_frag; | ||
1121 | } | ||
1122 | |||
1123 | memset(rxs, 0, sizeof(struct ieee80211_rx_status)); | 1194 | memset(rxs, 0, sizeof(struct ieee80211_rx_status)); |
1124 | 1195 | ||
1125 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; | 1196 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; |
@@ -1131,6 +1202,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1131 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) | 1202 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) |
1132 | rxs->mactime += 0x100000000ULL; | 1203 | rxs->mactime += 0x100000000ULL; |
1133 | 1204 | ||
1205 | if ((rs.rs_status & ATH9K_RXERR_PHY)) | ||
1206 | ath_process_fft(sc, hdr, &rs, rxs->mactime); | ||
1207 | |||
1134 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | 1208 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, |
1135 | rxs, &decrypt_error); | 1209 | rxs, &decrypt_error); |
1136 | if (retval) | 1210 | if (retval) |
@@ -1254,19 +1328,18 @@ requeue_drop_frag: | |||
1254 | sc->rx.frag = NULL; | 1328 | sc->rx.frag = NULL; |
1255 | } | 1329 | } |
1256 | requeue: | 1330 | requeue: |
1331 | list_add_tail(&bf->list, &sc->rx.rxbuf); | ||
1332 | if (flush) | ||
1333 | continue; | ||
1334 | |||
1257 | if (edma) { | 1335 | if (edma) { |
1258 | list_add_tail(&bf->list, &sc->rx.rxbuf); | ||
1259 | ath_rx_edma_buf_link(sc, qtype); | 1336 | ath_rx_edma_buf_link(sc, qtype); |
1260 | } else { | 1337 | } else { |
1261 | list_move_tail(&bf->list, &sc->rx.rxbuf); | ||
1262 | ath_rx_buf_link(sc, bf); | 1338 | ath_rx_buf_link(sc, bf); |
1263 | if (!flush) | 1339 | ath9k_hw_rxena(ah); |
1264 | ath9k_hw_rxena(ah); | ||
1265 | } | 1340 | } |
1266 | } while (1); | 1341 | } while (1); |
1267 | 1342 | ||
1268 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
1269 | |||
1270 | if (!(ah->imask & ATH9K_INT_RXEOL)) { | 1343 | if (!(ah->imask & ATH9K_INT_RXEOL)) { |
1271 | ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN); | 1344 | ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN); |
1272 | ath9k_hw_set_interrupts(ah); | 1345 | ath9k_hw_set_interrupts(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index ad3c82c09177..5929850649f0 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -789,6 +789,7 @@ | |||
789 | #define AR_SREV_REVISION_9271_11 1 | 789 | #define AR_SREV_REVISION_9271_11 1 |
790 | #define AR_SREV_VERSION_9300 0x1c0 | 790 | #define AR_SREV_VERSION_9300 0x1c0 |
791 | #define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */ | 791 | #define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */ |
792 | #define AR_SREV_REVISION_9300_22 3 | ||
792 | #define AR_SREV_VERSION_9330 0x200 | 793 | #define AR_SREV_VERSION_9330 0x200 |
793 | #define AR_SREV_REVISION_9330_10 0 | 794 | #define AR_SREV_REVISION_9330_10 0 |
794 | #define AR_SREV_REVISION_9330_11 1 | 795 | #define AR_SREV_REVISION_9330_11 1 |
@@ -869,6 +870,9 @@ | |||
869 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) | 870 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) |
870 | #define AR_SREV_9300_20_OR_LATER(_ah) \ | 871 | #define AR_SREV_9300_20_OR_LATER(_ah) \ |
871 | ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300) | 872 | ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300) |
873 | #define AR_SREV_9300_22(_ah) \ | ||
874 | (AR_SREV_9300(ah) && \ | ||
875 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9300_22)) | ||
872 | 876 | ||
873 | #define AR_SREV_9330(_ah) \ | 877 | #define AR_SREV_9330(_ah) \ |
874 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330)) | 878 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330)) |
@@ -884,9 +888,6 @@ | |||
884 | 888 | ||
885 | #define AR_SREV_9485(_ah) \ | 889 | #define AR_SREV_9485(_ah) \ |
886 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) | 890 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) |
887 | #define AR_SREV_9485_10(_ah) \ | ||
888 | (AR_SREV_9485(_ah) && \ | ||
889 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_10)) | ||
890 | #define AR_SREV_9485_11(_ah) \ | 891 | #define AR_SREV_9485_11(_ah) \ |
891 | (AR_SREV_9485(_ah) && \ | 892 | (AR_SREV_9485(_ah) && \ |
892 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11)) | 893 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11)) |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 90e48a0fafe5..feacaafee959 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -378,7 +378,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf, | |||
378 | 378 | ||
379 | static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | 379 | static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, |
380 | struct ath_buf *bf, struct list_head *bf_q, | 380 | struct ath_buf *bf, struct list_head *bf_q, |
381 | struct ath_tx_status *ts, int txok, bool retry) | 381 | struct ath_tx_status *ts, int txok) |
382 | { | 382 | { |
383 | struct ath_node *an = NULL; | 383 | struct ath_node *an = NULL; |
384 | struct sk_buff *skb; | 384 | struct sk_buff *skb; |
@@ -490,7 +490,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
490 | } else if (!isaggr && txok) { | 490 | } else if (!isaggr && txok) { |
491 | /* transmit completion */ | 491 | /* transmit completion */ |
492 | acked_cnt++; | 492 | acked_cnt++; |
493 | } else if ((tid->state & AGGR_CLEANUP) || !retry) { | 493 | } else if (tid->state & AGGR_CLEANUP) { |
494 | /* | 494 | /* |
495 | * cleanup in progress, just fail | 495 | * cleanup in progress, just fail |
496 | * the un-acked sub-frames | 496 | * the un-acked sub-frames |
@@ -604,6 +604,37 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
604 | ath9k_queue_reset(sc, RESET_TYPE_TX_ERROR); | 604 | ath9k_queue_reset(sc, RESET_TYPE_TX_ERROR); |
605 | } | 605 | } |
606 | 606 | ||
607 | static bool bf_is_ampdu_not_probing(struct ath_buf *bf) | ||
608 | { | ||
609 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu); | ||
610 | return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); | ||
611 | } | ||
612 | |||
613 | static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, | ||
614 | struct ath_tx_status *ts, struct ath_buf *bf, | ||
615 | struct list_head *bf_head) | ||
616 | { | ||
617 | bool txok, flush; | ||
618 | |||
619 | txok = !(ts->ts_status & ATH9K_TXERR_MASK); | ||
620 | flush = !!(ts->ts_status & ATH9K_TX_FLUSH); | ||
621 | txq->axq_tx_inprogress = false; | ||
622 | |||
623 | txq->axq_depth--; | ||
624 | if (bf_is_ampdu_not_probing(bf)) | ||
625 | txq->axq_ampdu_depth--; | ||
626 | |||
627 | if (!bf_isampdu(bf)) { | ||
628 | if (!flush) | ||
629 | ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok); | ||
630 | ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok); | ||
631 | } else | ||
632 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok); | ||
633 | |||
634 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && !flush) | ||
635 | ath_txq_schedule(sc, txq); | ||
636 | } | ||
637 | |||
607 | static bool ath_lookup_legacy(struct ath_buf *bf) | 638 | static bool ath_lookup_legacy(struct ath_buf *bf) |
608 | { | 639 | { |
609 | struct sk_buff *skb; | 640 | struct sk_buff *skb; |
@@ -1331,23 +1362,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid | |||
1331 | /* Queue Management */ | 1362 | /* Queue Management */ |
1332 | /********************/ | 1363 | /********************/ |
1333 | 1364 | ||
1334 | static void ath_txq_drain_pending_buffers(struct ath_softc *sc, | ||
1335 | struct ath_txq *txq) | ||
1336 | { | ||
1337 | struct ath_atx_ac *ac, *ac_tmp; | ||
1338 | struct ath_atx_tid *tid, *tid_tmp; | ||
1339 | |||
1340 | list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { | ||
1341 | list_del(&ac->list); | ||
1342 | ac->sched = false; | ||
1343 | list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) { | ||
1344 | list_del(&tid->list); | ||
1345 | tid->sched = false; | ||
1346 | ath_tid_drain(sc, txq, tid); | ||
1347 | } | ||
1348 | } | ||
1349 | } | ||
1350 | |||
1351 | struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | 1365 | struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) |
1352 | { | 1366 | { |
1353 | struct ath_hw *ah = sc->sc_ah; | 1367 | struct ath_hw *ah = sc->sc_ah; |
@@ -1470,14 +1484,8 @@ int ath_cabq_update(struct ath_softc *sc) | |||
1470 | return 0; | 1484 | return 0; |
1471 | } | 1485 | } |
1472 | 1486 | ||
1473 | static bool bf_is_ampdu_not_probing(struct ath_buf *bf) | ||
1474 | { | ||
1475 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu); | ||
1476 | return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); | ||
1477 | } | ||
1478 | |||
1479 | static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, | 1487 | static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, |
1480 | struct list_head *list, bool retry_tx) | 1488 | struct list_head *list) |
1481 | { | 1489 | { |
1482 | struct ath_buf *bf, *lastbf; | 1490 | struct ath_buf *bf, *lastbf; |
1483 | struct list_head bf_head; | 1491 | struct list_head bf_head; |
@@ -1499,16 +1507,7 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, | |||
1499 | 1507 | ||
1500 | lastbf = bf->bf_lastbf; | 1508 | lastbf = bf->bf_lastbf; |
1501 | list_cut_position(&bf_head, list, &lastbf->list); | 1509 | list_cut_position(&bf_head, list, &lastbf->list); |
1502 | 1510 | ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head); | |
1503 | txq->axq_depth--; | ||
1504 | if (bf_is_ampdu_not_probing(bf)) | ||
1505 | txq->axq_ampdu_depth--; | ||
1506 | |||
1507 | if (bf_isampdu(bf)) | ||
1508 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0, | ||
1509 | retry_tx); | ||
1510 | else | ||
1511 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); | ||
1512 | } | 1511 | } |
1513 | } | 1512 | } |
1514 | 1513 | ||
@@ -1518,7 +1517,7 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, | |||
1518 | * This assumes output has been stopped and | 1517 | * This assumes output has been stopped and |
1519 | * we do not need to block ath_tx_tasklet. | 1518 | * we do not need to block ath_tx_tasklet. |
1520 | */ | 1519 | */ |
1521 | void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | 1520 | void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq) |
1522 | { | 1521 | { |
1523 | ath_txq_lock(sc, txq); | 1522 | ath_txq_lock(sc, txq); |
1524 | 1523 | ||
@@ -1526,8 +1525,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1526 | int idx = txq->txq_tailidx; | 1525 | int idx = txq->txq_tailidx; |
1527 | 1526 | ||
1528 | while (!list_empty(&txq->txq_fifo[idx])) { | 1527 | while (!list_empty(&txq->txq_fifo[idx])) { |
1529 | ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx], | 1528 | ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx]); |
1530 | retry_tx); | ||
1531 | 1529 | ||
1532 | INCR(idx, ATH_TXFIFO_DEPTH); | 1530 | INCR(idx, ATH_TXFIFO_DEPTH); |
1533 | } | 1531 | } |
@@ -1536,16 +1534,12 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1536 | 1534 | ||
1537 | txq->axq_link = NULL; | 1535 | txq->axq_link = NULL; |
1538 | txq->axq_tx_inprogress = false; | 1536 | txq->axq_tx_inprogress = false; |
1539 | ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx); | 1537 | ath_drain_txq_list(sc, txq, &txq->axq_q); |
1540 | |||
1541 | /* flush any pending frames if aggregation is enabled */ | ||
1542 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && !retry_tx) | ||
1543 | ath_txq_drain_pending_buffers(sc, txq); | ||
1544 | 1538 | ||
1545 | ath_txq_unlock_complete(sc, txq); | 1539 | ath_txq_unlock_complete(sc, txq); |
1546 | } | 1540 | } |
1547 | 1541 | ||
1548 | bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) | 1542 | bool ath_drain_all_txq(struct ath_softc *sc) |
1549 | { | 1543 | { |
1550 | struct ath_hw *ah = sc->sc_ah; | 1544 | struct ath_hw *ah = sc->sc_ah; |
1551 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1545 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -1581,7 +1575,7 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) | |||
1581 | */ | 1575 | */ |
1582 | txq = &sc->tx.txq[i]; | 1576 | txq = &sc->tx.txq[i]; |
1583 | txq->stopped = false; | 1577 | txq->stopped = false; |
1584 | ath_draintxq(sc, txq, retry_tx); | 1578 | ath_draintxq(sc, txq); |
1585 | } | 1579 | } |
1586 | 1580 | ||
1587 | return !npend; | 1581 | return !npend; |
@@ -2175,28 +2169,6 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, | |||
2175 | tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; | 2169 | tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; |
2176 | } | 2170 | } |
2177 | 2171 | ||
2178 | static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, | ||
2179 | struct ath_tx_status *ts, struct ath_buf *bf, | ||
2180 | struct list_head *bf_head) | ||
2181 | { | ||
2182 | int txok; | ||
2183 | |||
2184 | txq->axq_depth--; | ||
2185 | txok = !(ts->ts_status & ATH9K_TXERR_MASK); | ||
2186 | txq->axq_tx_inprogress = false; | ||
2187 | if (bf_is_ampdu_not_probing(bf)) | ||
2188 | txq->axq_ampdu_depth--; | ||
2189 | |||
2190 | if (!bf_isampdu(bf)) { | ||
2191 | ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok); | ||
2192 | ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok); | ||
2193 | } else | ||
2194 | ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true); | ||
2195 | |||
2196 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) | ||
2197 | ath_txq_schedule(sc, txq); | ||
2198 | } | ||
2199 | |||
2200 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | 2172 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) |
2201 | { | 2173 | { |
2202 | struct ath_hw *ah = sc->sc_ah; | 2174 | struct ath_hw *ah = sc->sc_ah; |
@@ -2361,8 +2333,8 @@ static int ath_txstatus_setup(struct ath_softc *sc, int size) | |||
2361 | u8 txs_len = sc->sc_ah->caps.txs_len; | 2333 | u8 txs_len = sc->sc_ah->caps.txs_len; |
2362 | 2334 | ||
2363 | dd->dd_desc_len = size * txs_len; | 2335 | dd->dd_desc_len = size * txs_len; |
2364 | dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, | 2336 | dd->dd_desc = dmam_alloc_coherent(sc->dev, dd->dd_desc_len, |
2365 | &dd->dd_desc_paddr, GFP_KERNEL); | 2337 | &dd->dd_desc_paddr, GFP_KERNEL); |
2366 | if (!dd->dd_desc) | 2338 | if (!dd->dd_desc) |
2367 | return -ENOMEM; | 2339 | return -ENOMEM; |
2368 | 2340 | ||
@@ -2382,14 +2354,6 @@ static int ath_tx_edma_init(struct ath_softc *sc) | |||
2382 | return err; | 2354 | return err; |
2383 | } | 2355 | } |
2384 | 2356 | ||
2385 | static void ath_tx_edma_cleanup(struct ath_softc *sc) | ||
2386 | { | ||
2387 | struct ath_descdma *dd = &sc->txsdma; | ||
2388 | |||
2389 | dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, | ||
2390 | dd->dd_desc_paddr); | ||
2391 | } | ||
2392 | |||
2393 | int ath_tx_init(struct ath_softc *sc, int nbufs) | 2357 | int ath_tx_init(struct ath_softc *sc, int nbufs) |
2394 | { | 2358 | { |
2395 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 2359 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -2402,7 +2366,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) | |||
2402 | if (error != 0) { | 2366 | if (error != 0) { |
2403 | ath_err(common, | 2367 | ath_err(common, |
2404 | "Failed to allocate tx descriptors: %d\n", error); | 2368 | "Failed to allocate tx descriptors: %d\n", error); |
2405 | goto err; | 2369 | return error; |
2406 | } | 2370 | } |
2407 | 2371 | ||
2408 | error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, | 2372 | error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, |
@@ -2410,36 +2374,17 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) | |||
2410 | if (error != 0) { | 2374 | if (error != 0) { |
2411 | ath_err(common, | 2375 | ath_err(common, |
2412 | "Failed to allocate beacon descriptors: %d\n", error); | 2376 | "Failed to allocate beacon descriptors: %d\n", error); |
2413 | goto err; | 2377 | return error; |
2414 | } | 2378 | } |
2415 | 2379 | ||
2416 | INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); | 2380 | INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); |
2417 | 2381 | ||
2418 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 2382 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
2419 | error = ath_tx_edma_init(sc); | 2383 | error = ath_tx_edma_init(sc); |
2420 | if (error) | ||
2421 | goto err; | ||
2422 | } | ||
2423 | |||
2424 | err: | ||
2425 | if (error != 0) | ||
2426 | ath_tx_cleanup(sc); | ||
2427 | 2384 | ||
2428 | return error; | 2385 | return error; |
2429 | } | 2386 | } |
2430 | 2387 | ||
2431 | void ath_tx_cleanup(struct ath_softc *sc) | ||
2432 | { | ||
2433 | if (sc->beacon.bdma.dd_desc_len != 0) | ||
2434 | ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf); | ||
2435 | |||
2436 | if (sc->tx.txdma.dd_desc_len != 0) | ||
2437 | ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf); | ||
2438 | |||
2439 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | ||
2440 | ath_tx_edma_cleanup(sc); | ||
2441 | } | ||
2442 | |||
2443 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | 2388 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) |
2444 | { | 2389 | { |
2445 | struct ath_atx_tid *tid; | 2390 | struct ath_atx_tid *tid; |
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 2df17f1e49ef..25599741cd8a 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h | |||
@@ -85,20 +85,14 @@ enum carl9170_device_state { | |||
85 | CARL9170_STARTED, | 85 | CARL9170_STARTED, |
86 | }; | 86 | }; |
87 | 87 | ||
88 | #define CARL9170_NUM_TID 16 | ||
89 | #define WME_BA_BMP_SIZE 64 | 88 | #define WME_BA_BMP_SIZE 64 |
90 | #define CARL9170_TX_USER_RATE_TRIES 3 | 89 | #define CARL9170_TX_USER_RATE_TRIES 3 |
91 | 90 | ||
92 | #define WME_AC_BE 2 | ||
93 | #define WME_AC_BK 3 | ||
94 | #define WME_AC_VI 1 | ||
95 | #define WME_AC_VO 0 | ||
96 | |||
97 | #define TID_TO_WME_AC(_tid) \ | 91 | #define TID_TO_WME_AC(_tid) \ |
98 | ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ | 92 | ((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE : \ |
99 | (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ | 93 | (((_tid) == 1) || ((_tid) == 2)) ? IEEE80211_AC_BK : \ |
100 | (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ | 94 | (((_tid) == 4) || ((_tid) == 5)) ? IEEE80211_AC_VI : \ |
101 | WME_AC_VO) | 95 | IEEE80211_AC_VO) |
102 | 96 | ||
103 | #define SEQ_DIFF(_start, _seq) \ | 97 | #define SEQ_DIFF(_start, _seq) \ |
104 | (((_start) - (_seq)) & 0x0fff) | 98 | (((_start) - (_seq)) & 0x0fff) |
@@ -290,6 +284,7 @@ struct ar9170 { | |||
290 | unsigned int rx_size; | 284 | unsigned int rx_size; |
291 | unsigned int tx_seq_table; | 285 | unsigned int tx_seq_table; |
292 | bool ba_filter; | 286 | bool ba_filter; |
287 | bool disable_offload_fw; | ||
293 | } fw; | 288 | } fw; |
294 | 289 | ||
295 | /* interface configuration combinations */ | 290 | /* interface configuration combinations */ |
@@ -493,8 +488,8 @@ struct carl9170_sta_info { | |||
493 | bool sleeping; | 488 | bool sleeping; |
494 | atomic_t pending_frames; | 489 | atomic_t pending_frames; |
495 | unsigned int ampdu_max_len; | 490 | unsigned int ampdu_max_len; |
496 | struct carl9170_sta_tid __rcu *agg[CARL9170_NUM_TID]; | 491 | struct carl9170_sta_tid __rcu *agg[IEEE80211_NUM_TIDS]; |
497 | struct carl9170_ba_stats stats[CARL9170_NUM_TID]; | 492 | struct carl9170_ba_stats stats[IEEE80211_NUM_TIDS]; |
498 | }; | 493 | }; |
499 | 494 | ||
500 | struct carl9170_tx_info { | 495 | struct carl9170_tx_info { |
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index 63fd9af3fd39..47d5c2e910ad 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c | |||
@@ -215,6 +215,24 @@ static int carl9170_fw_tx_sequence(struct ar9170 *ar) | |||
215 | return 0; | 215 | return 0; |
216 | } | 216 | } |
217 | 217 | ||
218 | static void carl9170_fw_set_if_combinations(struct ar9170 *ar, | ||
219 | u16 if_comb_types) | ||
220 | { | ||
221 | if (ar->fw.vif_num < 2) | ||
222 | return; | ||
223 | |||
224 | ar->if_comb_limits[0].max = ar->fw.vif_num; | ||
225 | ar->if_comb_limits[0].types = if_comb_types; | ||
226 | |||
227 | ar->if_combs[0].num_different_channels = 1; | ||
228 | ar->if_combs[0].max_interfaces = ar->fw.vif_num; | ||
229 | ar->if_combs[0].limits = ar->if_comb_limits; | ||
230 | ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits); | ||
231 | |||
232 | ar->hw->wiphy->iface_combinations = ar->if_combs; | ||
233 | ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs); | ||
234 | } | ||
235 | |||
218 | static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) | 236 | static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) |
219 | { | 237 | { |
220 | const struct carl9170fw_otus_desc *otus_desc; | 238 | const struct carl9170fw_otus_desc *otus_desc; |
@@ -264,7 +282,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) | |||
264 | if (!SUPP(CARL9170FW_COMMAND_CAM)) { | 282 | if (!SUPP(CARL9170FW_COMMAND_CAM)) { |
265 | dev_info(&ar->udev->dev, "crypto offloading is disabled " | 283 | dev_info(&ar->udev->dev, "crypto offloading is disabled " |
266 | "by firmware.\n"); | 284 | "by firmware.\n"); |
267 | ar->disable_offload = true; | 285 | ar->fw.disable_offload_fw = true; |
268 | } | 286 | } |
269 | 287 | ||
270 | if (SUPP(CARL9170FW_PSM) && SUPP(CARL9170FW_FIXED_5GHZ_PSM)) | 288 | if (SUPP(CARL9170FW_PSM) && SUPP(CARL9170FW_FIXED_5GHZ_PSM)) |
@@ -345,20 +363,15 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) | |||
345 | } | 363 | } |
346 | } | 364 | } |
347 | 365 | ||
348 | ar->if_comb_limits[0].max = ar->fw.vif_num; | 366 | carl9170_fw_set_if_combinations(ar, if_comb_types); |
349 | ar->if_comb_limits[0].types = if_comb_types; | ||
350 | |||
351 | ar->if_combs[0].num_different_channels = 1; | ||
352 | ar->if_combs[0].max_interfaces = ar->fw.vif_num; | ||
353 | ar->if_combs[0].limits = ar->if_comb_limits; | ||
354 | ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits); | ||
355 | |||
356 | ar->hw->wiphy->iface_combinations = ar->if_combs; | ||
357 | ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs); | ||
358 | 367 | ||
359 | ar->hw->wiphy->interface_modes |= if_comb_types; | 368 | ar->hw->wiphy->interface_modes |= if_comb_types; |
360 | 369 | ||
361 | ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 370 | ar->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
371 | |||
372 | /* As IBSS Encryption is software-based, IBSS RSN is supported. */ | ||
373 | ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
374 | WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_SUPPORTS_TDLS; | ||
362 | 375 | ||
363 | #undef SUPPORTED | 376 | #undef SUPPORTED |
364 | return carl9170_fw_tx_sequence(ar); | 377 | return carl9170_fw_tx_sequence(ar); |
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index 9443c802b25b..9111d4ffc1b3 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h | |||
@@ -156,6 +156,14 @@ struct carl9170_psm { | |||
156 | } __packed; | 156 | } __packed; |
157 | #define CARL9170_PSM_SIZE 4 | 157 | #define CARL9170_PSM_SIZE 4 |
158 | 158 | ||
159 | /* | ||
160 | * Note: If a bit in rx_filter is set, then it | ||
161 | * means that the particular frames which matches | ||
162 | * the condition are FILTERED/REMOVED/DISCARDED! | ||
163 | * (This is can be a bit confusing, especially | ||
164 | * because someone people think it's the exact | ||
165 | * opposite way, so watch out!) | ||
166 | */ | ||
159 | struct carl9170_rx_filter_cmd { | 167 | struct carl9170_rx_filter_cmd { |
160 | __le32 rx_filter; | 168 | __le32 rx_filter; |
161 | } __packed; | 169 | } __packed; |
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h index fa834c1460f0..0db874abde50 100644 --- a/drivers/net/wireless/ath/carl9170/hw.h +++ b/drivers/net/wireless/ath/carl9170/hw.h | |||
@@ -384,7 +384,7 @@ | |||
384 | 384 | ||
385 | #define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xd84) | 385 | #define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xd84) |
386 | #define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xd88) | 386 | #define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xd88) |
387 | #define AR9170_MAC_BCN_LENGTH_MAX 256 | 387 | #define AR9170_MAC_BCN_LENGTH_MAX (512 - 32) |
388 | 388 | ||
389 | #define AR9170_MAC_REG_BCN_STATUS (AR9170_MAC_REG_BASE + 0xd8c) | 389 | #define AR9170_MAC_REG_BCN_STATUS (AR9170_MAC_REG_BASE + 0xd8c) |
390 | 390 | ||
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 25a1e2f4f738..ef82751722e0 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -358,8 +358,13 @@ static int carl9170_op_start(struct ieee80211_hw *hw) | |||
358 | ar->ps.last_action = jiffies; | 358 | ar->ps.last_action = jiffies; |
359 | ar->ps.last_slept = jiffies; | 359 | ar->ps.last_slept = jiffies; |
360 | ar->erp_mode = CARL9170_ERP_AUTO; | 360 | ar->erp_mode = CARL9170_ERP_AUTO; |
361 | ar->rx_software_decryption = false; | 361 | |
362 | ar->disable_offload = false; | 362 | /* Set "disable hw crypto offload" whenever the module parameter |
363 | * nohwcrypt is true or if the firmware does not support it. | ||
364 | */ | ||
365 | ar->disable_offload = modparam_nohwcrypt | | ||
366 | ar->fw.disable_offload_fw; | ||
367 | ar->rx_software_decryption = ar->disable_offload; | ||
363 | 368 | ||
364 | for (i = 0; i < ar->hw->queues; i++) { | 369 | for (i = 0; i < ar->hw->queues; i++) { |
365 | ar->queue_stop_timeout[i] = jiffies; | 370 | ar->queue_stop_timeout[i] = jiffies; |
@@ -565,12 +570,28 @@ static int carl9170_init_interface(struct ar9170 *ar, | |||
565 | 570 | ||
566 | memcpy(common->macaddr, vif->addr, ETH_ALEN); | 571 | memcpy(common->macaddr, vif->addr, ETH_ALEN); |
567 | 572 | ||
568 | if (modparam_nohwcrypt || | 573 | /* We have to fall back to software crypto, whenever |
569 | ((vif->type != NL80211_IFTYPE_STATION) && | 574 | * the user choose to participates in an IBSS. HW |
570 | (vif->type != NL80211_IFTYPE_AP))) { | 575 | * offload for IBSS RSN is not supported by this driver. |
571 | ar->rx_software_decryption = true; | 576 | * |
572 | ar->disable_offload = true; | 577 | * NOTE: If the previous main interface has already |
573 | } | 578 | * disabled hw crypto offload, we have to keep this |
579 | * previous disable_offload setting as it was. | ||
580 | * Altough ideally, we should notify mac80211 and tell | ||
581 | * it to forget about any HW crypto offload for now. | ||
582 | */ | ||
583 | ar->disable_offload |= ((vif->type != NL80211_IFTYPE_STATION) && | ||
584 | (vif->type != NL80211_IFTYPE_AP)); | ||
585 | |||
586 | /* While the driver supports HW offload in a single | ||
587 | * P2P client configuration, it doesn't support HW | ||
588 | * offload in the favourit, concurrent P2P GO+CLIENT | ||
589 | * configuration. Hence, HW offload will always be | ||
590 | * disabled for P2P. | ||
591 | */ | ||
592 | ar->disable_offload |= vif->p2p; | ||
593 | |||
594 | ar->rx_software_decryption = ar->disable_offload; | ||
574 | 595 | ||
575 | err = carl9170_set_operating_mode(ar); | 596 | err = carl9170_set_operating_mode(ar); |
576 | return err; | 597 | return err; |
@@ -580,7 +601,7 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw, | |||
580 | struct ieee80211_vif *vif) | 601 | struct ieee80211_vif *vif) |
581 | { | 602 | { |
582 | struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv; | 603 | struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv; |
583 | struct ieee80211_vif *main_vif; | 604 | struct ieee80211_vif *main_vif, *old_main = NULL; |
584 | struct ar9170 *ar = hw->priv; | 605 | struct ar9170 *ar = hw->priv; |
585 | int vif_id = -1, err = 0; | 606 | int vif_id = -1, err = 0; |
586 | 607 | ||
@@ -602,6 +623,15 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw, | |||
602 | goto init; | 623 | goto init; |
603 | } | 624 | } |
604 | 625 | ||
626 | /* Because the AR9170 HW's MAC doesn't provide full support for | ||
627 | * multiple, independent interfaces [of different operation modes]. | ||
628 | * We have to select ONE main interface [main mode of HW], but we | ||
629 | * can have multiple slaves [AKA: entry in the ACK-table]. | ||
630 | * | ||
631 | * The first (from HEAD/TOP) interface in the ar->vif_list is | ||
632 | * always the main intf. All following intfs in this list | ||
633 | * are considered to be slave intfs. | ||
634 | */ | ||
605 | main_vif = carl9170_get_main_vif(ar); | 635 | main_vif = carl9170_get_main_vif(ar); |
606 | 636 | ||
607 | if (main_vif) { | 637 | if (main_vif) { |
@@ -610,6 +640,18 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw, | |||
610 | if (vif->type == NL80211_IFTYPE_STATION) | 640 | if (vif->type == NL80211_IFTYPE_STATION) |
611 | break; | 641 | break; |
612 | 642 | ||
643 | /* P2P GO [master] use-case | ||
644 | * Because the P2P GO station is selected dynamically | ||
645 | * by all participating peers of a WIFI Direct network, | ||
646 | * the driver has be able to change the main interface | ||
647 | * operating mode on the fly. | ||
648 | */ | ||
649 | if (main_vif->p2p && vif->p2p && | ||
650 | vif->type == NL80211_IFTYPE_AP) { | ||
651 | old_main = main_vif; | ||
652 | break; | ||
653 | } | ||
654 | |||
613 | err = -EBUSY; | 655 | err = -EBUSY; |
614 | rcu_read_unlock(); | 656 | rcu_read_unlock(); |
615 | 657 | ||
@@ -648,14 +690,41 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw, | |||
648 | vif_priv->id = vif_id; | 690 | vif_priv->id = vif_id; |
649 | vif_priv->enable_beacon = false; | 691 | vif_priv->enable_beacon = false; |
650 | ar->vifs++; | 692 | ar->vifs++; |
651 | list_add_tail_rcu(&vif_priv->list, &ar->vif_list); | 693 | if (old_main) { |
694 | /* We end up in here, if the main interface is being replaced. | ||
695 | * Put the new main interface at the HEAD of the list and the | ||
696 | * previous inteface will automatically become second in line. | ||
697 | */ | ||
698 | list_add_rcu(&vif_priv->list, &ar->vif_list); | ||
699 | } else { | ||
700 | /* Add new inteface. If the list is empty, it will become the | ||
701 | * main inteface, otherwise it will be slave. | ||
702 | */ | ||
703 | list_add_tail_rcu(&vif_priv->list, &ar->vif_list); | ||
704 | } | ||
652 | rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif); | 705 | rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif); |
653 | 706 | ||
654 | init: | 707 | init: |
655 | if (carl9170_get_main_vif(ar) == vif) { | 708 | main_vif = carl9170_get_main_vif(ar); |
709 | |||
710 | if (main_vif == vif) { | ||
656 | rcu_assign_pointer(ar->beacon_iter, vif_priv); | 711 | rcu_assign_pointer(ar->beacon_iter, vif_priv); |
657 | rcu_read_unlock(); | 712 | rcu_read_unlock(); |
658 | 713 | ||
714 | if (old_main) { | ||
715 | struct carl9170_vif_info *old_main_priv = | ||
716 | (void *) old_main->drv_priv; | ||
717 | /* downgrade old main intf to slave intf. | ||
718 | * NOTE: We are no longer under rcu_read_lock. | ||
719 | * But we are still holding ar->mutex, so the | ||
720 | * vif data [id, addr] is safe. | ||
721 | */ | ||
722 | err = carl9170_mod_virtual_mac(ar, old_main_priv->id, | ||
723 | old_main->addr); | ||
724 | if (err) | ||
725 | goto unlock; | ||
726 | } | ||
727 | |||
659 | err = carl9170_init_interface(ar, vif); | 728 | err = carl9170_init_interface(ar, vif); |
660 | if (err) | 729 | if (err) |
661 | goto unlock; | 730 | goto unlock; |
@@ -1112,9 +1181,7 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1112 | if (ar->disable_offload || !vif) | 1181 | if (ar->disable_offload || !vif) |
1113 | return -EOPNOTSUPP; | 1182 | return -EOPNOTSUPP; |
1114 | 1183 | ||
1115 | /* | 1184 | /* Fall back to software encryption whenever the driver is connected |
1116 | * We have to fall back to software encryption, whenever | ||
1117 | * the user choose to participates in an IBSS or is connected | ||
1118 | * to more than one network. | 1185 | * to more than one network. |
1119 | * | 1186 | * |
1120 | * This is very unfortunate, because some machines cannot handle | 1187 | * This is very unfortunate, because some machines cannot handle |
@@ -1263,7 +1330,7 @@ static int carl9170_op_sta_add(struct ieee80211_hw *hw, | |||
1263 | return 0; | 1330 | return 0; |
1264 | } | 1331 | } |
1265 | 1332 | ||
1266 | for (i = 0; i < CARL9170_NUM_TID; i++) | 1333 | for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++) |
1267 | RCU_INIT_POINTER(sta_info->agg[i], NULL); | 1334 | RCU_INIT_POINTER(sta_info->agg[i], NULL); |
1268 | 1335 | ||
1269 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); | 1336 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); |
@@ -1287,7 +1354,7 @@ static int carl9170_op_sta_remove(struct ieee80211_hw *hw, | |||
1287 | sta_info->ht_sta = false; | 1354 | sta_info->ht_sta = false; |
1288 | 1355 | ||
1289 | rcu_read_lock(); | 1356 | rcu_read_lock(); |
1290 | for (i = 0; i < CARL9170_NUM_TID; i++) { | 1357 | for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++) { |
1291 | struct carl9170_sta_tid *tid_info; | 1358 | struct carl9170_sta_tid *tid_info; |
1292 | 1359 | ||
1293 | tid_info = rcu_dereference(sta_info->agg[i]); | 1360 | tid_info = rcu_dereference(sta_info->agg[i]); |
@@ -1394,7 +1461,9 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, | |||
1394 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1461 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1395 | break; | 1462 | break; |
1396 | 1463 | ||
1397 | case IEEE80211_AMPDU_TX_STOP: | 1464 | case IEEE80211_AMPDU_TX_STOP_CONT: |
1465 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
1466 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
1398 | rcu_read_lock(); | 1467 | rcu_read_lock(); |
1399 | tid_info = rcu_dereference(sta_info->agg[tid]); | 1468 | tid_info = rcu_dereference(sta_info->agg[tid]); |
1400 | if (tid_info) { | 1469 | if (tid_info) { |
@@ -1805,10 +1874,6 @@ void *carl9170_alloc(size_t priv_size) | |||
1805 | for (i = 0; i < ARRAY_SIZE(ar->noise); i++) | 1874 | for (i = 0; i < ARRAY_SIZE(ar->noise); i++) |
1806 | ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ | 1875 | ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ |
1807 | 1876 | ||
1808 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
1809 | |||
1810 | /* As IBSS Encryption is software-based, IBSS RSN is supported. */ | ||
1811 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | ||
1812 | return ar; | 1877 | return ar; |
1813 | 1878 | ||
1814 | err_nomem: | 1879 | err_nomem: |
@@ -1916,13 +1981,13 @@ static int carl9170_parse_eeprom(struct ar9170 *ar) | |||
1916 | return 0; | 1981 | return 0; |
1917 | } | 1982 | } |
1918 | 1983 | ||
1919 | static int carl9170_reg_notifier(struct wiphy *wiphy, | 1984 | static void carl9170_reg_notifier(struct wiphy *wiphy, |
1920 | struct regulatory_request *request) | 1985 | struct regulatory_request *request) |
1921 | { | 1986 | { |
1922 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 1987 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
1923 | struct ar9170 *ar = hw->priv; | 1988 | struct ar9170 *ar = hw->priv; |
1924 | 1989 | ||
1925 | return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); | 1990 | ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); |
1926 | } | 1991 | } |
1927 | 1992 | ||
1928 | int carl9170_register(struct ar9170 *ar) | 1993 | int carl9170_register(struct ar9170 *ar) |
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index ef4ec0da6e49..9c0b150d5b8e 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -1520,35 +1520,92 @@ void carl9170_tx_scheduler(struct ar9170 *ar) | |||
1520 | carl9170_tx(ar); | 1520 | carl9170_tx(ar); |
1521 | } | 1521 | } |
1522 | 1522 | ||
1523 | int carl9170_update_beacon(struct ar9170 *ar, const bool submit) | 1523 | /* caller has to take rcu_read_lock */ |
1524 | static struct carl9170_vif_info *carl9170_pick_beaconing_vif(struct ar9170 *ar) | ||
1524 | { | 1525 | { |
1525 | struct sk_buff *skb = NULL; | ||
1526 | struct carl9170_vif_info *cvif; | 1526 | struct carl9170_vif_info *cvif; |
1527 | int i = 1; | ||
1528 | |||
1529 | /* The AR9170 hardware has no fancy beacon queue or some | ||
1530 | * other scheduling mechanism. So, the driver has to make | ||
1531 | * due by setting the two beacon timers (pretbtt and tbtt) | ||
1532 | * once and then swapping the beacon address in the HW's | ||
1533 | * register file each time the pretbtt fires. | ||
1534 | */ | ||
1535 | |||
1536 | cvif = rcu_dereference(ar->beacon_iter); | ||
1537 | if (ar->vifs > 0 && cvif) { | ||
1538 | do { | ||
1539 | list_for_each_entry_continue_rcu(cvif, &ar->vif_list, | ||
1540 | list) { | ||
1541 | if (cvif->active && cvif->enable_beacon) | ||
1542 | goto out; | ||
1543 | } | ||
1544 | } while (ar->beacon_enabled && i--); | ||
1545 | } | ||
1546 | |||
1547 | out: | ||
1548 | rcu_assign_pointer(ar->beacon_iter, cvif); | ||
1549 | return cvif; | ||
1550 | } | ||
1551 | |||
1552 | static bool carl9170_tx_beacon_physet(struct ar9170 *ar, struct sk_buff *skb, | ||
1553 | u32 *ht1, u32 *plcp) | ||
1554 | { | ||
1527 | struct ieee80211_tx_info *txinfo; | 1555 | struct ieee80211_tx_info *txinfo; |
1528 | struct ieee80211_tx_rate *rate; | 1556 | struct ieee80211_tx_rate *rate; |
1529 | __le32 *data, *old = NULL; | 1557 | unsigned int power, chains; |
1530 | unsigned int plcp, power, chains; | 1558 | bool ht_rate; |
1531 | u32 word, ht1, off, addr, len; | ||
1532 | int i = 0, err = 0; | ||
1533 | 1559 | ||
1534 | rcu_read_lock(); | 1560 | txinfo = IEEE80211_SKB_CB(skb); |
1535 | cvif = rcu_dereference(ar->beacon_iter); | 1561 | rate = &txinfo->control.rates[0]; |
1536 | retry: | 1562 | ht_rate = !!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS); |
1537 | if (ar->vifs == 0 || !cvif) | 1563 | carl9170_tx_rate_tpc_chains(ar, txinfo, rate, plcp, &power, &chains); |
1538 | goto out_unlock; | ||
1539 | 1564 | ||
1540 | list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) { | 1565 | *ht1 = AR9170_MAC_BCN_HT1_TX_ANT0; |
1541 | if (cvif->active && cvif->enable_beacon) | 1566 | if (chains == AR9170_TX_PHY_TXCHAIN_2) |
1542 | goto found; | 1567 | *ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1; |
1568 | SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, *ht1, 7); | ||
1569 | SET_VAL(AR9170_MAC_BCN_HT1_TPC, *ht1, power); | ||
1570 | SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, *ht1, chains); | ||
1571 | |||
1572 | if (ht_rate) { | ||
1573 | *ht1 |= AR9170_MAC_BCN_HT1_HT_EN; | ||
1574 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
1575 | *plcp |= AR9170_MAC_BCN_HT2_SGI; | ||
1576 | |||
1577 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { | ||
1578 | *ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED; | ||
1579 | *plcp |= AR9170_MAC_BCN_HT2_BW40; | ||
1580 | } else if (rate->flags & IEEE80211_TX_RC_DUP_DATA) { | ||
1581 | *ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP; | ||
1582 | *plcp |= AR9170_MAC_BCN_HT2_BW40; | ||
1583 | } | ||
1584 | |||
1585 | SET_VAL(AR9170_MAC_BCN_HT2_LEN, *plcp, skb->len + FCS_LEN); | ||
1586 | } else { | ||
1587 | if (*plcp <= AR9170_TX_PHY_RATE_CCK_11M) | ||
1588 | *plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400; | ||
1589 | else | ||
1590 | *plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010; | ||
1543 | } | 1591 | } |
1544 | 1592 | ||
1545 | if (!ar->beacon_enabled || i++) | 1593 | return ht_rate; |
1546 | goto out_unlock; | 1594 | } |
1547 | 1595 | ||
1548 | goto retry; | 1596 | int carl9170_update_beacon(struct ar9170 *ar, const bool submit) |
1597 | { | ||
1598 | struct sk_buff *skb = NULL; | ||
1599 | struct carl9170_vif_info *cvif; | ||
1600 | __le32 *data, *old = NULL; | ||
1601 | u32 word, ht1, plcp, off, addr, len; | ||
1602 | int i = 0, err = 0; | ||
1603 | bool ht_rate; | ||
1549 | 1604 | ||
1550 | found: | 1605 | rcu_read_lock(); |
1551 | rcu_assign_pointer(ar->beacon_iter, cvif); | 1606 | cvif = carl9170_pick_beaconing_vif(ar); |
1607 | if (!cvif) | ||
1608 | goto out_unlock; | ||
1552 | 1609 | ||
1553 | skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif), | 1610 | skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif), |
1554 | NULL, NULL); | 1611 | NULL, NULL); |
@@ -1558,7 +1615,6 @@ found: | |||
1558 | goto err_free; | 1615 | goto err_free; |
1559 | } | 1616 | } |
1560 | 1617 | ||
1561 | txinfo = IEEE80211_SKB_CB(skb); | ||
1562 | spin_lock_bh(&ar->beacon_lock); | 1618 | spin_lock_bh(&ar->beacon_lock); |
1563 | data = (__le32 *)skb->data; | 1619 | data = (__le32 *)skb->data; |
1564 | if (cvif->beacon) | 1620 | if (cvif->beacon) |
@@ -1588,43 +1644,14 @@ found: | |||
1588 | goto err_unlock; | 1644 | goto err_unlock; |
1589 | } | 1645 | } |
1590 | 1646 | ||
1591 | ht1 = AR9170_MAC_BCN_HT1_TX_ANT0; | 1647 | ht_rate = carl9170_tx_beacon_physet(ar, skb, &ht1, &plcp); |
1592 | rate = &txinfo->control.rates[0]; | ||
1593 | carl9170_tx_rate_tpc_chains(ar, txinfo, rate, &plcp, &power, &chains); | ||
1594 | if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) { | ||
1595 | if (plcp <= AR9170_TX_PHY_RATE_CCK_11M) | ||
1596 | plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400; | ||
1597 | else | ||
1598 | plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010; | ||
1599 | } else { | ||
1600 | ht1 |= AR9170_MAC_BCN_HT1_HT_EN; | ||
1601 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
1602 | plcp |= AR9170_MAC_BCN_HT2_SGI; | ||
1603 | |||
1604 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { | ||
1605 | ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED; | ||
1606 | plcp |= AR9170_MAC_BCN_HT2_BW40; | ||
1607 | } | ||
1608 | if (rate->flags & IEEE80211_TX_RC_DUP_DATA) { | ||
1609 | ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP; | ||
1610 | plcp |= AR9170_MAC_BCN_HT2_BW40; | ||
1611 | } | ||
1612 | |||
1613 | SET_VAL(AR9170_MAC_BCN_HT2_LEN, plcp, skb->len + FCS_LEN); | ||
1614 | } | ||
1615 | |||
1616 | SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, ht1, 7); | ||
1617 | SET_VAL(AR9170_MAC_BCN_HT1_TPC, ht1, power); | ||
1618 | SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, ht1, chains); | ||
1619 | if (chains == AR9170_TX_PHY_TXCHAIN_2) | ||
1620 | ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1; | ||
1621 | 1648 | ||
1622 | carl9170_async_regwrite_begin(ar); | 1649 | carl9170_async_regwrite_begin(ar); |
1623 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT1, ht1); | 1650 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT1, ht1); |
1624 | if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) | 1651 | if (ht_rate) |
1625 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp); | ||
1626 | else | ||
1627 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT2, plcp); | 1652 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT2, plcp); |
1653 | else | ||
1654 | carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp); | ||
1628 | 1655 | ||
1629 | for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { | 1656 | for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { |
1630 | /* | 1657 | /* |
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h index 2ec3e9191e4d..2282847d4bb8 100644 --- a/drivers/net/wireless/ath/carl9170/version.h +++ b/drivers/net/wireless/ath/carl9170/version.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef __CARL9170_SHARED_VERSION_H | 1 | #ifndef __CARL9170_SHARED_VERSION_H |
2 | #define __CARL9170_SHARED_VERSION_H | 2 | #define __CARL9170_SHARED_VERSION_H |
3 | #define CARL9170FW_VERSION_YEAR 12 | 3 | #define CARL9170FW_VERSION_YEAR 12 |
4 | #define CARL9170FW_VERSION_MONTH 7 | 4 | #define CARL9170FW_VERSION_MONTH 12 |
5 | #define CARL9170FW_VERSION_DAY 7 | 5 | #define CARL9170FW_VERSION_DAY 15 |
6 | #define CARL9170FW_VERSION_GIT "1.9.6" | 6 | #define CARL9170FW_VERSION_GIT "1.9.7" |
7 | #endif /* __CARL9170_SHARED_VERSION_H */ | 7 | #endif /* __CARL9170_SHARED_VERSION_H */ |
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index d81698015bf7..ccc4c718f124 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -195,8 +195,6 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
195 | const struct ieee80211_reg_rule *reg_rule; | 195 | const struct ieee80211_reg_rule *reg_rule; |
196 | struct ieee80211_channel *ch; | 196 | struct ieee80211_channel *ch; |
197 | unsigned int i; | 197 | unsigned int i; |
198 | u32 bandwidth = 0; | ||
199 | int r; | ||
200 | 198 | ||
201 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 199 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
202 | 200 | ||
@@ -214,11 +212,8 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
214 | continue; | 212 | continue; |
215 | 213 | ||
216 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { | 214 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
217 | r = freq_reg_info(wiphy, | 215 | reg_rule = freq_reg_info(wiphy, ch->center_freq); |
218 | ch->center_freq, | 216 | if (IS_ERR(reg_rule)) |
219 | bandwidth, | ||
220 | ®_rule); | ||
221 | if (r) | ||
222 | continue; | 217 | continue; |
223 | /* | 218 | /* |
224 | * If 11d had a rule for this channel ensure | 219 | * If 11d had a rule for this channel ensure |
@@ -254,8 +249,6 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, | |||
254 | struct ieee80211_supported_band *sband; | 249 | struct ieee80211_supported_band *sband; |
255 | struct ieee80211_channel *ch; | 250 | struct ieee80211_channel *ch; |
256 | const struct ieee80211_reg_rule *reg_rule; | 251 | const struct ieee80211_reg_rule *reg_rule; |
257 | u32 bandwidth = 0; | ||
258 | int r; | ||
259 | 252 | ||
260 | sband = wiphy->bands[IEEE80211_BAND_2GHZ]; | 253 | sband = wiphy->bands[IEEE80211_BAND_2GHZ]; |
261 | if (!sband) | 254 | if (!sband) |
@@ -283,16 +276,16 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, | |||
283 | */ | 276 | */ |
284 | 277 | ||
285 | ch = &sband->channels[11]; /* CH 12 */ | 278 | ch = &sband->channels[11]; /* CH 12 */ |
286 | r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); | 279 | reg_rule = freq_reg_info(wiphy, ch->center_freq); |
287 | if (!r) { | 280 | if (!IS_ERR(reg_rule)) { |
288 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) | 281 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) |
289 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 282 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) |
290 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 283 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; |
291 | } | 284 | } |
292 | 285 | ||
293 | ch = &sband->channels[12]; /* CH 13 */ | 286 | ch = &sband->channels[12]; /* CH 13 */ |
294 | r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); | 287 | reg_rule = freq_reg_info(wiphy, ch->center_freq); |
295 | if (!r) { | 288 | if (!IS_ERR(reg_rule)) { |
296 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) | 289 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) |
297 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 290 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) |
298 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 291 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; |
@@ -363,9 +356,9 @@ static u16 ath_regd_find_country_by_name(char *alpha2) | |||
363 | return -1; | 356 | return -1; |
364 | } | 357 | } |
365 | 358 | ||
366 | int ath_reg_notifier_apply(struct wiphy *wiphy, | 359 | void ath_reg_notifier_apply(struct wiphy *wiphy, |
367 | struct regulatory_request *request, | 360 | struct regulatory_request *request, |
368 | struct ath_regulatory *reg) | 361 | struct ath_regulatory *reg) |
369 | { | 362 | { |
370 | struct ath_common *common = container_of(reg, struct ath_common, | 363 | struct ath_common *common = container_of(reg, struct ath_common, |
371 | regulatory); | 364 | regulatory); |
@@ -380,7 +373,7 @@ int ath_reg_notifier_apply(struct wiphy *wiphy, | |||
380 | * any pending requests in the queue. | 373 | * any pending requests in the queue. |
381 | */ | 374 | */ |
382 | if (!request) | 375 | if (!request) |
383 | return 0; | 376 | return; |
384 | 377 | ||
385 | switch (request->initiator) { | 378 | switch (request->initiator) { |
386 | case NL80211_REGDOM_SET_BY_CORE: | 379 | case NL80211_REGDOM_SET_BY_CORE: |
@@ -416,8 +409,6 @@ int ath_reg_notifier_apply(struct wiphy *wiphy, | |||
416 | 409 | ||
417 | break; | 410 | break; |
418 | } | 411 | } |
419 | |||
420 | return 0; | ||
421 | } | 412 | } |
422 | EXPORT_SYMBOL(ath_reg_notifier_apply); | 413 | EXPORT_SYMBOL(ath_reg_notifier_apply); |
423 | 414 | ||
@@ -507,8 +498,8 @@ ath_get_regpair(int regdmn) | |||
507 | static int | 498 | static int |
508 | ath_regd_init_wiphy(struct ath_regulatory *reg, | 499 | ath_regd_init_wiphy(struct ath_regulatory *reg, |
509 | struct wiphy *wiphy, | 500 | struct wiphy *wiphy, |
510 | int (*reg_notifier)(struct wiphy *wiphy, | 501 | void (*reg_notifier)(struct wiphy *wiphy, |
511 | struct regulatory_request *request)) | 502 | struct regulatory_request *request)) |
512 | { | 503 | { |
513 | const struct ieee80211_regdomain *regd; | 504 | const struct ieee80211_regdomain *regd; |
514 | 505 | ||
@@ -628,8 +619,8 @@ static int __ath_regd_init(struct ath_regulatory *reg) | |||
628 | int | 619 | int |
629 | ath_regd_init(struct ath_regulatory *reg, | 620 | ath_regd_init(struct ath_regulatory *reg, |
630 | struct wiphy *wiphy, | 621 | struct wiphy *wiphy, |
631 | int (*reg_notifier)(struct wiphy *wiphy, | 622 | void (*reg_notifier)(struct wiphy *wiphy, |
632 | struct regulatory_request *request)) | 623 | struct regulatory_request *request)) |
633 | { | 624 | { |
634 | struct ath_common *common = container_of(reg, struct ath_common, | 625 | struct ath_common *common = container_of(reg, struct ath_common, |
635 | regulatory); | 626 | regulatory); |
diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index 03a8268ccf21..37f53bd8fcb1 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h | |||
@@ -252,12 +252,12 @@ enum CountryCode { | |||
252 | bool ath_is_world_regd(struct ath_regulatory *reg); | 252 | bool ath_is_world_regd(struct ath_regulatory *reg); |
253 | bool ath_is_49ghz_allowed(u16 redomain); | 253 | bool ath_is_49ghz_allowed(u16 redomain); |
254 | int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy, | 254 | int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy, |
255 | int (*reg_notifier)(struct wiphy *wiphy, | 255 | void (*reg_notifier)(struct wiphy *wiphy, |
256 | struct regulatory_request *request)); | 256 | struct regulatory_request *request)); |
257 | u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, | 257 | u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, |
258 | enum ieee80211_band band); | 258 | enum ieee80211_band band); |
259 | int ath_reg_notifier_apply(struct wiphy *wiphy, | 259 | void ath_reg_notifier_apply(struct wiphy *wiphy, |
260 | struct regulatory_request *request, | 260 | struct regulatory_request *request, |
261 | struct ath_regulatory *reg); | 261 | struct ath_regulatory *reg); |
262 | 262 | ||
263 | #endif | 263 | #endif |
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index 97d4e27bf36f..aaca60c6f575 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c | |||
@@ -3226,8 +3226,6 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent( | |||
3226 | { | 3226 | { |
3227 | struct nphy_gain_ctl_workaround_entry *e; | 3227 | struct nphy_gain_ctl_workaround_entry *e; |
3228 | u8 phy_idx; | 3228 | u8 phy_idx; |
3229 | u8 tr_iso = ghz5 ? dev->dev->bus_sprom->fem.ghz5.tr_iso : | ||
3230 | dev->dev->bus_sprom->fem.ghz2.tr_iso; | ||
3231 | 3229 | ||
3232 | if (!ghz5 && dev->phy.rev >= 6 && dev->phy.radio_rev == 11) | 3230 | if (!ghz5 && dev->phy.rev >= 6 && dev->phy.radio_rev == 11) |
3233 | return &nphy_gain_ctl_wa_phy6_radio11_ghz2; | 3231 | return &nphy_gain_ctl_wa_phy6_radio11_ghz2; |
@@ -3249,6 +3247,10 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent( | |||
3249 | !b43_channel_type_is_40mhz(dev->phy.channel_type)) | 3247 | !b43_channel_type_is_40mhz(dev->phy.channel_type)) |
3250 | e->cliplo_gain = 0x2d; | 3248 | e->cliplo_gain = 0x2d; |
3251 | } else if (!ghz5 && dev->phy.rev >= 5) { | 3249 | } else if (!ghz5 && dev->phy.rev >= 5) { |
3250 | static const int gain_data[] = {0x0062, 0x0064, 0x006a, 0x106a, | ||
3251 | 0x106c, 0x1074, 0x107c, 0x207c}; | ||
3252 | u8 tr_iso = dev->dev->bus_sprom->fem.ghz2.tr_iso; | ||
3253 | |||
3252 | if (ext_lna) { | 3254 | if (ext_lna) { |
3253 | e->rfseq_init[0] &= ~0x4000; | 3255 | e->rfseq_init[0] &= ~0x4000; |
3254 | e->rfseq_init[1] &= ~0x4000; | 3256 | e->rfseq_init[1] &= ~0x4000; |
@@ -3256,26 +3258,10 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent( | |||
3256 | e->rfseq_init[3] &= ~0x4000; | 3258 | e->rfseq_init[3] &= ~0x4000; |
3257 | e->init_gain &= ~0x4000; | 3259 | e->init_gain &= ~0x4000; |
3258 | } | 3260 | } |
3259 | switch (tr_iso) { | 3261 | if (tr_iso > 7) |
3260 | case 0: | 3262 | tr_iso = 3; |
3261 | e->cliplo_gain = 0x0062; | 3263 | e->cliplo_gain = gain_data[tr_iso]; |
3262 | case 1: | 3264 | |
3263 | e->cliplo_gain = 0x0064; | ||
3264 | case 2: | ||
3265 | e->cliplo_gain = 0x006a; | ||
3266 | case 3: | ||
3267 | e->cliplo_gain = 0x106a; | ||
3268 | case 4: | ||
3269 | e->cliplo_gain = 0x106c; | ||
3270 | case 5: | ||
3271 | e->cliplo_gain = 0x1074; | ||
3272 | case 6: | ||
3273 | e->cliplo_gain = 0x107c; | ||
3274 | case 7: | ||
3275 | e->cliplo_gain = 0x207c; | ||
3276 | default: | ||
3277 | e->cliplo_gain = 0x106a; | ||
3278 | } | ||
3279 | } else if (ghz5 && dev->phy.rev == 4 && ext_lna) { | 3265 | } else if (ghz5 && dev->phy.rev == 4 && ext_lna) { |
3280 | e->rfseq_init[0] &= ~0x4000; | 3266 | e->rfseq_init[0] &= ~0x4000; |
3281 | e->rfseq_init[1] &= ~0x4000; | 3267 | e->rfseq_init[1] &= ~0x4000; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index be35a2f99b1c..11fd1c735589 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -15,8 +15,6 @@ | |||
15 | */ | 15 | */ |
16 | /* ****************** SDIO CARD Interface Functions **************************/ | 16 | /* ****************** SDIO CARD Interface Functions **************************/ |
17 | 17 | ||
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
19 | |||
20 | #include <linux/types.h> | 18 | #include <linux/types.h> |
21 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
22 | #include <linux/export.h> | 20 | #include <linux/export.h> |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index d33e5598611b..d92d373733d7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
@@ -14,8 +14,6 @@ | |||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include <linux/types.h> | 17 | #include <linux/types.h> |
20 | #include <linux/netdevice.h> | 18 | #include <linux/netdevice.h> |
21 | #include <linux/mmc/sdio.h> | 19 | #include <linux/mmc/sdio.h> |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index fd672bf53867..a2f32fb990fa 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #define BRCMF_C_GET_BSSID 23 | 39 | #define BRCMF_C_GET_BSSID 23 |
40 | #define BRCMF_C_GET_SSID 25 | 40 | #define BRCMF_C_GET_SSID 25 |
41 | #define BRCMF_C_SET_SSID 26 | 41 | #define BRCMF_C_SET_SSID 26 |
42 | #define BRCMF_C_TERMINATED 28 | ||
42 | #define BRCMF_C_GET_CHANNEL 29 | 43 | #define BRCMF_C_GET_CHANNEL 29 |
43 | #define BRCMF_C_SET_CHANNEL 30 | 44 | #define BRCMF_C_SET_CHANNEL 30 |
44 | #define BRCMF_C_GET_SRL 31 | 45 | #define BRCMF_C_GET_SRL 31 |
@@ -480,36 +481,14 @@ struct brcmf_pub { | |||
480 | unsigned long drv_version; /* Version of dongle-resident driver */ | 481 | unsigned long drv_version; /* Version of dongle-resident driver */ |
481 | u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ | 482 | u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ |
482 | 483 | ||
483 | /* Additional stats for the bus level */ | ||
484 | |||
485 | /* Multicast data packets sent to dongle */ | 484 | /* Multicast data packets sent to dongle */ |
486 | unsigned long tx_multicast; | 485 | unsigned long tx_multicast; |
487 | /* Packets flushed due to unscheduled sendup thread */ | ||
488 | unsigned long rx_flushed; | ||
489 | /* Number of times dpc scheduled by watchdog timer */ | ||
490 | unsigned long wd_dpc_sched; | ||
491 | |||
492 | /* Number of flow control pkts recvd */ | ||
493 | unsigned long fc_packets; | ||
494 | |||
495 | /* Last error return */ | ||
496 | int bcmerror; | ||
497 | |||
498 | /* Last error from dongle */ | ||
499 | int dongle_error; | ||
500 | |||
501 | /* Suspend disable flag flag */ | ||
502 | int suspend_disable_flag; /* "1" to disable all extra powersaving | ||
503 | during suspend */ | ||
504 | int in_suspend; /* flag set to 1 when early suspend called */ | ||
505 | int dtim_skip; /* dtim skip , default 0 means wake each dtim */ | ||
506 | 486 | ||
507 | struct brcmf_if *iflist[BRCMF_MAX_IFS]; | 487 | struct brcmf_if *iflist[BRCMF_MAX_IFS]; |
508 | 488 | ||
509 | struct mutex proto_block; | 489 | struct mutex proto_block; |
510 | unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; | 490 | unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; |
511 | 491 | ||
512 | u8 macvalue[ETH_ALEN]; | ||
513 | atomic_t pend_8021x_cnt; | 492 | atomic_t pend_8021x_cnt; |
514 | wait_queue_head_t pend_8021x_wait; | 493 | wait_queue_head_t pend_8021x_wait; |
515 | 494 | ||
@@ -519,11 +498,6 @@ struct brcmf_pub { | |||
519 | #endif | 498 | #endif |
520 | }; | 499 | }; |
521 | 500 | ||
522 | struct bcmevent_name { | ||
523 | uint event; | ||
524 | const char *name; | ||
525 | }; | ||
526 | |||
527 | struct brcmf_if_event { | 501 | struct brcmf_if_event { |
528 | u8 ifidx; | 502 | u8 ifidx; |
529 | u8 action; | 503 | u8 action; |
@@ -557,13 +531,6 @@ struct brcmf_if { | |||
557 | u8 mac_addr[ETH_ALEN]; | 531 | u8 mac_addr[ETH_ALEN]; |
558 | }; | 532 | }; |
559 | 533 | ||
560 | static inline s32 brcmf_ndev_bssidx(struct net_device *ndev) | ||
561 | { | ||
562 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
563 | return ifp->bssidx; | ||
564 | } | ||
565 | |||
566 | extern const struct bcmevent_name bcmevent_names[]; | ||
567 | 534 | ||
568 | extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); | 535 | extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); |
569 | 536 | ||
@@ -576,6 +543,10 @@ extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, | |||
576 | extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | 543 | extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, |
577 | void *buf, uint len); | 544 | void *buf, uint len); |
578 | 545 | ||
546 | /* Remove any protocol-specific data header. */ | ||
547 | extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, | ||
548 | struct sk_buff *rxp); | ||
549 | |||
579 | extern int brcmf_net_attach(struct brcmf_if *ifp); | 550 | extern int brcmf_net_attach(struct brcmf_if *ifp); |
580 | extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, | 551 | extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, |
581 | s32 bssidx, char *name, u8 *mac_addr); | 552 | s32 bssidx, char *name, u8 *mac_addr); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index dd38b78a9726..64c38f4226a3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -130,31 +130,18 @@ int brcmf_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint len) | |||
130 | * interface functions from common layer | 130 | * interface functions from common layer |
131 | */ | 131 | */ |
132 | 132 | ||
133 | /* Remove any protocol-specific data header. */ | ||
134 | extern int brcmf_proto_hdrpull(struct device *dev, int *ifidx, | ||
135 | struct sk_buff *rxp); | ||
136 | |||
137 | extern bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, | 133 | extern bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, |
138 | struct sk_buff *pkt, int prec); | 134 | struct sk_buff *pkt, int prec); |
139 | 135 | ||
140 | /* Receive frame for delivery to OS. Callee disposes of rxp. */ | 136 | /* Receive frame for delivery to OS. Callee disposes of rxp. */ |
141 | extern void brcmf_rx_frame(struct device *dev, u8 ifidx, | 137 | extern void brcmf_rx_frames(struct device *dev, struct sk_buff_head *rxlist); |
142 | struct sk_buff_head *rxlist); | ||
143 | static inline void brcmf_rx_packet(struct device *dev, int ifidx, | ||
144 | struct sk_buff *pkt) | ||
145 | { | ||
146 | struct sk_buff_head q; | ||
147 | |||
148 | skb_queue_head_init(&q); | ||
149 | skb_queue_tail(&q, pkt); | ||
150 | brcmf_rx_frame(dev, ifidx, &q); | ||
151 | } | ||
152 | 138 | ||
153 | /* Indication from bus module regarding presence/insertion of dongle. */ | 139 | /* Indication from bus module regarding presence/insertion of dongle. */ |
154 | extern int brcmf_attach(uint bus_hdrlen, struct device *dev); | 140 | extern int brcmf_attach(uint bus_hdrlen, struct device *dev); |
155 | /* Indication from bus module regarding removal/absence of dongle */ | 141 | /* Indication from bus module regarding removal/absence of dongle */ |
156 | extern void brcmf_detach(struct device *dev); | 142 | extern void brcmf_detach(struct device *dev); |
157 | 143 | /* Indication from bus module that dongle should be reset */ | |
144 | extern void brcmf_dev_reset(struct device *dev); | ||
158 | /* Indication from bus module to change flow-control state */ | 145 | /* Indication from bus module to change flow-control state */ |
159 | extern void brcmf_txflowblock(struct device *dev, bool state); | 146 | extern void brcmf_txflowblock(struct device *dev, bool state); |
160 | 147 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index 83923553f1ac..bb454cdab29d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c | |||
@@ -19,8 +19,6 @@ | |||
19 | * For certain dcmd codes, the dongle interprets string data from the host. | 19 | * For certain dcmd codes, the dongle interprets string data from the host. |
20 | ******************************************************************************/ | 20 | ******************************************************************************/ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
24 | #include <linux/types.h> | 22 | #include <linux/types.h> |
25 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
26 | 24 | ||
@@ -94,8 +92,6 @@ struct brcmf_proto_bdc_header { | |||
94 | 92 | ||
95 | struct brcmf_proto { | 93 | struct brcmf_proto { |
96 | u16 reqid; | 94 | u16 reqid; |
97 | u8 pending; | ||
98 | u32 lastcmd; | ||
99 | u8 bus_header[BUS_HEADER_LEN]; | 95 | u8 bus_header[BUS_HEADER_LEN]; |
100 | struct brcmf_proto_cdc_dcmd msg; | 96 | struct brcmf_proto_cdc_dcmd msg; |
101 | unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; | 97 | unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; |
@@ -107,7 +103,7 @@ static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) | |||
107 | int len = le32_to_cpu(prot->msg.len) + | 103 | int len = le32_to_cpu(prot->msg.len) + |
108 | sizeof(struct brcmf_proto_cdc_dcmd); | 104 | sizeof(struct brcmf_proto_cdc_dcmd); |
109 | 105 | ||
110 | brcmf_dbg(TRACE, "Enter\n"); | 106 | brcmf_dbg(CDC, "Enter\n"); |
111 | 107 | ||
112 | /* NOTE : cdc->msg.len holds the desired length of the buffer to be | 108 | /* NOTE : cdc->msg.len holds the desired length of the buffer to be |
113 | * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area | 109 | * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area |
@@ -125,7 +121,7 @@ static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) | |||
125 | int ret; | 121 | int ret; |
126 | struct brcmf_proto *prot = drvr->prot; | 122 | struct brcmf_proto *prot = drvr->prot; |
127 | 123 | ||
128 | brcmf_dbg(TRACE, "Enter\n"); | 124 | brcmf_dbg(CDC, "Enter\n"); |
129 | len += sizeof(struct brcmf_proto_cdc_dcmd); | 125 | len += sizeof(struct brcmf_proto_cdc_dcmd); |
130 | do { | 126 | do { |
131 | ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&prot->msg, | 127 | ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&prot->msg, |
@@ -147,20 +143,7 @@ brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | |||
147 | int ret = 0, retries = 0; | 143 | int ret = 0, retries = 0; |
148 | u32 id, flags; | 144 | u32 id, flags; |
149 | 145 | ||
150 | brcmf_dbg(TRACE, "Enter\n"); | 146 | brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len); |
151 | brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len); | ||
152 | |||
153 | /* Respond "bcmerror" and "bcmerrorstr" with local cache */ | ||
154 | if (cmd == BRCMF_C_GET_VAR && buf) { | ||
155 | if (!strcmp((char *)buf, "bcmerrorstr")) { | ||
156 | strncpy((char *)buf, "bcm_error", | ||
157 | BCME_STRLEN); | ||
158 | goto done; | ||
159 | } else if (!strcmp((char *)buf, "bcmerror")) { | ||
160 | *(int *)buf = drvr->dongle_error; | ||
161 | goto done; | ||
162 | } | ||
163 | } | ||
164 | 147 | ||
165 | memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); | 148 | memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); |
166 | 149 | ||
@@ -210,11 +193,8 @@ retry: | |||
210 | } | 193 | } |
211 | 194 | ||
212 | /* Check the ERROR flag */ | 195 | /* Check the ERROR flag */ |
213 | if (flags & CDC_DCMD_ERROR) { | 196 | if (flags & CDC_DCMD_ERROR) |
214 | ret = le32_to_cpu(msg->status); | 197 | ret = le32_to_cpu(msg->status); |
215 | /* Cache error from dongle */ | ||
216 | drvr->dongle_error = ret; | ||
217 | } | ||
218 | 198 | ||
219 | done: | 199 | done: |
220 | return ret; | 200 | return ret; |
@@ -228,8 +208,7 @@ int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | |||
228 | int ret = 0; | 208 | int ret = 0; |
229 | u32 flags, id; | 209 | u32 flags, id; |
230 | 210 | ||
231 | brcmf_dbg(TRACE, "Enter\n"); | 211 | brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len); |
232 | brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len); | ||
233 | 212 | ||
234 | memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); | 213 | memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); |
235 | 214 | ||
@@ -262,11 +241,8 @@ int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | |||
262 | } | 241 | } |
263 | 242 | ||
264 | /* Check the ERROR flag */ | 243 | /* Check the ERROR flag */ |
265 | if (flags & CDC_DCMD_ERROR) { | 244 | if (flags & CDC_DCMD_ERROR) |
266 | ret = le32_to_cpu(msg->status); | 245 | ret = le32_to_cpu(msg->status); |
267 | /* Cache error from dongle */ | ||
268 | drvr->dongle_error = ret; | ||
269 | } | ||
270 | 246 | ||
271 | done: | 247 | done: |
272 | return ret; | 248 | return ret; |
@@ -287,7 +263,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | |||
287 | { | 263 | { |
288 | struct brcmf_proto_bdc_header *h; | 264 | struct brcmf_proto_bdc_header *h; |
289 | 265 | ||
290 | brcmf_dbg(TRACE, "Enter\n"); | 266 | brcmf_dbg(CDC, "Enter\n"); |
291 | 267 | ||
292 | /* Push BDC header used to convey priority for buses that don't */ | 268 | /* Push BDC header used to convey priority for buses that don't */ |
293 | 269 | ||
@@ -305,14 +281,12 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | |||
305 | BDC_SET_IF_IDX(h, ifidx); | 281 | BDC_SET_IF_IDX(h, ifidx); |
306 | } | 282 | } |
307 | 283 | ||
308 | int brcmf_proto_hdrpull(struct device *dev, int *ifidx, | 284 | int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, |
309 | struct sk_buff *pktbuf) | 285 | struct sk_buff *pktbuf) |
310 | { | 286 | { |
311 | struct brcmf_proto_bdc_header *h; | 287 | struct brcmf_proto_bdc_header *h; |
312 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
313 | struct brcmf_pub *drvr = bus_if->drvr; | ||
314 | 288 | ||
315 | brcmf_dbg(TRACE, "Enter\n"); | 289 | brcmf_dbg(CDC, "Enter\n"); |
316 | 290 | ||
317 | /* Pop BDC header used to convey priority for buses that don't */ | 291 | /* Pop BDC header used to convey priority for buses that don't */ |
318 | 292 | ||
@@ -338,7 +312,7 @@ int brcmf_proto_hdrpull(struct device *dev, int *ifidx, | |||
338 | } | 312 | } |
339 | 313 | ||
340 | if (h->flags & BDC_FLAG_SUM_GOOD) { | 314 | if (h->flags & BDC_FLAG_SUM_GOOD) { |
341 | brcmf_dbg(INFO, "%s: BDC packet received with good rx-csum, flags 0x%x\n", | 315 | brcmf_dbg(CDC, "%s: BDC rcv, good checksum, flags 0x%x\n", |
342 | brcmf_ifname(drvr, *ifidx), h->flags); | 316 | brcmf_ifname(drvr, *ifidx), h->flags); |
343 | pkt_set_sum_good(pktbuf, true); | 317 | pkt_set_sum_good(pktbuf, true); |
344 | } | 318 | } |
@@ -348,6 +322,8 @@ int brcmf_proto_hdrpull(struct device *dev, int *ifidx, | |||
348 | skb_pull(pktbuf, BDC_HEADER_LEN); | 322 | skb_pull(pktbuf, BDC_HEADER_LEN); |
349 | skb_pull(pktbuf, h->data_offset << 2); | 323 | skb_pull(pktbuf, h->data_offset << 2); |
350 | 324 | ||
325 | if (pktbuf->len == 0) | ||
326 | return -ENODATA; | ||
351 | return 0; | 327 | return 0; |
352 | } | 328 | } |
353 | 329 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index f8b52e5b941a..4544342a0428 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | |||
@@ -14,8 +14,6 @@ | |||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
20 | #include <linux/string.h> | 18 | #include <linux/string.h> |
21 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index f2ab01cd7966..bc013cbe06f6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | |||
@@ -18,21 +18,26 @@ | |||
18 | #define _BRCMF_DBG_H_ | 18 | #define _BRCMF_DBG_H_ |
19 | 19 | ||
20 | /* message levels */ | 20 | /* message levels */ |
21 | #define BRCMF_TRACE_VAL 0x0002 | 21 | #define BRCMF_TRACE_VAL 0x00000002 |
22 | #define BRCMF_INFO_VAL 0x0004 | 22 | #define BRCMF_INFO_VAL 0x00000004 |
23 | #define BRCMF_DATA_VAL 0x0008 | 23 | #define BRCMF_DATA_VAL 0x00000008 |
24 | #define BRCMF_CTL_VAL 0x0010 | 24 | #define BRCMF_CTL_VAL 0x00000010 |
25 | #define BRCMF_TIMER_VAL 0x0020 | 25 | #define BRCMF_TIMER_VAL 0x00000020 |
26 | #define BRCMF_HDRS_VAL 0x0040 | 26 | #define BRCMF_HDRS_VAL 0x00000040 |
27 | #define BRCMF_BYTES_VAL 0x0080 | 27 | #define BRCMF_BYTES_VAL 0x00000080 |
28 | #define BRCMF_INTR_VAL 0x0100 | 28 | #define BRCMF_INTR_VAL 0x00000100 |
29 | #define BRCMF_GLOM_VAL 0x0200 | 29 | #define BRCMF_GLOM_VAL 0x00000200 |
30 | #define BRCMF_EVENT_VAL 0x0400 | 30 | #define BRCMF_EVENT_VAL 0x00000400 |
31 | #define BRCMF_BTA_VAL 0x0800 | 31 | #define BRCMF_BTA_VAL 0x00000800 |
32 | #define BRCMF_FIL_VAL 0x1000 | 32 | #define BRCMF_FIL_VAL 0x00001000 |
33 | #define BRCMF_USB_VAL 0x2000 | 33 | #define BRCMF_USB_VAL 0x00002000 |
34 | #define BRCMF_SCAN_VAL 0x4000 | 34 | #define BRCMF_SCAN_VAL 0x00004000 |
35 | #define BRCMF_CONN_VAL 0x8000 | 35 | #define BRCMF_CONN_VAL 0x00008000 |
36 | #define BRCMF_CDC_VAL 0x00010000 | ||
37 | |||
38 | /* set default print format */ | ||
39 | #undef pr_fmt | ||
40 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
36 | 41 | ||
37 | /* Macro for error messages. net_ratelimit() is used when driver | 42 | /* Macro for error messages. net_ratelimit() is used when driver |
38 | * debugging is not selected. When debugging the driver error | 43 | * debugging is not selected. When debugging the driver error |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 8c28a1518409..14b8fdde6954 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -14,8 +14,6 @@ | |||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
20 | #include <linux/etherdevice.h> | 18 | #include <linux/etherdevice.h> |
21 | #include <linux/module.h> | 19 | #include <linux/module.h> |
@@ -162,28 +160,31 @@ static void brcmf_netdev_set_multicast_list(struct net_device *ndev) | |||
162 | schedule_work(&ifp->multicast_work); | 160 | schedule_work(&ifp->multicast_work); |
163 | } | 161 | } |
164 | 162 | ||
165 | static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) | 163 | static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, |
164 | struct net_device *ndev) | ||
166 | { | 165 | { |
167 | int ret; | 166 | int ret; |
168 | struct brcmf_if *ifp = netdev_priv(ndev); | 167 | struct brcmf_if *ifp = netdev_priv(ndev); |
169 | struct brcmf_pub *drvr = ifp->drvr; | 168 | struct brcmf_pub *drvr = ifp->drvr; |
169 | struct ethhdr *eh; | ||
170 | 170 | ||
171 | brcmf_dbg(TRACE, "Enter\n"); | 171 | brcmf_dbg(TRACE, "Enter\n"); |
172 | 172 | ||
173 | /* Reject if down */ | 173 | /* Can the device send data? */ |
174 | if (!drvr->bus_if->drvr_up || | 174 | if (drvr->bus_if->state != BRCMF_BUS_DATA) { |
175 | (drvr->bus_if->state != BRCMF_BUS_DATA)) { | 175 | brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state); |
176 | brcmf_err("xmit rejected drvup=%d state=%d\n", | ||
177 | drvr->bus_if->drvr_up, | ||
178 | drvr->bus_if->state); | ||
179 | netif_stop_queue(ndev); | 176 | netif_stop_queue(ndev); |
180 | return -ENODEV; | 177 | dev_kfree_skb(skb); |
178 | ret = -ENODEV; | ||
179 | goto done; | ||
181 | } | 180 | } |
182 | 181 | ||
183 | if (!drvr->iflist[ifp->idx]) { | 182 | if (!drvr->iflist[ifp->idx]) { |
184 | brcmf_err("bad ifidx %d\n", ifp->idx); | 183 | brcmf_err("bad ifidx %d\n", ifp->idx); |
185 | netif_stop_queue(ndev); | 184 | netif_stop_queue(ndev); |
186 | return -ENODEV; | 185 | dev_kfree_skb(skb); |
186 | ret = -ENODEV; | ||
187 | goto done; | ||
187 | } | 188 | } |
188 | 189 | ||
189 | /* Make sure there's enough room for any header */ | 190 | /* Make sure there's enough room for any header */ |
@@ -204,17 +205,20 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
204 | } | 205 | } |
205 | } | 206 | } |
206 | 207 | ||
207 | /* Update multicast statistic */ | 208 | /* validate length for ether packet */ |
208 | if (skb->len >= ETH_ALEN) { | 209 | if (skb->len < sizeof(*eh)) { |
209 | u8 *pktdata = (u8 *)(skb->data); | 210 | ret = -EINVAL; |
210 | struct ethhdr *eh = (struct ethhdr *)pktdata; | 211 | dev_kfree_skb(skb); |
211 | 212 | goto done; | |
212 | if (is_multicast_ether_addr(eh->h_dest)) | ||
213 | drvr->tx_multicast++; | ||
214 | if (ntohs(eh->h_proto) == ETH_P_PAE) | ||
215 | atomic_inc(&drvr->pend_8021x_cnt); | ||
216 | } | 213 | } |
217 | 214 | ||
215 | /* handle ethernet header */ | ||
216 | eh = (struct ethhdr *)(skb->data); | ||
217 | if (is_multicast_ether_addr(eh->h_dest)) | ||
218 | drvr->tx_multicast++; | ||
219 | if (ntohs(eh->h_proto) == ETH_P_PAE) | ||
220 | atomic_inc(&drvr->pend_8021x_cnt); | ||
221 | |||
218 | /* If the protocol uses a data header, apply it */ | 222 | /* If the protocol uses a data header, apply it */ |
219 | brcmf_proto_hdrpush(drvr, ifp->idx, skb); | 223 | brcmf_proto_hdrpush(drvr, ifp->idx, skb); |
220 | 224 | ||
@@ -228,7 +232,7 @@ done: | |||
228 | drvr->bus_if->dstats.tx_packets++; | 232 | drvr->bus_if->dstats.tx_packets++; |
229 | 233 | ||
230 | /* Return ok: we always eat the packet */ | 234 | /* Return ok: we always eat the packet */ |
231 | return 0; | 235 | return NETDEV_TX_OK; |
232 | } | 236 | } |
233 | 237 | ||
234 | void brcmf_txflowblock(struct device *dev, bool state) | 238 | void brcmf_txflowblock(struct device *dev, bool state) |
@@ -250,8 +254,7 @@ void brcmf_txflowblock(struct device *dev, bool state) | |||
250 | } | 254 | } |
251 | } | 255 | } |
252 | 256 | ||
253 | void brcmf_rx_frame(struct device *dev, u8 ifidx, | 257 | void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) |
254 | struct sk_buff_head *skb_list) | ||
255 | { | 258 | { |
256 | unsigned char *eth; | 259 | unsigned char *eth; |
257 | uint len; | 260 | uint len; |
@@ -259,12 +262,24 @@ void brcmf_rx_frame(struct device *dev, u8 ifidx, | |||
259 | struct brcmf_if *ifp; | 262 | struct brcmf_if *ifp; |
260 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 263 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
261 | struct brcmf_pub *drvr = bus_if->drvr; | 264 | struct brcmf_pub *drvr = bus_if->drvr; |
265 | u8 ifidx; | ||
266 | int ret; | ||
262 | 267 | ||
263 | brcmf_dbg(TRACE, "Enter\n"); | 268 | brcmf_dbg(TRACE, "Enter\n"); |
264 | 269 | ||
265 | skb_queue_walk_safe(skb_list, skb, pnext) { | 270 | skb_queue_walk_safe(skb_list, skb, pnext) { |
266 | skb_unlink(skb, skb_list); | 271 | skb_unlink(skb, skb_list); |
267 | 272 | ||
273 | /* process and remove protocol-specific header | ||
274 | */ | ||
275 | ret = brcmf_proto_hdrpull(drvr, &ifidx, skb); | ||
276 | if (ret < 0) { | ||
277 | if (ret != -ENODATA) | ||
278 | bus_if->dstats.rx_errors++; | ||
279 | brcmu_pkt_buf_free_skb(skb); | ||
280 | continue; | ||
281 | } | ||
282 | |||
268 | /* Get the protocol, maintain skb around eth_type_trans() | 283 | /* Get the protocol, maintain skb around eth_type_trans() |
269 | * The main reason for this hack is for the limitation of | 284 | * The main reason for this hack is for the limitation of |
270 | * Linux 2.4 where 'eth_type_trans' uses the | 285 | * Linux 2.4 where 'eth_type_trans' uses the |
@@ -328,13 +343,13 @@ void brcmf_rx_frame(struct device *dev, u8 ifidx, | |||
328 | 343 | ||
329 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) | 344 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) |
330 | { | 345 | { |
331 | uint ifidx; | 346 | u8 ifidx; |
332 | struct ethhdr *eh; | 347 | struct ethhdr *eh; |
333 | u16 type; | 348 | u16 type; |
334 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 349 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
335 | struct brcmf_pub *drvr = bus_if->drvr; | 350 | struct brcmf_pub *drvr = bus_if->drvr; |
336 | 351 | ||
337 | brcmf_proto_hdrpull(dev, &ifidx, txp); | 352 | brcmf_proto_hdrpull(drvr, &ifidx, txp); |
338 | 353 | ||
339 | eh = (struct ethhdr *)(txp->data); | 354 | eh = (struct ethhdr *)(txp->data); |
340 | type = ntohs(eh->h_proto); | 355 | type = ntohs(eh->h_proto); |
@@ -452,7 +467,7 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr) | |||
452 | sprintf(info.version, "%lu", drvr->drv_version); | 467 | sprintf(info.version, "%lu", drvr->drv_version); |
453 | if (copy_to_user(uaddr, &info, sizeof(info))) | 468 | if (copy_to_user(uaddr, &info, sizeof(info))) |
454 | return -EFAULT; | 469 | return -EFAULT; |
455 | brcmf_dbg(CTL, "given %*s, returning %s\n", | 470 | brcmf_dbg(TRACE, "given %*s, returning %s\n", |
456 | (int)sizeof(drvname), drvname, info.driver); | 471 | (int)sizeof(drvname), drvname, info.driver); |
457 | break; | 472 | break; |
458 | 473 | ||
@@ -572,14 +587,9 @@ static int brcmf_netdev_open(struct net_device *ndev) | |||
572 | /* Get current TOE mode from dongle */ | 587 | /* Get current TOE mode from dongle */ |
573 | if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0 | 588 | if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0 |
574 | && (toe_ol & TOE_TX_CSUM_OL) != 0) | 589 | && (toe_ol & TOE_TX_CSUM_OL) != 0) |
575 | drvr->iflist[ifp->idx]->ndev->features |= | 590 | ndev->features |= NETIF_F_IP_CSUM; |
576 | NETIF_F_IP_CSUM; | ||
577 | else | 591 | else |
578 | drvr->iflist[ifp->idx]->ndev->features &= | 592 | ndev->features &= ~NETIF_F_IP_CSUM; |
579 | ~NETIF_F_IP_CSUM; | ||
580 | |||
581 | /* make sure RF is ready for work */ | ||
582 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0); | ||
583 | 593 | ||
584 | /* Allow transmit calls */ | 594 | /* Allow transmit calls */ |
585 | netif_start_queue(ndev); | 595 | netif_start_queue(ndev); |
@@ -847,6 +857,17 @@ static void brcmf_bus_detach(struct brcmf_pub *drvr) | |||
847 | } | 857 | } |
848 | } | 858 | } |
849 | 859 | ||
860 | void brcmf_dev_reset(struct device *dev) | ||
861 | { | ||
862 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
863 | struct brcmf_pub *drvr = bus_if->drvr; | ||
864 | |||
865 | if (drvr == NULL) | ||
866 | return; | ||
867 | |||
868 | brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1); | ||
869 | } | ||
870 | |||
850 | void brcmf_detach(struct device *dev) | 871 | void brcmf_detach(struct device *dev) |
851 | { | 872 | { |
852 | int i; | 873 | int i; |
@@ -868,9 +889,8 @@ void brcmf_detach(struct device *dev) | |||
868 | 889 | ||
869 | brcmf_bus_detach(drvr); | 890 | brcmf_bus_detach(drvr); |
870 | 891 | ||
871 | if (drvr->prot) { | 892 | if (drvr->prot) |
872 | brcmf_proto_detach(drvr); | 893 | brcmf_proto_detach(drvr); |
873 | } | ||
874 | 894 | ||
875 | brcmf_debugfs_detach(drvr); | 895 | brcmf_debugfs_detach(drvr); |
876 | bus_if->drvr = NULL; | 896 | bus_if->drvr = NULL; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index cf857f1edf8c..7fef9b5ba003 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -14,8 +14,6 @@ | |||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include <linux/types.h> | 17 | #include <linux/types.h> |
20 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
21 | #include <linux/kthread.h> | 19 | #include <linux/kthread.h> |
@@ -1169,7 +1167,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1169 | int errcode; | 1167 | int errcode; |
1170 | u8 doff, sfdoff; | 1168 | u8 doff, sfdoff; |
1171 | 1169 | ||
1172 | int ifidx = 0; | ||
1173 | bool usechain = bus->use_rxchain; | 1170 | bool usechain = bus->use_rxchain; |
1174 | 1171 | ||
1175 | struct brcmf_sdio_read rd_new; | 1172 | struct brcmf_sdio_read rd_new; |
@@ -1388,13 +1385,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1388 | skb_unlink(pfirst, &bus->glom); | 1385 | skb_unlink(pfirst, &bus->glom); |
1389 | brcmu_pkt_buf_free_skb(pfirst); | 1386 | brcmu_pkt_buf_free_skb(pfirst); |
1390 | continue; | 1387 | continue; |
1391 | } else if (brcmf_proto_hdrpull(bus->sdiodev->dev, | ||
1392 | &ifidx, pfirst) != 0) { | ||
1393 | brcmf_err("rx protocol error\n"); | ||
1394 | bus->sdiodev->bus_if->dstats.rx_errors++; | ||
1395 | skb_unlink(pfirst, &bus->glom); | ||
1396 | brcmu_pkt_buf_free_skb(pfirst); | ||
1397 | continue; | ||
1398 | } | 1388 | } |
1399 | 1389 | ||
1400 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), | 1390 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), |
@@ -1407,7 +1397,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1407 | } | 1397 | } |
1408 | /* sent any remaining packets up */ | 1398 | /* sent any remaining packets up */ |
1409 | if (bus->glom.qlen) | 1399 | if (bus->glom.qlen) |
1410 | brcmf_rx_frame(bus->sdiodev->dev, ifidx, &bus->glom); | 1400 | brcmf_rx_frames(bus->sdiodev->dev, &bus->glom); |
1411 | 1401 | ||
1412 | bus->sdcnt.rxglomframes++; | 1402 | bus->sdcnt.rxglomframes++; |
1413 | bus->sdcnt.rxglompkts += bus->glom.qlen; | 1403 | bus->sdcnt.rxglompkts += bus->glom.qlen; |
@@ -1558,10 +1548,10 @@ static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen) | |||
1558 | static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | 1548 | static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) |
1559 | { | 1549 | { |
1560 | struct sk_buff *pkt; /* Packet for event or data frames */ | 1550 | struct sk_buff *pkt; /* Packet for event or data frames */ |
1551 | struct sk_buff_head pktlist; /* needed for bus interface */ | ||
1561 | u16 pad; /* Number of pad bytes to read */ | 1552 | u16 pad; /* Number of pad bytes to read */ |
1562 | uint rxleft = 0; /* Remaining number of frames allowed */ | 1553 | uint rxleft = 0; /* Remaining number of frames allowed */ |
1563 | int sdret; /* Return code from calls */ | 1554 | int sdret; /* Return code from calls */ |
1564 | int ifidx = 0; | ||
1565 | uint rxcount = 0; /* Total frames read */ | 1555 | uint rxcount = 0; /* Total frames read */ |
1566 | struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; | 1556 | struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; |
1567 | u8 head_read = 0; | 1557 | u8 head_read = 0; |
@@ -1760,15 +1750,11 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1760 | if (pkt->len == 0) { | 1750 | if (pkt->len == 0) { |
1761 | brcmu_pkt_buf_free_skb(pkt); | 1751 | brcmu_pkt_buf_free_skb(pkt); |
1762 | continue; | 1752 | continue; |
1763 | } else if (brcmf_proto_hdrpull(bus->sdiodev->dev, &ifidx, | ||
1764 | pkt) != 0) { | ||
1765 | brcmf_err("rx protocol error\n"); | ||
1766 | brcmu_pkt_buf_free_skb(pkt); | ||
1767 | bus->sdiodev->bus_if->dstats.rx_errors++; | ||
1768 | continue; | ||
1769 | } | 1753 | } |
1770 | 1754 | ||
1771 | brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt); | 1755 | skb_queue_head_init(&pktlist); |
1756 | skb_queue_tail(&pktlist, pkt); | ||
1757 | brcmf_rx_frames(bus->sdiodev->dev, &pktlist); | ||
1772 | } | 1758 | } |
1773 | 1759 | ||
1774 | rxcount = maxframes - rxleft; | 1760 | rxcount = maxframes - rxleft; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index b1bb46c49799..14be2d5530ce 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c | |||
@@ -15,8 +15,6 @@ | |||
15 | */ | 15 | */ |
16 | /* ***** SDIO interface chip backplane handle functions ***** */ | 16 | /* ***** SDIO interface chip backplane handle functions ***** */ |
17 | 17 | ||
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
19 | |||
20 | #include <linux/types.h> | 18 | #include <linux/types.h> |
21 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
22 | #include <linux/mmc/card.h> | 20 | #include <linux/mmc/card.h> |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 914c56fe6c5f..e15630cc3889 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -443,14 +443,15 @@ static void brcmf_usb_rx_complete(struct urb *urb) | |||
443 | struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context; | 443 | struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context; |
444 | struct brcmf_usbdev_info *devinfo = req->devinfo; | 444 | struct brcmf_usbdev_info *devinfo = req->devinfo; |
445 | struct sk_buff *skb; | 445 | struct sk_buff *skb; |
446 | int ifidx = 0; | 446 | struct sk_buff_head skbq; |
447 | 447 | ||
448 | brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status); | 448 | brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status); |
449 | brcmf_usb_del_fromq(devinfo, req); | 449 | brcmf_usb_del_fromq(devinfo, req); |
450 | skb = req->skb; | 450 | skb = req->skb; |
451 | req->skb = NULL; | 451 | req->skb = NULL; |
452 | 452 | ||
453 | if (urb->status == 0) { | 453 | /* zero lenght packets indicate usb "failure". Do not refill */ |
454 | if (urb->status == 0 && urb->actual_length) { | ||
454 | devinfo->bus_pub.bus->dstats.rx_packets++; | 455 | devinfo->bus_pub.bus->dstats.rx_packets++; |
455 | } else { | 456 | } else { |
456 | devinfo->bus_pub.bus->dstats.rx_errors++; | 457 | devinfo->bus_pub.bus->dstats.rx_errors++; |
@@ -460,13 +461,10 @@ static void brcmf_usb_rx_complete(struct urb *urb) | |||
460 | } | 461 | } |
461 | 462 | ||
462 | if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) { | 463 | if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) { |
464 | skb_queue_head_init(&skbq); | ||
465 | skb_queue_tail(&skbq, skb); | ||
463 | skb_put(skb, urb->actual_length); | 466 | skb_put(skb, urb->actual_length); |
464 | if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) { | 467 | brcmf_rx_frames(devinfo->dev, &skbq); |
465 | brcmf_err("rx protocol error\n"); | ||
466 | brcmu_pkt_buf_free_skb(skb); | ||
467 | devinfo->bus_pub.bus->dstats.rx_errors++; | ||
468 | } else | ||
469 | brcmf_rx_packet(devinfo->dev, ifidx, skb); | ||
470 | brcmf_usb_rx_refill(devinfo, req); | 468 | brcmf_usb_rx_refill(devinfo, req); |
471 | } else { | 469 | } else { |
472 | brcmu_pkt_buf_free_skb(skb); | 470 | brcmu_pkt_buf_free_skb(skb); |
@@ -1520,10 +1518,23 @@ static void brcmf_release_fw(struct list_head *q) | |||
1520 | } | 1518 | } |
1521 | } | 1519 | } |
1522 | 1520 | ||
1521 | static int brcmf_usb_reset_device(struct device *dev, void *notused) | ||
1522 | { | ||
1523 | /* device past is the usb interface so we | ||
1524 | * need to use parent here. | ||
1525 | */ | ||
1526 | brcmf_dev_reset(dev->parent); | ||
1527 | return 0; | ||
1528 | } | ||
1523 | 1529 | ||
1524 | void brcmf_usb_exit(void) | 1530 | void brcmf_usb_exit(void) |
1525 | { | 1531 | { |
1532 | struct device_driver *drv = &brcmf_usbdrvr.drvwrap.driver; | ||
1533 | int ret; | ||
1534 | |||
1526 | brcmf_dbg(USB, "Enter\n"); | 1535 | brcmf_dbg(USB, "Enter\n"); |
1536 | ret = driver_for_each_device(drv, NULL, NULL, | ||
1537 | brcmf_usb_reset_device); | ||
1527 | usb_deregister(&brcmf_usbdrvr); | 1538 | usb_deregister(&brcmf_usbdrvr); |
1528 | brcmf_release_fw(&fw_image_list); | 1539 | brcmf_release_fw(&fw_image_list); |
1529 | } | 1540 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 75464ad4fbd1..62a528e8b958 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -16,8 +16,6 @@ | |||
16 | 16 | ||
17 | /* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */ | 17 | /* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */ |
18 | 18 | ||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
20 | |||
21 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
22 | #include <linux/etherdevice.h> | 20 | #include <linux/etherdevice.h> |
23 | #include <net/cfg80211.h> | 21 | #include <net/cfg80211.h> |
@@ -2011,67 +2009,6 @@ done: | |||
2011 | return err; | 2009 | return err; |
2012 | } | 2010 | } |
2013 | 2011 | ||
2014 | static s32 | ||
2015 | brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, | ||
2016 | const u8 *addr, | ||
2017 | const struct cfg80211_bitrate_mask *mask) | ||
2018 | { | ||
2019 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
2020 | struct brcm_rateset_le rateset_le; | ||
2021 | s32 rate; | ||
2022 | s32 val; | ||
2023 | s32 err_bg; | ||
2024 | s32 err_a; | ||
2025 | u32 legacy; | ||
2026 | s32 err = 0; | ||
2027 | |||
2028 | brcmf_dbg(TRACE, "Enter\n"); | ||
2029 | if (!check_vif_up(ifp->vif)) | ||
2030 | return -EIO; | ||
2031 | |||
2032 | /* addr param is always NULL. ignore it */ | ||
2033 | /* Get current rateset */ | ||
2034 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CURR_RATESET, | ||
2035 | &rateset_le, sizeof(rateset_le)); | ||
2036 | if (err) { | ||
2037 | brcmf_err("could not get current rateset (%d)\n", err); | ||
2038 | goto done; | ||
2039 | } | ||
2040 | |||
2041 | legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF); | ||
2042 | if (!legacy) | ||
2043 | legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy & | ||
2044 | 0xFFFF); | ||
2045 | |||
2046 | val = wl_g_rates[legacy - 1].bitrate * 100000; | ||
2047 | |||
2048 | if (val < le32_to_cpu(rateset_le.count)) | ||
2049 | /* Select rate by rateset index */ | ||
2050 | rate = rateset_le.rates[val] & 0x7f; | ||
2051 | else | ||
2052 | /* Specified rate in bps */ | ||
2053 | rate = val / 500000; | ||
2054 | |||
2055 | brcmf_dbg(CONN, "rate %d mbps\n", rate / 2); | ||
2056 | |||
2057 | /* | ||
2058 | * | ||
2059 | * Set rate override, | ||
2060 | * Since the is a/b/g-blind, both a/bg_rate are enforced. | ||
2061 | */ | ||
2062 | err_bg = brcmf_fil_iovar_int_set(ifp, "bg_rate", rate); | ||
2063 | err_a = brcmf_fil_iovar_int_set(ifp, "a_rate", rate); | ||
2064 | if (err_bg && err_a) { | ||
2065 | brcmf_err("could not set fixed rate (%d) (%d)\n", err_bg, | ||
2066 | err_a); | ||
2067 | err = err_bg | err_a; | ||
2068 | } | ||
2069 | |||
2070 | done: | ||
2071 | brcmf_dbg(TRACE, "Exit\n"); | ||
2072 | return err; | ||
2073 | } | ||
2074 | |||
2075 | static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, | 2012 | static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, |
2076 | struct brcmf_bss_info_le *bi) | 2013 | struct brcmf_bss_info_le *bi) |
2077 | { | 2014 | { |
@@ -3704,7 +3641,6 @@ static struct cfg80211_ops wl_cfg80211_ops = { | |||
3704 | .set_default_key = brcmf_cfg80211_config_default_key, | 3641 | .set_default_key = brcmf_cfg80211_config_default_key, |
3705 | .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key, | 3642 | .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key, |
3706 | .set_power_mgmt = brcmf_cfg80211_set_power_mgmt, | 3643 | .set_power_mgmt = brcmf_cfg80211_set_power_mgmt, |
3707 | .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask, | ||
3708 | .connect = brcmf_cfg80211_connect, | 3644 | .connect = brcmf_cfg80211_connect, |
3709 | .disconnect = brcmf_cfg80211_disconnect, | 3645 | .disconnect = brcmf_cfg80211_disconnect, |
3710 | .suspend = brcmf_cfg80211_suspend, | 3646 | .suspend = brcmf_cfg80211_suspend, |
@@ -4330,9 +4266,8 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | |||
4330 | } | 4266 | } |
4331 | 4267 | ||
4332 | static s32 | 4268 | static s32 |
4333 | brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) | 4269 | brcmf_dongle_roam(struct brcmf_if *ifp, u32 roamvar, u32 bcn_timeout) |
4334 | { | 4270 | { |
4335 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
4336 | s32 err = 0; | 4271 | s32 err = 0; |
4337 | __le32 roamtrigger[2]; | 4272 | __le32 roamtrigger[2]; |
4338 | __le32 roam_delta[2]; | 4273 | __le32 roam_delta[2]; |
@@ -4383,10 +4318,9 @@ dongle_rom_out: | |||
4383 | } | 4318 | } |
4384 | 4319 | ||
4385 | static s32 | 4320 | static s32 |
4386 | brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, | 4321 | brcmf_dongle_scantime(struct brcmf_if *ifp, s32 scan_assoc_time, |
4387 | s32 scan_unassoc_time, s32 scan_passive_time) | 4322 | s32 scan_unassoc_time, s32 scan_passive_time) |
4388 | { | 4323 | { |
4389 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
4390 | s32 err = 0; | 4324 | s32 err = 0; |
4391 | 4325 | ||
4392 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, | 4326 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, |
@@ -4456,6 +4390,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | |||
4456 | { | 4390 | { |
4457 | struct net_device *ndev; | 4391 | struct net_device *ndev; |
4458 | struct wireless_dev *wdev; | 4392 | struct wireless_dev *wdev; |
4393 | struct brcmf_if *ifp; | ||
4459 | s32 power_mode; | 4394 | s32 power_mode; |
4460 | s32 err = 0; | 4395 | s32 err = 0; |
4461 | 4396 | ||
@@ -4464,35 +4399,34 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | |||
4464 | 4399 | ||
4465 | ndev = cfg_to_ndev(cfg); | 4400 | ndev = cfg_to_ndev(cfg); |
4466 | wdev = ndev->ieee80211_ptr; | 4401 | wdev = ndev->ieee80211_ptr; |
4402 | ifp = netdev_priv(ndev); | ||
4467 | 4403 | ||
4468 | brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME, | 4404 | /* make sure RF is ready for work */ |
4469 | WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME); | 4405 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0); |
4406 | |||
4407 | brcmf_dongle_scantime(ifp, WL_SCAN_CHANNEL_TIME, | ||
4408 | WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME); | ||
4470 | 4409 | ||
4471 | power_mode = cfg->pwr_save ? PM_FAST : PM_OFF; | 4410 | power_mode = cfg->pwr_save ? PM_FAST : PM_OFF; |
4472 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PM, | 4411 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, power_mode); |
4473 | power_mode); | ||
4474 | if (err) | 4412 | if (err) |
4475 | goto default_conf_out; | 4413 | goto default_conf_out; |
4476 | brcmf_dbg(INFO, "power save set to %s\n", | 4414 | brcmf_dbg(INFO, "power save set to %s\n", |
4477 | (power_mode ? "enabled" : "disabled")); | 4415 | (power_mode ? "enabled" : "disabled")); |
4478 | 4416 | ||
4479 | err = brcmf_dongle_roam(ndev, (cfg->roam_on ? 0 : 1), | 4417 | err = brcmf_dongle_roam(ifp, (cfg->roam_on ? 0 : 1), WL_BEACON_TIMEOUT); |
4480 | WL_BEACON_TIMEOUT); | ||
4481 | if (err) | 4418 | if (err) |
4482 | goto default_conf_out; | 4419 | goto default_conf_out; |
4483 | err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, | 4420 | err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, |
4484 | NULL, NULL); | 4421 | NULL, NULL); |
4485 | if (err && err != -EINPROGRESS) | 4422 | if (err) |
4486 | goto default_conf_out; | 4423 | goto default_conf_out; |
4487 | err = brcmf_dongle_probecap(cfg); | 4424 | err = brcmf_dongle_probecap(cfg); |
4488 | if (err) | 4425 | if (err) |
4489 | goto default_conf_out; | 4426 | goto default_conf_out; |
4490 | 4427 | ||
4491 | /* -EINPROGRESS: Call commit handler */ | ||
4492 | |||
4493 | default_conf_out: | ||
4494 | |||
4495 | cfg->dongle_up = true; | 4428 | cfg->dongle_up = true; |
4429 | default_conf_out: | ||
4496 | 4430 | ||
4497 | return err; | 4431 | return err; |
4498 | 4432 | ||
@@ -4501,8 +4435,6 @@ default_conf_out: | |||
4501 | static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp) | 4435 | static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp) |
4502 | { | 4436 | { |
4503 | set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state); | 4437 | set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state); |
4504 | if (ifp->idx) | ||
4505 | return 0; | ||
4506 | 4438 | ||
4507 | return brcmf_config_dongle(ifp->drvr->config); | 4439 | return brcmf_config_dongle(ifp->drvr->config); |
4508 | } | 4440 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c index 1de94f30564f..1585cc5bf866 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | |||
@@ -961,7 +961,6 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, | |||
961 | /* if acked then clear bit and free packet */ | 961 | /* if acked then clear bit and free packet */ |
962 | if ((bindex < AMPDU_TX_BA_MAX_WSIZE) | 962 | if ((bindex < AMPDU_TX_BA_MAX_WSIZE) |
963 | && isset(bitmap, bindex)) { | 963 | && isset(bitmap, bindex)) { |
964 | ini->tx_in_transit--; | ||
965 | ini->txretry[index] = 0; | 964 | ini->txretry[index] = 0; |
966 | 965 | ||
967 | /* | 966 | /* |
@@ -990,7 +989,6 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, | |||
990 | if (retry && (ini->txretry[index] < (int)retry_limit)) { | 989 | if (retry && (ini->txretry[index] < (int)retry_limit)) { |
991 | int ret; | 990 | int ret; |
992 | ini->txretry[index]++; | 991 | ini->txretry[index]++; |
993 | ini->tx_in_transit--; | ||
994 | ret = brcms_c_txfifo(wlc, queue, p); | 992 | ret = brcms_c_txfifo(wlc, queue, p); |
995 | /* | 993 | /* |
996 | * We shouldn't be out of space in the DMA | 994 | * We shouldn't be out of space in the DMA |
@@ -1000,7 +998,6 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, | |||
1000 | WARN_ONCE(ret, "queue %d out of txds\n", queue); | 998 | WARN_ONCE(ret, "queue %d out of txds\n", queue); |
1001 | } else { | 999 | } else { |
1002 | /* Retry timeout */ | 1000 | /* Retry timeout */ |
1003 | ini->tx_in_transit--; | ||
1004 | ieee80211_tx_info_clear_status(tx_info); | 1001 | ieee80211_tx_info_clear_status(tx_info); |
1005 | tx_info->status.ampdu_ack_len = 0; | 1002 | tx_info->status.ampdu_ack_len = 0; |
1006 | tx_info->status.ampdu_len = 1; | 1003 | tx_info->status.ampdu_len = 1; |
@@ -1009,8 +1006,8 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, | |||
1009 | skb_pull(p, D11_PHY_HDR_LEN); | 1006 | skb_pull(p, D11_PHY_HDR_LEN); |
1010 | skb_pull(p, D11_TXH_LEN); | 1007 | skb_pull(p, D11_TXH_LEN); |
1011 | brcms_dbg_ht(wlc->hw->d11core, | 1008 | brcms_dbg_ht(wlc->hw->d11core, |
1012 | "BA Timeout, seq %d, in_transit %d\n", | 1009 | "BA Timeout, seq %d\n", |
1013 | seq, ini->tx_in_transit); | 1010 | seq); |
1014 | ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, | 1011 | ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, |
1015 | p); | 1012 | p); |
1016 | } | 1013 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index a90b72202ec5..cdb62b8ccc79 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c | |||
@@ -670,7 +670,7 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
670 | struct ieee80211_supported_band *sband; | 670 | struct ieee80211_supported_band *sband; |
671 | struct ieee80211_channel *ch; | 671 | struct ieee80211_channel *ch; |
672 | const struct ieee80211_reg_rule *rule; | 672 | const struct ieee80211_reg_rule *rule; |
673 | int band, i, ret; | 673 | int band, i; |
674 | 674 | ||
675 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 675 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
676 | sband = wiphy->bands[band]; | 676 | sband = wiphy->bands[band]; |
@@ -685,9 +685,8 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
685 | continue; | 685 | continue; |
686 | 686 | ||
687 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { | 687 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
688 | ret = freq_reg_info(wiphy, ch->center_freq, | 688 | rule = freq_reg_info(wiphy, ch->center_freq); |
689 | 0, &rule); | 689 | if (IS_ERR(rule)) |
690 | if (ret) | ||
691 | continue; | 690 | continue; |
692 | 691 | ||
693 | if (!(rule->flags & NL80211_RRF_NO_IBSS)) | 692 | if (!(rule->flags & NL80211_RRF_NO_IBSS)) |
@@ -703,8 +702,8 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
703 | } | 702 | } |
704 | } | 703 | } |
705 | 704 | ||
706 | static int brcms_reg_notifier(struct wiphy *wiphy, | 705 | static void brcms_reg_notifier(struct wiphy *wiphy, |
707 | struct regulatory_request *request) | 706 | struct regulatory_request *request) |
708 | { | 707 | { |
709 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 708 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
710 | struct brcms_info *wl = hw->priv; | 709 | struct brcms_info *wl = hw->priv; |
@@ -745,8 +744,6 @@ static int brcms_reg_notifier(struct wiphy *wiphy, | |||
745 | if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G) | 744 | if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G) |
746 | wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi, | 745 | wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi, |
747 | brcms_c_japan_ccode(request->alpha2)); | 746 | brcms_c_japan_ccode(request->alpha2)); |
748 | |||
749 | return 0; | ||
750 | } | 747 | } |
751 | 748 | ||
752 | void brcms_c_regd_init(struct brcms_c_info *wlc) | 749 | void brcms_c_regd_init(struct brcms_c_info *wlc) |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 1fbd8ecbe2ea..7fc49ca3f597 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -362,8 +362,11 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
362 | return -EOPNOTSUPP; | 362 | return -EOPNOTSUPP; |
363 | } | 363 | } |
364 | 364 | ||
365 | spin_lock_bh(&wl->lock); | ||
366 | memcpy(wl->pub->cur_etheraddr, vif->addr, sizeof(vif->addr)); | ||
365 | wl->mute_tx = false; | 367 | wl->mute_tx = false; |
366 | brcms_c_mute(wl->wlc, false); | 368 | brcms_c_mute(wl->wlc, false); |
369 | spin_unlock_bh(&wl->lock); | ||
367 | 370 | ||
368 | return 0; | 371 | return 0; |
369 | } | 372 | } |
@@ -668,7 +671,9 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, | |||
668 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 671 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
669 | break; | 672 | break; |
670 | 673 | ||
671 | case IEEE80211_AMPDU_TX_STOP: | 674 | case IEEE80211_AMPDU_TX_STOP_CONT: |
675 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
676 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
672 | spin_lock_bh(&wl->lock); | 677 | spin_lock_bh(&wl->lock); |
673 | brcms_c_ampdu_flush(wl->wlc, sta, tid); | 678 | brcms_c_ampdu_flush(wl->wlc, sta, tid); |
674 | spin_unlock_bh(&wl->lock); | 679 | spin_unlock_bh(&wl->lock); |
@@ -1407,9 +1412,10 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) | |||
1407 | #endif | 1412 | #endif |
1408 | t->ms = ms; | 1413 | t->ms = ms; |
1409 | t->periodic = (bool) periodic; | 1414 | t->periodic = (bool) periodic; |
1410 | t->set = true; | 1415 | if (!t->set) { |
1411 | 1416 | t->set = true; | |
1412 | atomic_inc(&t->wl->callbacks); | 1417 | atomic_inc(&t->wl->callbacks); |
1418 | } | ||
1413 | 1419 | ||
1414 | ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); | 1420 | ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); |
1415 | } | 1421 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 17594de4199e..c26992a60e6c 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -2473,6 +2473,7 @@ static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw, | |||
2473 | static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool mute_tx) | 2473 | static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool mute_tx) |
2474 | { | 2474 | { |
2475 | static const u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; | 2475 | static const u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; |
2476 | u8 *ethaddr = wlc_hw->wlc->pub->cur_etheraddr; | ||
2476 | 2477 | ||
2477 | if (mute_tx) { | 2478 | if (mute_tx) { |
2478 | /* suspend tx fifos */ | 2479 | /* suspend tx fifos */ |
@@ -2482,8 +2483,7 @@ static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool mute_tx) | |||
2482 | brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO); | 2483 | brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO); |
2483 | 2484 | ||
2484 | /* zero the address match register so we do not send ACKs */ | 2485 | /* zero the address match register so we do not send ACKs */ |
2485 | brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, | 2486 | brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, null_ether_addr); |
2486 | null_ether_addr); | ||
2487 | } else { | 2487 | } else { |
2488 | /* resume tx fifos */ | 2488 | /* resume tx fifos */ |
2489 | brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO); | 2489 | brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO); |
@@ -2492,8 +2492,7 @@ static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool mute_tx) | |||
2492 | brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO); | 2492 | brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO); |
2493 | 2493 | ||
2494 | /* Restore address */ | 2494 | /* Restore address */ |
2495 | brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, | 2495 | brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, ethaddr); |
2496 | wlc_hw->etheraddr); | ||
2497 | } | 2496 | } |
2498 | 2497 | ||
2499 | wlc_phy_mute_upd(wlc_hw->band->pi, mute_tx, 0); | 2498 | wlc_phy_mute_upd(wlc_hw->band->pi, mute_tx, 0); |
@@ -7633,7 +7632,7 @@ brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound) | |||
7633 | 7632 | ||
7634 | uint n = 0; | 7633 | uint n = 0; |
7635 | uint bound_limit = bound ? RXBND : -1; | 7634 | uint bound_limit = bound ? RXBND : -1; |
7636 | bool morepending; | 7635 | bool morepending = false; |
7637 | 7636 | ||
7638 | skb_queue_head_init(&recv_frames); | 7637 | skb_queue_head_init(&recv_frames); |
7639 | 7638 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/scb.h b/drivers/net/wireless/brcm80211/brcmsmac/scb.h index 51c79c7239b7..3a3d73699f83 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/scb.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/scb.h | |||
@@ -36,7 +36,6 @@ | |||
36 | 36 | ||
37 | /* structure to store per-tid state for the ampdu initiator */ | 37 | /* structure to store per-tid state for the ampdu initiator */ |
38 | struct scb_ampdu_tid_ini { | 38 | struct scb_ampdu_tid_ini { |
39 | u8 tx_in_transit; /* number of pending mpdus in transit in driver */ | ||
40 | u8 tid; /* initiator tid for easy lookup */ | 39 | u8 tid; /* initiator tid for easy lookup */ |
41 | /* tx retry count; indexed by seq modulo */ | 40 | /* tx retry count; indexed by seq modulo */ |
42 | u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; | 41 | u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; |
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 3726cd6fcd75..050ce7c70d74 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c | |||
@@ -3474,6 +3474,7 @@ struct ieee80211_ops il3945_mac_ops = { | |||
3474 | .sta_add = il3945_mac_sta_add, | 3474 | .sta_add = il3945_mac_sta_add, |
3475 | .sta_remove = il_mac_sta_remove, | 3475 | .sta_remove = il_mac_sta_remove, |
3476 | .tx_last_beacon = il_mac_tx_last_beacon, | 3476 | .tx_last_beacon = il_mac_tx_last_beacon, |
3477 | .flush = il_mac_flush, | ||
3477 | }; | 3478 | }; |
3478 | 3479 | ||
3479 | static int | 3480 | static int |
@@ -3548,7 +3549,8 @@ il3945_setup_mac(struct il_priv *il) | |||
3548 | hw->vif_data_size = sizeof(struct il_vif_priv); | 3549 | hw->vif_data_size = sizeof(struct il_vif_priv); |
3549 | 3550 | ||
3550 | /* Tell mac80211 our characteristics */ | 3551 | /* Tell mac80211 our characteristics */ |
3551 | hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SPECTRUM_MGMT; | 3552 | hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SPECTRUM_MGMT | |
3553 | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | ||
3552 | 3554 | ||
3553 | hw->wiphy->interface_modes = | 3555 | hw->wiphy->interface_modes = |
3554 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); | 3556 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); |
@@ -3557,6 +3559,8 @@ il3945_setup_mac(struct il_priv *il) | |||
3557 | WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | | 3559 | WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | |
3558 | WIPHY_FLAG_IBSS_RSN; | 3560 | WIPHY_FLAG_IBSS_RSN; |
3559 | 3561 | ||
3562 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
3563 | |||
3560 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; | 3564 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; |
3561 | /* we create the 802.11 header and a zero-length SSID element */ | 3565 | /* we create the 802.11 header and a zero-length SSID element */ |
3562 | hw->wiphy->max_scan_ie_len = IL3945_MAX_PROBE_REQUEST - 24 - 2; | 3566 | hw->wiphy->max_scan_ie_len = IL3945_MAX_PROBE_REQUEST - 24 - 2; |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index c3fbf6717564..f1dc04006564 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
@@ -5712,8 +5712,8 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) | |||
5712 | hw->flags = | 5712 | hw->flags = |
5713 | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | | 5713 | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | |
5714 | IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT | | 5714 | IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT | |
5715 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; | 5715 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | |
5716 | 5716 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | |
5717 | if (il->cfg->sku & IL_SKU_N) | 5717 | if (il->cfg->sku & IL_SKU_N) |
5718 | hw->flags |= | 5718 | hw->flags |= |
5719 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 5719 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
@@ -5968,7 +5968,9 @@ il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5968 | D_HT("start Tx\n"); | 5968 | D_HT("start Tx\n"); |
5969 | ret = il4965_tx_agg_start(il, vif, sta, tid, ssn); | 5969 | ret = il4965_tx_agg_start(il, vif, sta, tid, ssn); |
5970 | break; | 5970 | break; |
5971 | case IEEE80211_AMPDU_TX_STOP: | 5971 | case IEEE80211_AMPDU_TX_STOP_CONT: |
5972 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
5973 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
5972 | D_HT("stop Tx\n"); | 5974 | D_HT("stop Tx\n"); |
5973 | ret = il4965_tx_agg_stop(il, vif, sta, tid); | 5975 | ret = il4965_tx_agg_stop(il, vif, sta, tid); |
5974 | if (test_bit(S_EXIT_PENDING, &il->status)) | 5976 | if (test_bit(S_EXIT_PENDING, &il->status)) |
@@ -6306,6 +6308,7 @@ const struct ieee80211_ops il4965_mac_ops = { | |||
6306 | .sta_remove = il_mac_sta_remove, | 6308 | .sta_remove = il_mac_sta_remove, |
6307 | .channel_switch = il4965_mac_channel_switch, | 6309 | .channel_switch = il4965_mac_channel_switch, |
6308 | .tx_last_beacon = il_mac_tx_last_beacon, | 6310 | .tx_last_beacon = il_mac_tx_last_beacon, |
6311 | .flush = il_mac_flush, | ||
6309 | }; | 6312 | }; |
6310 | 6313 | ||
6311 | static int | 6314 | static int |
@@ -6553,6 +6556,7 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
6553 | il4965_prepare_card_hw(il); | 6556 | il4965_prepare_card_hw(il); |
6554 | if (!il->hw_ready) { | 6557 | if (!il->hw_ready) { |
6555 | IL_WARN("Failed, HW not ready\n"); | 6558 | IL_WARN("Failed, HW not ready\n"); |
6559 | err = -EIO; | ||
6556 | goto out_iounmap; | 6560 | goto out_iounmap; |
6557 | } | 6561 | } |
6558 | 6562 | ||
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 7e16d10a7f14..1f598604a79c 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
@@ -3958,17 +3958,21 @@ il_connection_init_rx_config(struct il_priv *il) | |||
3958 | 3958 | ||
3959 | memset(&il->staging, 0, sizeof(il->staging)); | 3959 | memset(&il->staging, 0, sizeof(il->staging)); |
3960 | 3960 | ||
3961 | if (!il->vif) { | 3961 | switch (il->iw_mode) { |
3962 | case NL80211_IFTYPE_UNSPECIFIED: | ||
3962 | il->staging.dev_type = RXON_DEV_TYPE_ESS; | 3963 | il->staging.dev_type = RXON_DEV_TYPE_ESS; |
3963 | } else if (il->vif->type == NL80211_IFTYPE_STATION) { | 3964 | break; |
3965 | case NL80211_IFTYPE_STATION: | ||
3964 | il->staging.dev_type = RXON_DEV_TYPE_ESS; | 3966 | il->staging.dev_type = RXON_DEV_TYPE_ESS; |
3965 | il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; | 3967 | il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; |
3966 | } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { | 3968 | break; |
3969 | case NL80211_IFTYPE_ADHOC: | ||
3967 | il->staging.dev_type = RXON_DEV_TYPE_IBSS; | 3970 | il->staging.dev_type = RXON_DEV_TYPE_IBSS; |
3968 | il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; | 3971 | il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; |
3969 | il->staging.filter_flags = | 3972 | il->staging.filter_flags = |
3970 | RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; | 3973 | RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; |
3971 | } else { | 3974 | break; |
3975 | default: | ||
3972 | IL_ERR("Unsupported interface type %d\n", il->vif->type); | 3976 | IL_ERR("Unsupported interface type %d\n", il->vif->type); |
3973 | return; | 3977 | return; |
3974 | } | 3978 | } |
@@ -4550,8 +4554,7 @@ out: | |||
4550 | EXPORT_SYMBOL(il_mac_add_interface); | 4554 | EXPORT_SYMBOL(il_mac_add_interface); |
4551 | 4555 | ||
4552 | static void | 4556 | static void |
4553 | il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, | 4557 | il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) |
4554 | bool mode_change) | ||
4555 | { | 4558 | { |
4556 | lockdep_assert_held(&il->mutex); | 4559 | lockdep_assert_held(&il->mutex); |
4557 | 4560 | ||
@@ -4560,9 +4563,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, | |||
4560 | il_force_scan_end(il); | 4563 | il_force_scan_end(il); |
4561 | } | 4564 | } |
4562 | 4565 | ||
4563 | if (!mode_change) | 4566 | il_set_mode(il); |
4564 | il_set_mode(il); | ||
4565 | |||
4566 | } | 4567 | } |
4567 | 4568 | ||
4568 | void | 4569 | void |
@@ -4575,8 +4576,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
4575 | 4576 | ||
4576 | WARN_ON(il->vif != vif); | 4577 | WARN_ON(il->vif != vif); |
4577 | il->vif = NULL; | 4578 | il->vif = NULL; |
4578 | 4579 | il->iw_mode = NL80211_IFTYPE_UNSPECIFIED; | |
4579 | il_teardown_interface(il, vif, false); | 4580 | il_teardown_interface(il, vif); |
4580 | memset(il->bssid, 0, ETH_ALEN); | 4581 | memset(il->bssid, 0, ETH_ALEN); |
4581 | 4582 | ||
4582 | D_MAC80211("leave\n"); | 4583 | D_MAC80211("leave\n"); |
@@ -4685,18 +4686,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
4685 | } | 4686 | } |
4686 | 4687 | ||
4687 | /* success */ | 4688 | /* success */ |
4688 | il_teardown_interface(il, vif, true); | ||
4689 | vif->type = newtype; | 4689 | vif->type = newtype; |
4690 | vif->p2p = false; | 4690 | vif->p2p = false; |
4691 | err = il_set_mode(il); | 4691 | il->iw_mode = newtype; |
4692 | WARN_ON(err); | 4692 | il_teardown_interface(il, vif); |
4693 | /* | ||
4694 | * We've switched internally, but submitting to the | ||
4695 | * device may have failed for some reason. Mask this | ||
4696 | * error, because otherwise mac80211 will not switch | ||
4697 | * (and set the interface type back) and we'll be | ||
4698 | * out of sync with it. | ||
4699 | */ | ||
4700 | err = 0; | 4693 | err = 0; |
4701 | 4694 | ||
4702 | out: | 4695 | out: |
@@ -4707,6 +4700,42 @@ out: | |||
4707 | } | 4700 | } |
4708 | EXPORT_SYMBOL(il_mac_change_interface); | 4701 | EXPORT_SYMBOL(il_mac_change_interface); |
4709 | 4702 | ||
4703 | void | ||
4704 | il_mac_flush(struct ieee80211_hw *hw, bool drop) | ||
4705 | { | ||
4706 | struct il_priv *il = hw->priv; | ||
4707 | unsigned long timeout = jiffies + msecs_to_jiffies(500); | ||
4708 | int i; | ||
4709 | |||
4710 | mutex_lock(&il->mutex); | ||
4711 | D_MAC80211("enter\n"); | ||
4712 | |||
4713 | if (il->txq == NULL) | ||
4714 | goto out; | ||
4715 | |||
4716 | for (i = 0; i < il->hw_params.max_txq_num; i++) { | ||
4717 | struct il_queue *q; | ||
4718 | |||
4719 | if (i == il->cmd_queue) | ||
4720 | continue; | ||
4721 | |||
4722 | q = &il->txq[i].q; | ||
4723 | if (q->read_ptr == q->write_ptr) | ||
4724 | continue; | ||
4725 | |||
4726 | if (time_after(jiffies, timeout)) { | ||
4727 | IL_ERR("Failed to flush queue %d\n", q->id); | ||
4728 | break; | ||
4729 | } | ||
4730 | |||
4731 | msleep(20); | ||
4732 | } | ||
4733 | out: | ||
4734 | D_MAC80211("leave\n"); | ||
4735 | mutex_unlock(&il->mutex); | ||
4736 | } | ||
4737 | EXPORT_SYMBOL(il_mac_flush); | ||
4738 | |||
4710 | /* | 4739 | /* |
4711 | * On every watchdog tick we check (latest) time stamp. If it does not | 4740 | * On every watchdog tick we check (latest) time stamp. If it does not |
4712 | * change during timeout period and queue is not empty we reset firmware. | 4741 | * change during timeout period and queue is not empty we reset firmware. |
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index a9a569f432fb..37fe553b25e0 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h | |||
@@ -1723,6 +1723,7 @@ void il_mac_remove_interface(struct ieee80211_hw *hw, | |||
1723 | struct ieee80211_vif *vif); | 1723 | struct ieee80211_vif *vif); |
1724 | int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1724 | int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1725 | enum nl80211_iftype newtype, bool newp2p); | 1725 | enum nl80211_iftype newtype, bool newp2p); |
1726 | void il_mac_flush(struct ieee80211_hw *hw, bool drop); | ||
1726 | int il_alloc_txq_mem(struct il_priv *il); | 1727 | int il_alloc_txq_mem(struct il_priv *il); |
1727 | void il_free_txq_mem(struct il_priv *il); | 1728 | void il_free_txq_mem(struct il_priv *il); |
1728 | 1729 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index 71ab76b2b39d..0ca99c13f7f2 100644 --- a/drivers/net/wireless/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h | |||
@@ -3695,7 +3695,7 @@ struct iwl_bt_uart_msg { | |||
3695 | u8 frame5; | 3695 | u8 frame5; |
3696 | u8 frame6; | 3696 | u8 frame6; |
3697 | u8 frame7; | 3697 | u8 frame7; |
3698 | } __attribute__((packed)); | 3698 | } __packed; |
3699 | 3699 | ||
3700 | struct iwl_bt_coex_profile_notif { | 3700 | struct iwl_bt_coex_profile_notif { |
3701 | struct iwl_bt_uart_msg last_bt_uart_msg; | 3701 | struct iwl_bt_uart_msg last_bt_uart_msg; |
@@ -3703,7 +3703,7 @@ struct iwl_bt_coex_profile_notif { | |||
3703 | u8 bt_traffic_load; /* 0 .. 3? */ | 3703 | u8 bt_traffic_load; /* 0 .. 3? */ |
3704 | u8 bt_ci_compliance; /* 0 - not complied, 1 - complied */ | 3704 | u8 bt_ci_compliance; /* 0 - not complied, 1 - complied */ |
3705 | u8 reserved; | 3705 | u8 reserved; |
3706 | } __attribute__((packed)); | 3706 | } __packed; |
3707 | 3707 | ||
3708 | #define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS 0 | 3708 | #define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS 0 |
3709 | #define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_MSK 0x1 | 3709 | #define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_MSK 0x1 |
@@ -3752,7 +3752,7 @@ enum bt_coex_prio_table_priorities { | |||
3752 | 3752 | ||
3753 | struct iwl_bt_coex_prio_table_cmd { | 3753 | struct iwl_bt_coex_prio_table_cmd { |
3754 | u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX]; | 3754 | u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX]; |
3755 | } __attribute__((packed)); | 3755 | } __packed; |
3756 | 3756 | ||
3757 | #define IWL_BT_COEX_ENV_CLOSE 0 | 3757 | #define IWL_BT_COEX_ENV_CLOSE 0 |
3758 | #define IWL_BT_COEX_ENV_OPEN 1 | 3758 | #define IWL_BT_COEX_ENV_OPEN 1 |
@@ -3764,7 +3764,7 @@ struct iwl_bt_coex_prot_env_cmd { | |||
3764 | u8 action; /* 0 = closed, 1 = open */ | 3764 | u8 action; /* 0 = closed, 1 = open */ |
3765 | u8 type; /* 0 .. 15 */ | 3765 | u8 type; /* 0 .. 15 */ |
3766 | u8 reserved[2]; | 3766 | u8 reserved[2]; |
3767 | } __attribute__((packed)); | 3767 | } __packed; |
3768 | 3768 | ||
3769 | /* | 3769 | /* |
3770 | * REPLY_D3_CONFIG | 3770 | * REPLY_D3_CONFIG |
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index 5b9533eef54d..72c74af38138 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c | |||
@@ -157,7 +157,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
157 | sram = priv->dbgfs_sram_offset & ~0x3; | 157 | sram = priv->dbgfs_sram_offset & ~0x3; |
158 | 158 | ||
159 | /* read the first u32 from sram */ | 159 | /* read the first u32 from sram */ |
160 | val = iwl_read_targ_mem(priv->trans, sram); | 160 | val = iwl_trans_read_mem32(priv->trans, sram); |
161 | 161 | ||
162 | for (; len; len--) { | 162 | for (; len; len--) { |
163 | /* put the address at the start of every line */ | 163 | /* put the address at the start of every line */ |
@@ -176,7 +176,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
176 | if (++offset == 4) { | 176 | if (++offset == 4) { |
177 | sram += 4; | 177 | sram += 4; |
178 | offset = 0; | 178 | offset = 0; |
179 | val = iwl_read_targ_mem(priv->trans, sram); | 179 | val = iwl_trans_read_mem32(priv->trans, sram); |
180 | } | 180 | } |
181 | 181 | ||
182 | /* put in extra spaces and split lines for human readability */ | 182 | /* put in extra spaces and split lines for human readability */ |
diff --git a/drivers/net/wireless/iwlwifi/dvm/led.c b/drivers/net/wireless/iwlwifi/dvm/led.c index bf479f709091..844a17f99a18 100644 --- a/drivers/net/wireless/iwlwifi/dvm/led.c +++ b/drivers/net/wireless/iwlwifi/dvm/led.c | |||
@@ -69,7 +69,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = { | |||
69 | /* Set led register off */ | 69 | /* Set led register off */ |
70 | void iwlagn_led_enable(struct iwl_priv *priv) | 70 | void iwlagn_led_enable(struct iwl_priv *priv) |
71 | { | 71 | { |
72 | iwl_write32(priv->trans, CSR_LED_REG, CSR_LED_REG_TRUN_ON); | 72 | iwl_write32(priv->trans, CSR_LED_REG, CSR_LED_REG_TURN_ON); |
73 | } | 73 | } |
74 | 74 | ||
75 | /* | 75 | /* |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 3163e0f38c25..0353e1c0670d 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -206,7 +206,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
206 | 206 | ||
207 | #ifdef CONFIG_PM_SLEEP | 207 | #ifdef CONFIG_PM_SLEEP |
208 | if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && | 208 | if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && |
209 | priv->trans->ops->wowlan_suspend && | 209 | priv->trans->ops->d3_suspend && |
210 | priv->trans->ops->d3_resume && | ||
210 | device_can_wakeup(priv->trans->dev)) { | 211 | device_can_wakeup(priv->trans->dev)) { |
211 | hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | | 212 | hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | |
212 | WIPHY_WOWLAN_DISCONNECT | | 213 | WIPHY_WOWLAN_DISCONNECT | |
@@ -426,7 +427,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, | |||
426 | if (ret) | 427 | if (ret) |
427 | goto error; | 428 | goto error; |
428 | 429 | ||
429 | iwl_trans_wowlan_suspend(priv->trans); | 430 | iwl_trans_d3_suspend(priv->trans); |
430 | 431 | ||
431 | goto out; | 432 | goto out; |
432 | 433 | ||
@@ -459,11 +460,11 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
459 | base = priv->device_pointers.error_event_table; | 460 | base = priv->device_pointers.error_event_table; |
460 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | 461 | if (iwlagn_hw_valid_rtc_data_addr(base)) { |
461 | spin_lock_irqsave(&priv->trans->reg_lock, flags); | 462 | spin_lock_irqsave(&priv->trans->reg_lock, flags); |
462 | ret = iwl_grab_nic_access_silent(priv->trans); | 463 | if (iwl_trans_grab_nic_access(priv->trans, true)) { |
463 | if (likely(ret == 0)) { | ||
464 | iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, base); | 464 | iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, base); |
465 | status = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT); | 465 | status = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT); |
466 | iwl_release_nic_access(priv->trans); | 466 | iwl_trans_release_nic_access(priv->trans); |
467 | ret = 0; | ||
467 | } | 468 | } |
468 | spin_unlock_irqrestore(&priv->trans->reg_lock, flags); | 469 | spin_unlock_irqrestore(&priv->trans->reg_lock, flags); |
469 | 470 | ||
@@ -479,7 +480,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
479 | } | 480 | } |
480 | 481 | ||
481 | if (priv->wowlan_sram) | 482 | if (priv->wowlan_sram) |
482 | _iwl_read_targ_mem_dwords( | 483 | iwl_trans_read_mem( |
483 | priv->trans, 0x800000, | 484 | priv->trans, 0x800000, |
484 | priv->wowlan_sram, | 485 | priv->wowlan_sram, |
485 | img->sec[IWL_UCODE_SECTION_DATA].len / 4); | 486 | img->sec[IWL_UCODE_SECTION_DATA].len / 4); |
@@ -520,9 +521,6 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw, | |||
520 | { | 521 | { |
521 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 522 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
522 | 523 | ||
523 | IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, | ||
524 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); | ||
525 | |||
526 | if (iwlagn_tx_skb(priv, control->sta, skb)) | 524 | if (iwlagn_tx_skb(priv, control->sta, skb)) |
527 | ieee80211_free_txskb(hw, skb); | 525 | ieee80211_free_txskb(hw, skb); |
528 | } | 526 | } |
@@ -679,7 +677,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
679 | IWL_DEBUG_HT(priv, "start Tx\n"); | 677 | IWL_DEBUG_HT(priv, "start Tx\n"); |
680 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); | 678 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); |
681 | break; | 679 | break; |
682 | case IEEE80211_AMPDU_TX_STOP: | 680 | case IEEE80211_AMPDU_TX_STOP_CONT: |
681 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
682 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
683 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 683 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
684 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); | 684 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); |
685 | if ((ret == 0) && (priv->agg_tids_count > 0)) { | 685 | if ((ret == 0) && (priv->agg_tids_count > 0)) { |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index faa05932efae..a64f361e341c 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -354,7 +354,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, | |||
354 | 354 | ||
355 | /* Make sure device is powered up for SRAM reads */ | 355 | /* Make sure device is powered up for SRAM reads */ |
356 | spin_lock_irqsave(&priv->trans->reg_lock, reg_flags); | 356 | spin_lock_irqsave(&priv->trans->reg_lock, reg_flags); |
357 | if (unlikely(!iwl_grab_nic_access(priv->trans))) { | 357 | if (!iwl_trans_grab_nic_access(priv->trans, false)) { |
358 | spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags); | 358 | spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags); |
359 | return; | 359 | return; |
360 | } | 360 | } |
@@ -388,7 +388,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, | |||
388 | } | 388 | } |
389 | } | 389 | } |
390 | /* Allow device to power down */ | 390 | /* Allow device to power down */ |
391 | iwl_release_nic_access(priv->trans); | 391 | iwl_trans_release_nic_access(priv->trans); |
392 | spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags); | 392 | spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags); |
393 | } | 393 | } |
394 | 394 | ||
@@ -408,7 +408,8 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) | |||
408 | 408 | ||
409 | base = priv->device_pointers.log_event_table; | 409 | base = priv->device_pointers.log_event_table; |
410 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | 410 | if (iwlagn_hw_valid_rtc_data_addr(base)) { |
411 | iwl_read_targ_mem_bytes(priv->trans, base, &read, sizeof(read)); | 411 | iwl_trans_read_mem_bytes(priv->trans, base, |
412 | &read, sizeof(read)); | ||
412 | capacity = read.capacity; | 413 | capacity = read.capacity; |
413 | mode = read.mode; | 414 | mode = read.mode; |
414 | num_wraps = read.wrap_counter; | 415 | num_wraps = read.wrap_counter; |
@@ -1627,7 +1628,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1627 | } | 1628 | } |
1628 | 1629 | ||
1629 | /*TODO: Update dbgfs with ISR error stats obtained below */ | 1630 | /*TODO: Update dbgfs with ISR error stats obtained below */ |
1630 | iwl_read_targ_mem_bytes(trans, base, &table, sizeof(table)); | 1631 | iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); |
1631 | 1632 | ||
1632 | if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { | 1633 | if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { |
1633 | IWL_ERR(trans, "Start IWL Error Log Dump:\n"); | 1634 | IWL_ERR(trans, "Start IWL Error Log Dump:\n"); |
@@ -1717,7 +1718,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1717 | 1718 | ||
1718 | /* Make sure device is powered up for SRAM reads */ | 1719 | /* Make sure device is powered up for SRAM reads */ |
1719 | spin_lock_irqsave(&trans->reg_lock, reg_flags); | 1720 | spin_lock_irqsave(&trans->reg_lock, reg_flags); |
1720 | if (unlikely(!iwl_grab_nic_access(trans))) | 1721 | if (!iwl_trans_grab_nic_access(trans, false)) |
1721 | goto out_unlock; | 1722 | goto out_unlock; |
1722 | 1723 | ||
1723 | /* Set starting address; reads will auto-increment */ | 1724 | /* Set starting address; reads will auto-increment */ |
@@ -1756,7 +1757,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1756 | } | 1757 | } |
1757 | 1758 | ||
1758 | /* Allow device to power down */ | 1759 | /* Allow device to power down */ |
1759 | iwl_release_nic_access(trans); | 1760 | iwl_trans_release_nic_access(trans); |
1760 | out_unlock: | 1761 | out_unlock: |
1761 | spin_unlock_irqrestore(&trans->reg_lock, reg_flags); | 1762 | spin_unlock_irqrestore(&trans->reg_lock, reg_flags); |
1762 | return pos; | 1763 | return pos; |
@@ -1835,10 +1836,10 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
1835 | } | 1836 | } |
1836 | 1837 | ||
1837 | /* event log header */ | 1838 | /* event log header */ |
1838 | capacity = iwl_read_targ_mem(trans, base); | 1839 | capacity = iwl_trans_read_mem32(trans, base); |
1839 | mode = iwl_read_targ_mem(trans, base + (1 * sizeof(u32))); | 1840 | mode = iwl_trans_read_mem32(trans, base + (1 * sizeof(u32))); |
1840 | num_wraps = iwl_read_targ_mem(trans, base + (2 * sizeof(u32))); | 1841 | num_wraps = iwl_trans_read_mem32(trans, base + (2 * sizeof(u32))); |
1841 | next_entry = iwl_read_targ_mem(trans, base + (3 * sizeof(u32))); | 1842 | next_entry = iwl_trans_read_mem32(trans, base + (3 * sizeof(u32))); |
1842 | 1843 | ||
1843 | if (capacity > logsize) { | 1844 | if (capacity > logsize) { |
1844 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d " | 1845 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d " |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tt.c b/drivers/net/wireless/iwlwifi/dvm/tt.c index eb864433e59d..b28cfc8553d7 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/iwlwifi/dvm/tt.c | |||
@@ -186,8 +186,8 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) | |||
186 | } | 186 | } |
187 | iwl_read32(priv->trans, CSR_UCODE_DRV_GP1); | 187 | iwl_read32(priv->trans, CSR_UCODE_DRV_GP1); |
188 | spin_lock_irqsave(&priv->trans->reg_lock, flags); | 188 | spin_lock_irqsave(&priv->trans->reg_lock, flags); |
189 | if (likely(iwl_grab_nic_access(priv->trans))) | 189 | if (iwl_trans_grab_nic_access(priv->trans, false)) |
190 | iwl_release_nic_access(priv->trans); | 190 | iwl_trans_release_nic_access(priv->trans); |
191 | spin_unlock_irqrestore(&priv->trans->reg_lock, flags); | 191 | spin_unlock_irqrestore(&priv->trans->reg_lock, flags); |
192 | 192 | ||
193 | /* Reschedule the ct_kill timer to occur in | 193 | /* Reschedule the ct_kill timer to occur in |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index a790599fe2c2..6b01fc195940 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -231,13 +231,11 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | |||
231 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); | 231 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); |
232 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 232 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
233 | tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; | 233 | tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; |
234 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | ||
235 | break; | 234 | break; |
236 | 235 | ||
237 | case WLAN_CIPHER_SUITE_TKIP: | 236 | case WLAN_CIPHER_SUITE_TKIP: |
238 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; | 237 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; |
239 | ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key); | 238 | ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key); |
240 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); | ||
241 | break; | 239 | break; |
242 | 240 | ||
243 | case WLAN_CIPHER_SUITE_WEP104: | 241 | case WLAN_CIPHER_SUITE_WEP104: |
@@ -355,8 +353,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, | |||
355 | } | 353 | } |
356 | } | 354 | } |
357 | 355 | ||
358 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); | ||
359 | |||
360 | if (sta) | 356 | if (sta) |
361 | sta_priv = (void *)sta->drv_priv; | 357 | sta_priv = (void *)sta->drv_priv; |
362 | 358 | ||
@@ -472,6 +468,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, | |||
472 | WARN_ON_ONCE(is_agg && | 468 | WARN_ON_ONCE(is_agg && |
473 | priv->queue_to_mac80211[txq_id] != info->hw_queue); | 469 | priv->queue_to_mac80211[txq_id] != info->hw_queue); |
474 | 470 | ||
471 | IWL_DEBUG_TX(priv, "TX to [%d|%d] Q:%d - seq: 0x%x\n", sta_id, tid, | ||
472 | txq_id, seq_number); | ||
473 | |||
475 | if (iwl_trans_tx(priv->trans, skb, dev_cmd, txq_id)) | 474 | if (iwl_trans_tx(priv->trans, skb, dev_cmd, txq_id)) |
476 | goto drop_unlock_sta; | 475 | goto drop_unlock_sta; |
477 | 476 | ||
@@ -541,9 +540,9 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
541 | spin_lock_bh(&priv->sta_lock); | 540 | spin_lock_bh(&priv->sta_lock); |
542 | 541 | ||
543 | tid_data = &priv->tid_data[sta_id][tid]; | 542 | tid_data = &priv->tid_data[sta_id][tid]; |
544 | txq_id = priv->tid_data[sta_id][tid].agg.txq_id; | 543 | txq_id = tid_data->agg.txq_id; |
545 | 544 | ||
546 | switch (priv->tid_data[sta_id][tid].agg.state) { | 545 | switch (tid_data->agg.state) { |
547 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | 546 | case IWL_EMPTYING_HW_QUEUE_ADDBA: |
548 | /* | 547 | /* |
549 | * This can happen if the peer stops aggregation | 548 | * This can happen if the peer stops aggregation |
@@ -563,9 +562,9 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
563 | case IWL_AGG_ON: | 562 | case IWL_AGG_ON: |
564 | break; | 563 | break; |
565 | default: | 564 | default: |
566 | IWL_WARN(priv, "Stopping AGG while state not ON " | 565 | IWL_WARN(priv, |
567 | "or starting for %d on %d (%d)\n", sta_id, tid, | 566 | "Stopping AGG while state not ON or starting for %d on %d (%d)\n", |
568 | priv->tid_data[sta_id][tid].agg.state); | 567 | sta_id, tid, tid_data->agg.state); |
569 | spin_unlock_bh(&priv->sta_lock); | 568 | spin_unlock_bh(&priv->sta_lock); |
570 | return 0; | 569 | return 0; |
571 | } | 570 | } |
@@ -578,12 +577,11 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
578 | "stopping AGG on STA/TID %d/%d but hwq %d not used\n", | 577 | "stopping AGG on STA/TID %d/%d but hwq %d not used\n", |
579 | sta_id, tid, txq_id); | 578 | sta_id, tid, txq_id); |
580 | } else if (tid_data->agg.ssn != tid_data->next_reclaimed) { | 579 | } else if (tid_data->agg.ssn != tid_data->next_reclaimed) { |
581 | IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, " | 580 | IWL_DEBUG_TX_QUEUES(priv, |
582 | "next_recl = %d\n", | 581 | "Can't proceed: ssn %d, next_recl = %d\n", |
583 | tid_data->agg.ssn, | 582 | tid_data->agg.ssn, |
584 | tid_data->next_reclaimed); | 583 | tid_data->next_reclaimed); |
585 | priv->tid_data[sta_id][tid].agg.state = | 584 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_DELBA; |
586 | IWL_EMPTYING_HW_QUEUE_DELBA; | ||
587 | spin_unlock_bh(&priv->sta_lock); | 585 | spin_unlock_bh(&priv->sta_lock); |
588 | return 0; | 586 | return 0; |
589 | } | 587 | } |
@@ -591,8 +589,8 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
591 | IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n", | 589 | IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n", |
592 | tid_data->agg.ssn); | 590 | tid_data->agg.ssn); |
593 | turn_off: | 591 | turn_off: |
594 | agg_state = priv->tid_data[sta_id][tid].agg.state; | 592 | agg_state = tid_data->agg.state; |
595 | priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; | 593 | tid_data->agg.state = IWL_AGG_OFF; |
596 | 594 | ||
597 | spin_unlock_bh(&priv->sta_lock); | 595 | spin_unlock_bh(&priv->sta_lock); |
598 | 596 | ||
@@ -954,12 +952,6 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, | |||
954 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | 952 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | |
955 | AGG_TX_STATE_ABORT_MSK)) | 953 | AGG_TX_STATE_ABORT_MSK)) |
956 | continue; | 954 | continue; |
957 | |||
958 | IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), " | ||
959 | "try-count (0x%08x)\n", | ||
960 | iwl_get_agg_tx_fail_reason(fstatus), | ||
961 | fstatus & AGG_TX_STATUS_MSK, | ||
962 | fstatus & AGG_TX_TRY_MSK); | ||
963 | } | 955 | } |
964 | } | 956 | } |
965 | 957 | ||
@@ -1079,6 +1071,8 @@ static void iwlagn_set_tx_status(struct iwl_priv *priv, | |||
1079 | { | 1071 | { |
1080 | u16 status = le16_to_cpu(tx_resp->status.status); | 1072 | u16 status = le16_to_cpu(tx_resp->status.status); |
1081 | 1073 | ||
1074 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
1075 | |||
1082 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1076 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1083 | info->flags |= iwl_tx_status_to_mac80211(status); | 1077 | info->flags |= iwl_tx_status_to_mac80211(status); |
1084 | iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), | 1078 | iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), |
@@ -1223,16 +1217,27 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1223 | next_reclaimed); | 1217 | next_reclaimed); |
1224 | } | 1218 | } |
1225 | 1219 | ||
1226 | WARN_ON(!is_agg && freed != 1); | 1220 | if (!is_agg && freed != 1) |
1221 | IWL_ERR(priv, "Q: %d, freed %d\n", txq_id, freed); | ||
1227 | 1222 | ||
1228 | /* | 1223 | /* |
1229 | * An offchannel frame can be send only on the AUX queue, where | 1224 | * An offchannel frame can be send only on the AUX queue, where |
1230 | * there is no aggregation (and reordering) so it only is single | 1225 | * there is no aggregation (and reordering) so it only is single |
1231 | * skb is expected to be processed. | 1226 | * skb is expected to be processed. |
1232 | */ | 1227 | */ |
1233 | WARN_ON(is_offchannel_skb && freed != 1); | 1228 | if (is_offchannel_skb && freed != 1) |
1229 | IWL_ERR(priv, "OFFCHANNEL SKB freed %d\n", freed); | ||
1234 | } | 1230 | } |
1235 | 1231 | ||
1232 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x)\n", txq_id, | ||
1233 | iwl_get_tx_fail_reason(status), status); | ||
1234 | |||
1235 | IWL_DEBUG_TX_REPLY(priv, | ||
1236 | "\t\t\t\tinitial_rate 0x%x retries %d, idx=%d ssn=%d seq_ctl=0x%x\n", | ||
1237 | le32_to_cpu(tx_resp->rate_n_flags), | ||
1238 | tx_resp->failure_frame, SEQ_TO_INDEX(sequence), ssn, | ||
1239 | le16_to_cpu(tx_resp->seq_ctl)); | ||
1240 | |||
1236 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | 1241 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
1237 | spin_unlock(&priv->sta_lock); | 1242 | spin_unlock(&priv->sta_lock); |
1238 | 1243 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index c6467e5554f5..ebec13a3329f 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
@@ -286,89 +286,6 @@ static int iwl_alive_notify(struct iwl_priv *priv) | |||
286 | return iwl_send_calib_results(priv); | 286 | return iwl_send_calib_results(priv); |
287 | } | 287 | } |
288 | 288 | ||
289 | |||
290 | /** | ||
291 | * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host, | ||
292 | * using sample data 100 bytes apart. If these sample points are good, | ||
293 | * it's a pretty good bet that everything between them is good, too. | ||
294 | */ | ||
295 | static int iwl_verify_sec_sparse(struct iwl_priv *priv, | ||
296 | const struct fw_desc *fw_desc) | ||
297 | { | ||
298 | __le32 *image = (__le32 *)fw_desc->data; | ||
299 | u32 len = fw_desc->len; | ||
300 | u32 val; | ||
301 | u32 i; | ||
302 | |||
303 | IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len); | ||
304 | |||
305 | for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { | ||
306 | /* read data comes through single port, auto-incr addr */ | ||
307 | /* NOTE: Use the debugless read so we don't flood kernel log | ||
308 | * if IWL_DL_IO is set */ | ||
309 | iwl_write_direct32(priv->trans, HBUS_TARG_MEM_RADDR, | ||
310 | i + fw_desc->offset); | ||
311 | val = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT); | ||
312 | if (val != le32_to_cpu(*image)) | ||
313 | return -EIO; | ||
314 | } | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static void iwl_print_mismatch_sec(struct iwl_priv *priv, | ||
320 | const struct fw_desc *fw_desc) | ||
321 | { | ||
322 | __le32 *image = (__le32 *)fw_desc->data; | ||
323 | u32 len = fw_desc->len; | ||
324 | u32 val; | ||
325 | u32 offs; | ||
326 | int errors = 0; | ||
327 | |||
328 | IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len); | ||
329 | |||
330 | iwl_write_direct32(priv->trans, HBUS_TARG_MEM_RADDR, | ||
331 | fw_desc->offset); | ||
332 | |||
333 | for (offs = 0; | ||
334 | offs < len && errors < 20; | ||
335 | offs += sizeof(u32), image++) { | ||
336 | /* read data comes through single port, auto-incr addr */ | ||
337 | val = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT); | ||
338 | if (val != le32_to_cpu(*image)) { | ||
339 | IWL_ERR(priv, "uCode INST section at " | ||
340 | "offset 0x%x, is 0x%x, s/b 0x%x\n", | ||
341 | offs, val, le32_to_cpu(*image)); | ||
342 | errors++; | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | |||
347 | /** | ||
348 | * iwl_verify_ucode - determine which instruction image is in SRAM, | ||
349 | * and verify its contents | ||
350 | */ | ||
351 | static int iwl_verify_ucode(struct iwl_priv *priv, | ||
352 | enum iwl_ucode_type ucode_type) | ||
353 | { | ||
354 | const struct fw_img *img = iwl_get_ucode_image(priv, ucode_type); | ||
355 | |||
356 | if (!img) { | ||
357 | IWL_ERR(priv, "Invalid ucode requested (%d)\n", ucode_type); | ||
358 | return -EINVAL; | ||
359 | } | ||
360 | |||
361 | if (!iwl_verify_sec_sparse(priv, &img->sec[IWL_UCODE_SECTION_INST])) { | ||
362 | IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n"); | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); | ||
367 | |||
368 | iwl_print_mismatch_sec(priv, &img->sec[IWL_UCODE_SECTION_INST]); | ||
369 | return -EIO; | ||
370 | } | ||
371 | |||
372 | struct iwl_alive_data { | 289 | struct iwl_alive_data { |
373 | bool valid; | 290 | bool valid; |
374 | u8 subtype; | 291 | u8 subtype; |
@@ -426,7 +343,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
426 | alive_cmd, ARRAY_SIZE(alive_cmd), | 343 | alive_cmd, ARRAY_SIZE(alive_cmd), |
427 | iwl_alive_fn, &alive_data); | 344 | iwl_alive_fn, &alive_data); |
428 | 345 | ||
429 | ret = iwl_trans_start_fw(priv->trans, fw); | 346 | ret = iwl_trans_start_fw(priv->trans, fw, false); |
430 | if (ret) { | 347 | if (ret) { |
431 | priv->cur_ucode = old_type; | 348 | priv->cur_ucode = old_type; |
432 | iwl_remove_notification(&priv->notif_wait, &alive_wait); | 349 | iwl_remove_notification(&priv->notif_wait, &alive_wait); |
@@ -450,18 +367,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
450 | return -EIO; | 367 | return -EIO; |
451 | } | 368 | } |
452 | 369 | ||
453 | /* | ||
454 | * This step takes a long time (60-80ms!!) and | ||
455 | * WoWLAN image should be loaded quickly, so | ||
456 | * skip it for WoWLAN. | ||
457 | */ | ||
458 | if (ucode_type != IWL_UCODE_WOWLAN) { | 370 | if (ucode_type != IWL_UCODE_WOWLAN) { |
459 | ret = iwl_verify_ucode(priv, ucode_type); | ||
460 | if (ret) { | ||
461 | priv->cur_ucode = old_type; | ||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | /* delay a bit to give rfkill time to run */ | 371 | /* delay a bit to give rfkill time to run */ |
466 | msleep(5); | 372 | msleep(5); |
467 | } | 373 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 34a5287dfc2f..b419a1efac0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -381,8 +381,8 @@ | |||
381 | 381 | ||
382 | /* LED */ | 382 | /* LED */ |
383 | #define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF) | 383 | #define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF) |
384 | #define CSR_LED_REG_TRUN_ON (0x78) | 384 | #define CSR_LED_REG_TURN_ON (0x60) |
385 | #define CSR_LED_REG_TRUN_OFF (0x38) | 385 | #define CSR_LED_REG_TURN_OFF (0x20) |
386 | 386 | ||
387 | /* ANA_PLL */ | 387 | /* ANA_PLL */ |
388 | #define CSR50_ANA_PLL_CFG_VAL (0x00880300) | 388 | #define CSR50_ANA_PLL_CFG_VAL (0x00880300) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index ec48563d3c6a..c646a90b725e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h | |||
@@ -225,6 +225,8 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) | |||
225 | #define FH_RSCSR_CHNL0_RBDCB_WPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x008) | 225 | #define FH_RSCSR_CHNL0_RBDCB_WPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x008) |
226 | #define FH_RSCSR_CHNL0_WPTR (FH_RSCSR_CHNL0_RBDCB_WPTR_REG) | 226 | #define FH_RSCSR_CHNL0_WPTR (FH_RSCSR_CHNL0_RBDCB_WPTR_REG) |
227 | 227 | ||
228 | #define FW_RSCSR_CHNL0_RXDCB_RDPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x00c) | ||
229 | #define FH_RSCSR_CHNL0_RDPTR FW_RSCSR_CHNL0_RXDCB_RDPTR_REG | ||
228 | 230 | ||
229 | /** | 231 | /** |
230 | * Rx Config/Status Registers (RCSR) | 232 | * Rx Config/Status Registers (RCSR) |
@@ -257,6 +259,8 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) | |||
257 | #define FH_MEM_RCSR_CHNL0 (FH_MEM_RCSR_LOWER_BOUND) | 259 | #define FH_MEM_RCSR_CHNL0 (FH_MEM_RCSR_LOWER_BOUND) |
258 | 260 | ||
259 | #define FH_MEM_RCSR_CHNL0_CONFIG_REG (FH_MEM_RCSR_CHNL0) | 261 | #define FH_MEM_RCSR_CHNL0_CONFIG_REG (FH_MEM_RCSR_CHNL0) |
262 | #define FH_MEM_RCSR_CHNL0_RBDCB_WPTR (FH_MEM_RCSR_CHNL0 + 0x8) | ||
263 | #define FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ (FH_MEM_RCSR_CHNL0 + 0x10) | ||
260 | 264 | ||
261 | #define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MSK (0x00000FF0) /* bits 4-11 */ | 265 | #define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MSK (0x00000FF0) /* bits 4-11 */ |
262 | #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MSK (0x00001000) /* bits 12 */ | 266 | #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MSK (0x00001000) /* bits 12 */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index cdaff9572059..bff3ac96c00b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -35,12 +35,12 @@ | |||
35 | 35 | ||
36 | #define IWL_POLL_INTERVAL 10 /* microseconds */ | 36 | #define IWL_POLL_INTERVAL 10 /* microseconds */ |
37 | 37 | ||
38 | static inline void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) | 38 | void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) |
39 | { | 39 | { |
40 | iwl_write32(trans, reg, iwl_read32(trans, reg) | mask); | 40 | iwl_write32(trans, reg, iwl_read32(trans, reg) | mask); |
41 | } | 41 | } |
42 | 42 | ||
43 | static inline void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) | 43 | void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) |
44 | { | 44 | { |
45 | iwl_write32(trans, reg, iwl_read32(trans, reg) & ~mask); | 45 | iwl_write32(trans, reg, iwl_read32(trans, reg) & ~mask); |
46 | } | 46 | } |
@@ -99,86 +99,16 @@ int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | |||
99 | } | 99 | } |
100 | EXPORT_SYMBOL_GPL(iwl_poll_bit); | 100 | EXPORT_SYMBOL_GPL(iwl_poll_bit); |
101 | 101 | ||
102 | int iwl_grab_nic_access_silent(struct iwl_trans *trans) | ||
103 | { | ||
104 | int ret; | ||
105 | |||
106 | lockdep_assert_held(&trans->reg_lock); | ||
107 | |||
108 | /* this bit wakes up the NIC */ | ||
109 | __iwl_set_bit(trans, CSR_GP_CNTRL, | ||
110 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
111 | |||
112 | /* | ||
113 | * These bits say the device is running, and should keep running for | ||
114 | * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), | ||
115 | * but they do not indicate that embedded SRAM is restored yet; | ||
116 | * 3945 and 4965 have volatile SRAM, and must save/restore contents | ||
117 | * to/from host DRAM when sleeping/waking for power-saving. | ||
118 | * Each direction takes approximately 1/4 millisecond; with this | ||
119 | * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a | ||
120 | * series of register accesses are expected (e.g. reading Event Log), | ||
121 | * to keep device from sleeping. | ||
122 | * | ||
123 | * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that | ||
124 | * SRAM is okay/restored. We don't check that here because this call | ||
125 | * is just for hardware register access; but GP1 MAC_SLEEP check is a | ||
126 | * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). | ||
127 | * | ||
128 | * 5000 series and later (including 1000 series) have non-volatile SRAM, | ||
129 | * and do not save/restore SRAM when power cycling. | ||
130 | */ | ||
131 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
132 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, | ||
133 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | | ||
134 | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); | ||
135 | if (ret < 0) { | ||
136 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); | ||
137 | return -EIO; | ||
138 | } | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | EXPORT_SYMBOL_GPL(iwl_grab_nic_access_silent); | ||
143 | |||
144 | bool iwl_grab_nic_access(struct iwl_trans *trans) | ||
145 | { | ||
146 | int ret = iwl_grab_nic_access_silent(trans); | ||
147 | if (unlikely(ret)) { | ||
148 | u32 val = iwl_read32(trans, CSR_GP_CNTRL); | ||
149 | WARN_ONCE(1, "Timeout waiting for hardware access " | ||
150 | "(CSR_GP_CNTRL 0x%08x)\n", val); | ||
151 | return false; | ||
152 | } | ||
153 | |||
154 | return true; | ||
155 | } | ||
156 | EXPORT_SYMBOL_GPL(iwl_grab_nic_access); | ||
157 | |||
158 | void iwl_release_nic_access(struct iwl_trans *trans) | ||
159 | { | ||
160 | lockdep_assert_held(&trans->reg_lock); | ||
161 | __iwl_clear_bit(trans, CSR_GP_CNTRL, | ||
162 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
163 | /* | ||
164 | * Above we read the CSR_GP_CNTRL register, which will flush | ||
165 | * any previous writes, but we need the write that clears the | ||
166 | * MAC_ACCESS_REQ bit to be performed before any other writes | ||
167 | * scheduled on different CPUs (after we drop reg_lock). | ||
168 | */ | ||
169 | mmiowb(); | ||
170 | } | ||
171 | EXPORT_SYMBOL_GPL(iwl_release_nic_access); | ||
172 | |||
173 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) | 102 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) |
174 | { | 103 | { |
175 | u32 value; | 104 | u32 value = 0x5a5a5a5a; |
176 | unsigned long flags; | 105 | unsigned long flags; |
177 | 106 | ||
178 | spin_lock_irqsave(&trans->reg_lock, flags); | 107 | spin_lock_irqsave(&trans->reg_lock, flags); |
179 | iwl_grab_nic_access(trans); | 108 | if (iwl_trans_grab_nic_access(trans, false)) { |
180 | value = iwl_read32(trans, reg); | 109 | value = iwl_read32(trans, reg); |
181 | iwl_release_nic_access(trans); | 110 | iwl_trans_release_nic_access(trans); |
111 | } | ||
182 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 112 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
183 | 113 | ||
184 | return value; | 114 | return value; |
@@ -190,9 +120,9 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) | |||
190 | unsigned long flags; | 120 | unsigned long flags; |
191 | 121 | ||
192 | spin_lock_irqsave(&trans->reg_lock, flags); | 122 | spin_lock_irqsave(&trans->reg_lock, flags); |
193 | if (likely(iwl_grab_nic_access(trans))) { | 123 | if (iwl_trans_grab_nic_access(trans, false)) { |
194 | iwl_write32(trans, reg, value); | 124 | iwl_write32(trans, reg, value); |
195 | iwl_release_nic_access(trans); | 125 | iwl_trans_release_nic_access(trans); |
196 | } | 126 | } |
197 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 127 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
198 | } | 128 | } |
@@ -230,12 +160,13 @@ static inline void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) | |||
230 | u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) | 160 | u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) |
231 | { | 161 | { |
232 | unsigned long flags; | 162 | unsigned long flags; |
233 | u32 val; | 163 | u32 val = 0x5a5a5a5a; |
234 | 164 | ||
235 | spin_lock_irqsave(&trans->reg_lock, flags); | 165 | spin_lock_irqsave(&trans->reg_lock, flags); |
236 | iwl_grab_nic_access(trans); | 166 | if (iwl_trans_grab_nic_access(trans, false)) { |
237 | val = __iwl_read_prph(trans, ofs); | 167 | val = __iwl_read_prph(trans, ofs); |
238 | iwl_release_nic_access(trans); | 168 | iwl_trans_release_nic_access(trans); |
169 | } | ||
239 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 170 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
240 | return val; | 171 | return val; |
241 | } | 172 | } |
@@ -246,9 +177,9 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) | |||
246 | unsigned long flags; | 177 | unsigned long flags; |
247 | 178 | ||
248 | spin_lock_irqsave(&trans->reg_lock, flags); | 179 | spin_lock_irqsave(&trans->reg_lock, flags); |
249 | if (likely(iwl_grab_nic_access(trans))) { | 180 | if (iwl_trans_grab_nic_access(trans, false)) { |
250 | __iwl_write_prph(trans, ofs, val); | 181 | __iwl_write_prph(trans, ofs, val); |
251 | iwl_release_nic_access(trans); | 182 | iwl_trans_release_nic_access(trans); |
252 | } | 183 | } |
253 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 184 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
254 | } | 185 | } |
@@ -259,10 +190,10 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | |||
259 | unsigned long flags; | 190 | unsigned long flags; |
260 | 191 | ||
261 | spin_lock_irqsave(&trans->reg_lock, flags); | 192 | spin_lock_irqsave(&trans->reg_lock, flags); |
262 | if (likely(iwl_grab_nic_access(trans))) { | 193 | if (iwl_trans_grab_nic_access(trans, false)) { |
263 | __iwl_write_prph(trans, ofs, | 194 | __iwl_write_prph(trans, ofs, |
264 | __iwl_read_prph(trans, ofs) | mask); | 195 | __iwl_read_prph(trans, ofs) | mask); |
265 | iwl_release_nic_access(trans); | 196 | iwl_trans_release_nic_access(trans); |
266 | } | 197 | } |
267 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 198 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
268 | } | 199 | } |
@@ -274,10 +205,10 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, | |||
274 | unsigned long flags; | 205 | unsigned long flags; |
275 | 206 | ||
276 | spin_lock_irqsave(&trans->reg_lock, flags); | 207 | spin_lock_irqsave(&trans->reg_lock, flags); |
277 | if (likely(iwl_grab_nic_access(trans))) { | 208 | if (iwl_trans_grab_nic_access(trans, false)) { |
278 | __iwl_write_prph(trans, ofs, | 209 | __iwl_write_prph(trans, ofs, |
279 | (__iwl_read_prph(trans, ofs) & mask) | bits); | 210 | (__iwl_read_prph(trans, ofs) & mask) | bits); |
280 | iwl_release_nic_access(trans); | 211 | iwl_trans_release_nic_access(trans); |
281 | } | 212 | } |
282 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 213 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
283 | } | 214 | } |
@@ -289,66 +220,11 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | |||
289 | u32 val; | 220 | u32 val; |
290 | 221 | ||
291 | spin_lock_irqsave(&trans->reg_lock, flags); | 222 | spin_lock_irqsave(&trans->reg_lock, flags); |
292 | if (likely(iwl_grab_nic_access(trans))) { | 223 | if (iwl_trans_grab_nic_access(trans, false)) { |
293 | val = __iwl_read_prph(trans, ofs); | 224 | val = __iwl_read_prph(trans, ofs); |
294 | __iwl_write_prph(trans, ofs, (val & ~mask)); | 225 | __iwl_write_prph(trans, ofs, (val & ~mask)); |
295 | iwl_release_nic_access(trans); | 226 | iwl_trans_release_nic_access(trans); |
296 | } | 227 | } |
297 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 228 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
298 | } | 229 | } |
299 | EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); | 230 | EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); |
300 | |||
301 | void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr, | ||
302 | void *buf, int dwords) | ||
303 | { | ||
304 | unsigned long flags; | ||
305 | int offs; | ||
306 | u32 *vals = buf; | ||
307 | |||
308 | spin_lock_irqsave(&trans->reg_lock, flags); | ||
309 | if (likely(iwl_grab_nic_access(trans))) { | ||
310 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); | ||
311 | for (offs = 0; offs < dwords; offs++) | ||
312 | vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); | ||
313 | iwl_release_nic_access(trans); | ||
314 | } | ||
315 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
316 | } | ||
317 | EXPORT_SYMBOL_GPL(_iwl_read_targ_mem_dwords); | ||
318 | |||
319 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr) | ||
320 | { | ||
321 | u32 value; | ||
322 | |||
323 | _iwl_read_targ_mem_dwords(trans, addr, &value, 1); | ||
324 | |||
325 | return value; | ||
326 | } | ||
327 | EXPORT_SYMBOL_GPL(iwl_read_targ_mem); | ||
328 | |||
329 | int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr, | ||
330 | const void *buf, int dwords) | ||
331 | { | ||
332 | unsigned long flags; | ||
333 | int offs, result = 0; | ||
334 | const u32 *vals = buf; | ||
335 | |||
336 | spin_lock_irqsave(&trans->reg_lock, flags); | ||
337 | if (likely(iwl_grab_nic_access(trans))) { | ||
338 | iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); | ||
339 | for (offs = 0; offs < dwords; offs++) | ||
340 | iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]); | ||
341 | iwl_release_nic_access(trans); | ||
342 | } else | ||
343 | result = -EBUSY; | ||
344 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
345 | |||
346 | return result; | ||
347 | } | ||
348 | EXPORT_SYMBOL_GPL(_iwl_write_targ_mem_dwords); | ||
349 | |||
350 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val) | ||
351 | { | ||
352 | return _iwl_write_targ_mem_dwords(trans, addr, &val, 1); | ||
353 | } | ||
354 | EXPORT_SYMBOL_GPL(iwl_write_targ_mem); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 48dc753e3742..dc478068596b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -53,6 +53,8 @@ static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs) | |||
53 | 53 | ||
54 | void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); | 54 | void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); |
55 | void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask); | 55 | void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask); |
56 | void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); | ||
57 | void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask); | ||
56 | 58 | ||
57 | void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value); | 59 | void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value); |
58 | 60 | ||
@@ -61,10 +63,6 @@ int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | |||
61 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | 63 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, |
62 | int timeout); | 64 | int timeout); |
63 | 65 | ||
64 | int iwl_grab_nic_access_silent(struct iwl_trans *trans); | ||
65 | bool iwl_grab_nic_access(struct iwl_trans *trans); | ||
66 | void iwl_release_nic_access(struct iwl_trans *trans); | ||
67 | |||
68 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg); | 66 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg); |
69 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); | 67 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); |
70 | 68 | ||
@@ -76,19 +74,4 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, | |||
76 | u32 bits, u32 mask); | 74 | u32 bits, u32 mask); |
77 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); | 75 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); |
78 | 76 | ||
79 | void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr, | ||
80 | void *buf, int dwords); | ||
81 | |||
82 | #define iwl_read_targ_mem_bytes(trans, addr, buf, bufsize) \ | ||
83 | do { \ | ||
84 | BUILD_BUG_ON((bufsize) % sizeof(u32)); \ | ||
85 | _iwl_read_targ_mem_dwords(trans, addr, buf, \ | ||
86 | (bufsize) / sizeof(u32));\ | ||
87 | } while (0) | ||
88 | |||
89 | int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr, | ||
90 | const void *buf, int dwords); | ||
91 | |||
92 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr); | ||
93 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val); | ||
94 | #endif | 77 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.c b/drivers/net/wireless/iwlwifi/iwl-test.c index 81e8c7126d72..1a226114fe73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-test.c +++ b/drivers/net/wireless/iwlwifi/iwl-test.c | |||
@@ -467,18 +467,20 @@ static int iwl_test_indirect_read(struct iwl_test *tst, u32 addr, u32 size) | |||
467 | if (IWL_ABS_PRPH_START <= addr && | 467 | if (IWL_ABS_PRPH_START <= addr && |
468 | addr < IWL_ABS_PRPH_START + PRPH_END) { | 468 | addr < IWL_ABS_PRPH_START + PRPH_END) { |
469 | spin_lock_irqsave(&trans->reg_lock, flags); | 469 | spin_lock_irqsave(&trans->reg_lock, flags); |
470 | iwl_grab_nic_access(trans); | 470 | if (!iwl_trans_grab_nic_access(trans, false)) { |
471 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
472 | return -EIO; | ||
473 | } | ||
471 | iwl_write32(trans, HBUS_TARG_PRPH_RADDR, | 474 | iwl_write32(trans, HBUS_TARG_PRPH_RADDR, |
472 | addr | (3 << 24)); | 475 | addr | (3 << 24)); |
473 | for (i = 0; i < size; i += 4) | 476 | for (i = 0; i < size; i += 4) |
474 | *(u32 *)(tst->mem.addr + i) = | 477 | *(u32 *)(tst->mem.addr + i) = |
475 | iwl_read32(trans, HBUS_TARG_PRPH_RDAT); | 478 | iwl_read32(trans, HBUS_TARG_PRPH_RDAT); |
476 | iwl_release_nic_access(trans); | 479 | iwl_trans_release_nic_access(trans); |
477 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 480 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
478 | } else { /* target memory (SRAM) */ | 481 | } else { /* target memory (SRAM) */ |
479 | _iwl_read_targ_mem_dwords(trans, addr, | 482 | iwl_trans_read_mem(trans, addr, tst->mem.addr, |
480 | tst->mem.addr, | 483 | tst->mem.size / 4); |
481 | tst->mem.size / 4); | ||
482 | } | 484 | } |
483 | 485 | ||
484 | tst->mem.nchunks = | 486 | tst->mem.nchunks = |
@@ -501,28 +503,31 @@ static int iwl_test_indirect_write(struct iwl_test *tst, u32 addr, | |||
501 | 503 | ||
502 | if (IWL_ABS_PRPH_START <= addr && | 504 | if (IWL_ABS_PRPH_START <= addr && |
503 | addr < IWL_ABS_PRPH_START + PRPH_END) { | 505 | addr < IWL_ABS_PRPH_START + PRPH_END) { |
504 | /* Periphery writes can be 1-3 bytes long, or DWORDs */ | 506 | /* Periphery writes can be 1-3 bytes long, or DWORDs */ |
505 | if (size < 4) { | 507 | if (size < 4) { |
506 | memcpy(&val, buf, size); | 508 | memcpy(&val, buf, size); |
507 | spin_lock_irqsave(&trans->reg_lock, flags); | 509 | spin_lock_irqsave(&trans->reg_lock, flags); |
508 | iwl_grab_nic_access(trans); | 510 | if (!iwl_trans_grab_nic_access(trans, false)) { |
509 | iwl_write32(trans, HBUS_TARG_PRPH_WADDR, | ||
510 | (addr & 0x0000FFFF) | | ||
511 | ((size - 1) << 24)); | ||
512 | iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); | ||
513 | iwl_release_nic_access(trans); | ||
514 | /* needed after consecutive writes w/o read */ | ||
515 | mmiowb(); | ||
516 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 511 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
517 | } else { | 512 | return -EIO; |
518 | if (size % 4) | ||
519 | return -EINVAL; | ||
520 | for (i = 0; i < size; i += 4) | ||
521 | iwl_write_prph(trans, addr+i, | ||
522 | *(u32 *)(buf+i)); | ||
523 | } | 513 | } |
514 | iwl_write32(trans, HBUS_TARG_PRPH_WADDR, | ||
515 | (addr & 0x0000FFFF) | | ||
516 | ((size - 1) << 24)); | ||
517 | iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); | ||
518 | iwl_trans_release_nic_access(trans); | ||
519 | /* needed after consecutive writes w/o read */ | ||
520 | mmiowb(); | ||
521 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
522 | } else { | ||
523 | if (size % 4) | ||
524 | return -EINVAL; | ||
525 | for (i = 0; i < size; i += 4) | ||
526 | iwl_write_prph(trans, addr+i, | ||
527 | *(u32 *)(buf+i)); | ||
528 | } | ||
524 | } else if (iwl_test_valid_hw_addr(tst, addr)) { | 529 | } else if (iwl_test_valid_hw_addr(tst, addr)) { |
525 | _iwl_write_targ_mem_dwords(trans, addr, buf, size / 4); | 530 | iwl_trans_write_mem(trans, addr, buf, size / 4); |
526 | } else { | 531 | } else { |
527 | return -EINVAL; | 532 | return -EINVAL; |
528 | } | 533 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index b76532e238c1..0f85eb305878 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -308,6 +308,16 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) | |||
308 | #define IWL_FRAME_LIMIT 64 | 308 | #define IWL_FRAME_LIMIT 64 |
309 | 309 | ||
310 | /** | 310 | /** |
311 | * enum iwl_wowlan_status - WoWLAN image/device status | ||
312 | * @IWL_D3_STATUS_ALIVE: firmware is still running after resume | ||
313 | * @IWL_D3_STATUS_RESET: device was reset while suspended | ||
314 | */ | ||
315 | enum iwl_d3_status { | ||
316 | IWL_D3_STATUS_ALIVE, | ||
317 | IWL_D3_STATUS_RESET, | ||
318 | }; | ||
319 | |||
320 | /** | ||
311 | * struct iwl_trans_config - transport configuration | 321 | * struct iwl_trans_config - transport configuration |
312 | * | 322 | * |
313 | * @op_mode: pointer to the upper layer. | 323 | * @op_mode: pointer to the upper layer. |
@@ -321,6 +331,8 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) | |||
321 | * @n_no_reclaim_cmds: # of commands in list | 331 | * @n_no_reclaim_cmds: # of commands in list |
322 | * @rx_buf_size_8k: 8 kB RX buffer size needed for A-MSDUs, | 332 | * @rx_buf_size_8k: 8 kB RX buffer size needed for A-MSDUs, |
323 | * if unset 4k will be the RX buffer size | 333 | * if unset 4k will be the RX buffer size |
334 | * @bc_table_dword: set to true if the BC table expects the byte count to be | ||
335 | * in DWORD (as opposed to bytes) | ||
324 | * @queue_watchdog_timeout: time (in ms) after which queues | 336 | * @queue_watchdog_timeout: time (in ms) after which queues |
325 | * are considered stuck and will trigger device restart | 337 | * are considered stuck and will trigger device restart |
326 | * @command_names: array of command names, must be 256 entries | 338 | * @command_names: array of command names, must be 256 entries |
@@ -335,6 +347,7 @@ struct iwl_trans_config { | |||
335 | int n_no_reclaim_cmds; | 347 | int n_no_reclaim_cmds; |
336 | 348 | ||
337 | bool rx_buf_size_8k; | 349 | bool rx_buf_size_8k; |
350 | bool bc_table_dword; | ||
338 | unsigned int queue_watchdog_timeout; | 351 | unsigned int queue_watchdog_timeout; |
339 | const char **command_names; | 352 | const char **command_names; |
340 | }; | 353 | }; |
@@ -360,9 +373,12 @@ struct iwl_trans; | |||
360 | * May sleep | 373 | * May sleep |
361 | * @stop_device:stops the whole device (embedded CPU put to reset) | 374 | * @stop_device:stops the whole device (embedded CPU put to reset) |
362 | * May sleep | 375 | * May sleep |
363 | * @wowlan_suspend: put the device into the correct mode for WoWLAN during | 376 | * @d3_suspend: put the device into the correct mode for WoWLAN during |
364 | * suspend. This is optional, if not implemented WoWLAN will not be | 377 | * suspend. This is optional, if not implemented WoWLAN will not be |
365 | * supported. This callback may sleep. | 378 | * supported. This callback may sleep. |
379 | * @d3_resume: resume the device after WoWLAN, enabling the opmode to | ||
380 | * talk to the WoWLAN image to get its status. This is optional, if not | ||
381 | * implemented WoWLAN will not be supported. This callback may sleep. | ||
366 | * @send_cmd:send a host command. Must return -ERFKILL if RFkill is asserted. | 382 | * @send_cmd:send a host command. Must return -ERFKILL if RFkill is asserted. |
367 | * If RFkill is asserted in the middle of a SYNC host command, it must | 383 | * If RFkill is asserted in the middle of a SYNC host command, it must |
368 | * return -ERFKILL straight away. | 384 | * return -ERFKILL straight away. |
@@ -387,20 +403,27 @@ struct iwl_trans; | |||
387 | * @read32: read a u32 register at offset ofs from the BAR | 403 | * @read32: read a u32 register at offset ofs from the BAR |
388 | * @read_prph: read a DWORD from a periphery register | 404 | * @read_prph: read a DWORD from a periphery register |
389 | * @write_prph: write a DWORD to a periphery register | 405 | * @write_prph: write a DWORD to a periphery register |
406 | * @read_mem: read device's SRAM in DWORD | ||
407 | * @write_mem: write device's SRAM in DWORD. If %buf is %NULL, then the memory | ||
408 | * will be zeroed. | ||
390 | * @configure: configure parameters required by the transport layer from | 409 | * @configure: configure parameters required by the transport layer from |
391 | * the op_mode. May be called several times before start_fw, can't be | 410 | * the op_mode. May be called several times before start_fw, can't be |
392 | * called after that. | 411 | * called after that. |
393 | * @set_pmi: set the power pmi state | 412 | * @set_pmi: set the power pmi state |
413 | * @grab_nic_access: wake the NIC to be able to access non-HBUS regs | ||
414 | * @release_nic_access: let the NIC go to sleep | ||
394 | */ | 415 | */ |
395 | struct iwl_trans_ops { | 416 | struct iwl_trans_ops { |
396 | 417 | ||
397 | int (*start_hw)(struct iwl_trans *iwl_trans); | 418 | int (*start_hw)(struct iwl_trans *iwl_trans); |
398 | void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving); | 419 | void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving); |
399 | int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw); | 420 | int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw, |
421 | bool run_in_rfkill); | ||
400 | void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); | 422 | void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); |
401 | void (*stop_device)(struct iwl_trans *trans); | 423 | void (*stop_device)(struct iwl_trans *trans); |
402 | 424 | ||
403 | void (*wowlan_suspend)(struct iwl_trans *trans); | 425 | void (*d3_suspend)(struct iwl_trans *trans); |
426 | int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status); | ||
404 | 427 | ||
405 | int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); | 428 | int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); |
406 | 429 | ||
@@ -424,9 +447,15 @@ struct iwl_trans_ops { | |||
424 | u32 (*read32)(struct iwl_trans *trans, u32 ofs); | 447 | u32 (*read32)(struct iwl_trans *trans, u32 ofs); |
425 | u32 (*read_prph)(struct iwl_trans *trans, u32 ofs); | 448 | u32 (*read_prph)(struct iwl_trans *trans, u32 ofs); |
426 | void (*write_prph)(struct iwl_trans *trans, u32 ofs, u32 val); | 449 | void (*write_prph)(struct iwl_trans *trans, u32 ofs, u32 val); |
450 | int (*read_mem)(struct iwl_trans *trans, u32 addr, | ||
451 | void *buf, int dwords); | ||
452 | int (*write_mem)(struct iwl_trans *trans, u32 addr, | ||
453 | void *buf, int dwords); | ||
427 | void (*configure)(struct iwl_trans *trans, | 454 | void (*configure)(struct iwl_trans *trans, |
428 | const struct iwl_trans_config *trans_cfg); | 455 | const struct iwl_trans_config *trans_cfg); |
429 | void (*set_pmi)(struct iwl_trans *trans, bool state); | 456 | void (*set_pmi)(struct iwl_trans *trans, bool state); |
457 | bool (*grab_nic_access)(struct iwl_trans *trans, bool silent); | ||
458 | void (*release_nic_access)(struct iwl_trans *trans); | ||
430 | }; | 459 | }; |
431 | 460 | ||
432 | /** | 461 | /** |
@@ -528,13 +557,14 @@ static inline void iwl_trans_fw_alive(struct iwl_trans *trans, u32 scd_addr) | |||
528 | } | 557 | } |
529 | 558 | ||
530 | static inline int iwl_trans_start_fw(struct iwl_trans *trans, | 559 | static inline int iwl_trans_start_fw(struct iwl_trans *trans, |
531 | const struct fw_img *fw) | 560 | const struct fw_img *fw, |
561 | bool run_in_rfkill) | ||
532 | { | 562 | { |
533 | might_sleep(); | 563 | might_sleep(); |
534 | 564 | ||
535 | WARN_ON_ONCE(!trans->rx_mpdu_cmd); | 565 | WARN_ON_ONCE(!trans->rx_mpdu_cmd); |
536 | 566 | ||
537 | return trans->ops->start_fw(trans, fw); | 567 | return trans->ops->start_fw(trans, fw, run_in_rfkill); |
538 | } | 568 | } |
539 | 569 | ||
540 | static inline void iwl_trans_stop_device(struct iwl_trans *trans) | 570 | static inline void iwl_trans_stop_device(struct iwl_trans *trans) |
@@ -546,10 +576,17 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans) | |||
546 | trans->state = IWL_TRANS_NO_FW; | 576 | trans->state = IWL_TRANS_NO_FW; |
547 | } | 577 | } |
548 | 578 | ||
549 | static inline void iwl_trans_wowlan_suspend(struct iwl_trans *trans) | 579 | static inline void iwl_trans_d3_suspend(struct iwl_trans *trans) |
580 | { | ||
581 | might_sleep(); | ||
582 | trans->ops->d3_suspend(trans); | ||
583 | } | ||
584 | |||
585 | static inline int iwl_trans_d3_resume(struct iwl_trans *trans, | ||
586 | enum iwl_d3_status *status) | ||
550 | { | 587 | { |
551 | might_sleep(); | 588 | might_sleep(); |
552 | trans->ops->wowlan_suspend(trans); | 589 | return trans->ops->d3_resume(trans, status); |
553 | } | 590 | } |
554 | 591 | ||
555 | static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | 592 | static inline int iwl_trans_send_cmd(struct iwl_trans *trans, |
@@ -636,7 +673,7 @@ static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) | |||
636 | } | 673 | } |
637 | 674 | ||
638 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, | 675 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, |
639 | struct dentry *dir) | 676 | struct dentry *dir) |
640 | { | 677 | { |
641 | return trans->ops->dbgfs_register(trans, dir); | 678 | return trans->ops->dbgfs_register(trans, dir); |
642 | } | 679 | } |
@@ -679,11 +716,57 @@ static inline void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, | |||
679 | return trans->ops->write_prph(trans, ofs, val); | 716 | return trans->ops->write_prph(trans, ofs, val); |
680 | } | 717 | } |
681 | 718 | ||
719 | static inline int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr, | ||
720 | void *buf, int dwords) | ||
721 | { | ||
722 | return trans->ops->read_mem(trans, addr, buf, dwords); | ||
723 | } | ||
724 | |||
725 | #define iwl_trans_read_mem_bytes(trans, addr, buf, bufsize) \ | ||
726 | do { \ | ||
727 | if (__builtin_constant_p(bufsize)) \ | ||
728 | BUILD_BUG_ON((bufsize) % sizeof(u32)); \ | ||
729 | iwl_trans_read_mem(trans, addr, buf, (bufsize) / sizeof(u32));\ | ||
730 | } while (0) | ||
731 | |||
732 | static inline u32 iwl_trans_read_mem32(struct iwl_trans *trans, u32 addr) | ||
733 | { | ||
734 | u32 value; | ||
735 | |||
736 | if (WARN_ON(iwl_trans_read_mem(trans, addr, &value, 1))) | ||
737 | return 0xa5a5a5a5; | ||
738 | |||
739 | return value; | ||
740 | } | ||
741 | |||
742 | static inline int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr, | ||
743 | void *buf, int dwords) | ||
744 | { | ||
745 | return trans->ops->write_mem(trans, addr, buf, dwords); | ||
746 | } | ||
747 | |||
748 | static inline u32 iwl_trans_write_mem32(struct iwl_trans *trans, u32 addr, | ||
749 | u32 val) | ||
750 | { | ||
751 | return iwl_trans_write_mem(trans, addr, &val, 1); | ||
752 | } | ||
753 | |||
682 | static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state) | 754 | static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state) |
683 | { | 755 | { |
684 | trans->ops->set_pmi(trans, state); | 756 | trans->ops->set_pmi(trans, state); |
685 | } | 757 | } |
686 | 758 | ||
759 | #define iwl_trans_grab_nic_access(trans, silent) \ | ||
760 | __cond_lock(nic_access, \ | ||
761 | likely((trans)->ops->grab_nic_access(trans, silent))) | ||
762 | |||
763 | static inline void __releases(nic_access) | ||
764 | iwl_trans_release_nic_access(struct iwl_trans *trans) | ||
765 | { | ||
766 | trans->ops->release_nic_access(trans); | ||
767 | __release(nic_access); | ||
768 | } | ||
769 | |||
687 | /***************************************************** | 770 | /***************************************************** |
688 | * driver (transport) register/unregister functions | 771 | * driver (transport) register/unregister functions |
689 | ******************************************************/ | 772 | ******************************************************/ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index d91d2e8c62f5..20735a008cab 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -222,8 +222,6 @@ struct iwl_txq { | |||
222 | * @rx_replenish: work that will be called when buffers need to be allocated | 222 | * @rx_replenish: work that will be called when buffers need to be allocated |
223 | * @drv - pointer to iwl_drv | 223 | * @drv - pointer to iwl_drv |
224 | * @trans: pointer to the generic transport area | 224 | * @trans: pointer to the generic transport area |
225 | * @irq - the irq number for the device | ||
226 | * @irq_requested: true when the irq has been requested | ||
227 | * @scd_base_addr: scheduler sram base address in SRAM | 225 | * @scd_base_addr: scheduler sram base address in SRAM |
228 | * @scd_bc_tbls: pointer to the byte count table of the scheduler | 226 | * @scd_bc_tbls: pointer to the byte count table of the scheduler |
229 | * @kw: keep warm address | 227 | * @kw: keep warm address |
@@ -234,6 +232,7 @@ struct iwl_txq { | |||
234 | * @status - transport specific status flags | 232 | * @status - transport specific status flags |
235 | * @cmd_queue - command queue number | 233 | * @cmd_queue - command queue number |
236 | * @rx_buf_size_8k: 8 kB RX buffer size | 234 | * @rx_buf_size_8k: 8 kB RX buffer size |
235 | * @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes) | ||
237 | * @rx_page_order: page order for receive buffer size | 236 | * @rx_page_order: page order for receive buffer size |
238 | * @wd_timeout: queue watchdog timeout (jiffies) | 237 | * @wd_timeout: queue watchdog timeout (jiffies) |
239 | */ | 238 | */ |
@@ -249,11 +248,9 @@ struct iwl_trans_pcie { | |||
249 | int ict_index; | 248 | int ict_index; |
250 | u32 inta; | 249 | u32 inta; |
251 | bool use_ict; | 250 | bool use_ict; |
252 | bool irq_requested; | ||
253 | struct tasklet_struct irq_tasklet; | 251 | struct tasklet_struct irq_tasklet; |
254 | struct isr_statistics isr_stats; | 252 | struct isr_statistics isr_stats; |
255 | 253 | ||
256 | unsigned int irq; | ||
257 | spinlock_t irq_lock; | 254 | spinlock_t irq_lock; |
258 | u32 inta_mask; | 255 | u32 inta_mask; |
259 | u32 scd_base_addr; | 256 | u32 scd_base_addr; |
@@ -279,6 +276,7 @@ struct iwl_trans_pcie { | |||
279 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; | 276 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; |
280 | 277 | ||
281 | bool rx_buf_size_8k; | 278 | bool rx_buf_size_8k; |
279 | bool bc_table_dword; | ||
282 | u32 rx_page_order; | 280 | u32 rx_page_order; |
283 | 281 | ||
284 | const char **command_names; | 282 | const char **command_names; |
@@ -359,6 +357,8 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, | |||
359 | struct iwl_rx_cmd_buffer *rxb, int handler_status); | 357 | struct iwl_rx_cmd_buffer *rxb, int handler_status); |
360 | void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | 358 | void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, |
361 | struct sk_buff_head *skbs); | 359 | struct sk_buff_head *skbs); |
360 | void iwl_trans_pcie_tx_reset(struct iwl_trans *trans); | ||
361 | |||
362 | /***************************************************** | 362 | /***************************************************** |
363 | * Error handling | 363 | * Error handling |
364 | ******************************************************/ | 364 | ******************************************************/ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 8389cd38338b..4e6591d24e61 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -436,7 +436,7 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans) | |||
436 | err_rb_stts: | 436 | err_rb_stts: |
437 | dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, | 437 | dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, |
438 | rxq->bd, rxq->bd_dma); | 438 | rxq->bd, rxq->bd_dma); |
439 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); | 439 | rxq->bd_dma = 0; |
440 | rxq->bd = NULL; | 440 | rxq->bd = NULL; |
441 | err_bd: | 441 | err_bd: |
442 | return -ENOMEM; | 442 | return -ENOMEM; |
@@ -455,6 +455,10 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) | |||
455 | 455 | ||
456 | /* Stop Rx DMA */ | 456 | /* Stop Rx DMA */ |
457 | iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | 457 | iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); |
458 | /* reset and flush pointers */ | ||
459 | iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_RBDCB_WPTR, 0); | ||
460 | iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ, 0); | ||
461 | iwl_write_direct32(trans, FH_RSCSR_CHNL0_RDPTR, 0); | ||
458 | 462 | ||
459 | /* Reset driver's Rx queue write index */ | 463 | /* Reset driver's Rx queue write index */ |
460 | iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); | 464 | iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); |
@@ -491,7 +495,6 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) | |||
491 | { | 495 | { |
492 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 496 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
493 | struct iwl_rxq *rxq = &trans_pcie->rxq; | 497 | struct iwl_rxq *rxq = &trans_pcie->rxq; |
494 | |||
495 | int i, err; | 498 | int i, err; |
496 | unsigned long flags; | 499 | unsigned long flags; |
497 | 500 | ||
@@ -518,6 +521,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) | |||
518 | rxq->read = rxq->write = 0; | 521 | rxq->read = rxq->write = 0; |
519 | rxq->write_actual = 0; | 522 | rxq->write_actual = 0; |
520 | rxq->free_count = 0; | 523 | rxq->free_count = 0; |
524 | memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); | ||
521 | spin_unlock_irqrestore(&rxq->lock, flags); | 525 | spin_unlock_irqrestore(&rxq->lock, flags); |
522 | 526 | ||
523 | iwl_pcie_rx_replenish(trans); | 527 | iwl_pcie_rx_replenish(trans); |
@@ -545,13 +549,15 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) | |||
545 | return; | 549 | return; |
546 | } | 550 | } |
547 | 551 | ||
552 | cancel_work_sync(&trans_pcie->rx_replenish); | ||
553 | |||
548 | spin_lock_irqsave(&rxq->lock, flags); | 554 | spin_lock_irqsave(&rxq->lock, flags); |
549 | iwl_pcie_rxq_free_rbs(trans); | 555 | iwl_pcie_rxq_free_rbs(trans); |
550 | spin_unlock_irqrestore(&rxq->lock, flags); | 556 | spin_unlock_irqrestore(&rxq->lock, flags); |
551 | 557 | ||
552 | dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE, | 558 | dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE, |
553 | rxq->bd, rxq->bd_dma); | 559 | rxq->bd, rxq->bd_dma); |
554 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); | 560 | rxq->bd_dma = 0; |
555 | rxq->bd = NULL; | 561 | rxq->bd = NULL; |
556 | 562 | ||
557 | if (rxq->rb_stts) | 563 | if (rxq->rb_stts) |
@@ -560,7 +566,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) | |||
560 | rxq->rb_stts, rxq->rb_stts_dma); | 566 | rxq->rb_stts, rxq->rb_stts_dma); |
561 | else | 567 | else |
562 | IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); | 568 | IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); |
563 | memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma)); | 569 | rxq->rb_stts_dma = 0; |
564 | rxq->rb_stts = NULL; | 570 | rxq->rb_stts = NULL; |
565 | } | 571 | } |
566 | 572 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 35708b959ad6..c57641eb83d5 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -75,21 +75,16 @@ | |||
75 | #include "iwl-agn-hw.h" | 75 | #include "iwl-agn-hw.h" |
76 | #include "internal.h" | 76 | #include "internal.h" |
77 | 77 | ||
78 | static void iwl_pcie_set_pwr_vmain(struct iwl_trans *trans) | 78 | static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux) |
79 | { | 79 | { |
80 | /* | 80 | if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold)) |
81 | * (for documentation purposes) | 81 | iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, |
82 | * to set power to V_AUX, do: | 82 | APMG_PS_CTRL_VAL_PWR_SRC_VAUX, |
83 | 83 | ~APMG_PS_CTRL_MSK_PWR_SRC); | |
84 | if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) | 84 | else |
85 | iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, | 85 | iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, |
86 | APMG_PS_CTRL_VAL_PWR_SRC_VAUX, | 86 | APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, |
87 | ~APMG_PS_CTRL_MSK_PWR_SRC); | 87 | ~APMG_PS_CTRL_MSK_PWR_SRC); |
88 | */ | ||
89 | |||
90 | iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, | ||
91 | APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, | ||
92 | ~APMG_PS_CTRL_MSK_PWR_SRC); | ||
93 | } | 88 | } |
94 | 89 | ||
95 | /* PCI registers */ | 90 | /* PCI registers */ |
@@ -259,7 +254,7 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans) | |||
259 | 254 | ||
260 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 255 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
261 | 256 | ||
262 | iwl_pcie_set_pwr_vmain(trans); | 257 | iwl_pcie_set_pwr(trans, false); |
263 | 258 | ||
264 | iwl_op_mode_nic_config(trans->op_mode); | 259 | iwl_op_mode_nic_config(trans->op_mode); |
265 | 260 | ||
@@ -435,7 +430,7 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, | |||
435 | } | 430 | } |
436 | 431 | ||
437 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | 432 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, |
438 | const struct fw_img *fw) | 433 | const struct fw_img *fw, bool run_in_rfkill) |
439 | { | 434 | { |
440 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 435 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
441 | int ret; | 436 | int ret; |
@@ -454,7 +449,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | |||
454 | /* If platform's RF_KILL switch is NOT set to KILL */ | 449 | /* If platform's RF_KILL switch is NOT set to KILL */ |
455 | hw_rfkill = iwl_is_rfkill_set(trans); | 450 | hw_rfkill = iwl_is_rfkill_set(trans); |
456 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 451 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); |
457 | if (hw_rfkill) | 452 | if (hw_rfkill && !run_in_rfkill) |
458 | return -ERFKILL; | 453 | return -ERFKILL; |
459 | 454 | ||
460 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | 455 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); |
@@ -534,12 +529,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
534 | 529 | ||
535 | iwl_enable_rfkill_int(trans); | 530 | iwl_enable_rfkill_int(trans); |
536 | 531 | ||
537 | /* wait to make sure we flush pending tasklet*/ | ||
538 | synchronize_irq(trans_pcie->irq); | ||
539 | tasklet_kill(&trans_pcie->irq_tasklet); | ||
540 | |||
541 | cancel_work_sync(&trans_pcie->rx_replenish); | ||
542 | |||
543 | /* stop and reset the on-board processor */ | 532 | /* stop and reset the on-board processor */ |
544 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | 533 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); |
545 | 534 | ||
@@ -551,46 +540,87 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
551 | clear_bit(STATUS_RFKILL, &trans_pcie->status); | 540 | clear_bit(STATUS_RFKILL, &trans_pcie->status); |
552 | } | 541 | } |
553 | 542 | ||
554 | static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans) | 543 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans) |
555 | { | 544 | { |
556 | /* let the ucode operate on its own */ | 545 | /* let the ucode operate on its own */ |
557 | iwl_write32(trans, CSR_UCODE_DRV_GP1_SET, | 546 | iwl_write32(trans, CSR_UCODE_DRV_GP1_SET, |
558 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | 547 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); |
559 | 548 | ||
560 | iwl_disable_interrupts(trans); | 549 | iwl_disable_interrupts(trans); |
550 | iwl_pcie_disable_ict(trans); | ||
551 | |||
561 | iwl_clear_bit(trans, CSR_GP_CNTRL, | 552 | iwl_clear_bit(trans, CSR_GP_CNTRL, |
562 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 553 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
554 | iwl_clear_bit(trans, CSR_GP_CNTRL, | ||
555 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
556 | |||
557 | /* | ||
558 | * reset TX queues -- some of their registers reset during S3 | ||
559 | * so if we don't reset everything here the D3 image would try | ||
560 | * to execute some invalid memory upon resume | ||
561 | */ | ||
562 | iwl_trans_pcie_tx_reset(trans); | ||
563 | |||
564 | iwl_pcie_set_pwr(trans, true); | ||
563 | } | 565 | } |
564 | 566 | ||
565 | static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | 567 | static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, |
568 | enum iwl_d3_status *status) | ||
566 | { | 569 | { |
567 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 570 | u32 val; |
568 | int err; | 571 | int ret; |
569 | bool hw_rfkill; | ||
570 | 572 | ||
571 | trans_pcie->inta_mask = CSR_INI_SET_MASK; | 573 | iwl_pcie_set_pwr(trans, false); |
572 | 574 | ||
573 | if (!trans_pcie->irq_requested) { | 575 | val = iwl_read32(trans, CSR_RESET); |
574 | tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) | 576 | if (val & CSR_RESET_REG_FLAG_NEVO_RESET) { |
575 | iwl_pcie_tasklet, (unsigned long)trans); | 577 | *status = IWL_D3_STATUS_RESET; |
578 | return 0; | ||
579 | } | ||
576 | 580 | ||
577 | iwl_pcie_alloc_ict(trans); | 581 | /* |
582 | * Also enables interrupts - none will happen as the device doesn't | ||
583 | * know we're waking it up, only when the opmode actually tells it | ||
584 | * after this call. | ||
585 | */ | ||
586 | iwl_pcie_reset_ict(trans); | ||
578 | 587 | ||
579 | err = request_irq(trans_pcie->irq, iwl_pcie_isr_ict, | 588 | iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
580 | IRQF_SHARED, DRV_NAME, trans); | 589 | iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
581 | if (err) { | ||
582 | IWL_ERR(trans, "Error allocating IRQ %d\n", | ||
583 | trans_pcie->irq); | ||
584 | goto error; | ||
585 | } | ||
586 | 590 | ||
587 | trans_pcie->irq_requested = true; | 591 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, |
592 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
593 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
594 | 25000); | ||
595 | if (ret) { | ||
596 | IWL_ERR(trans, "Failed to resume the device (mac ready)\n"); | ||
597 | return ret; | ||
588 | } | 598 | } |
589 | 599 | ||
600 | iwl_trans_pcie_tx_reset(trans); | ||
601 | |||
602 | ret = iwl_pcie_rx_init(trans); | ||
603 | if (ret) { | ||
604 | IWL_ERR(trans, "Failed to resume the device (RX reset)\n"); | ||
605 | return ret; | ||
606 | } | ||
607 | |||
608 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, | ||
609 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | ||
610 | |||
611 | *status = IWL_D3_STATUS_ALIVE; | ||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | ||
616 | { | ||
617 | bool hw_rfkill; | ||
618 | int err; | ||
619 | |||
590 | err = iwl_pcie_prepare_card_hw(trans); | 620 | err = iwl_pcie_prepare_card_hw(trans); |
591 | if (err) { | 621 | if (err) { |
592 | IWL_ERR(trans, "Error while preparing HW: %d\n", err); | 622 | IWL_ERR(trans, "Error while preparing HW: %d\n", err); |
593 | goto err_free_irq; | 623 | return err; |
594 | } | 624 | } |
595 | 625 | ||
596 | iwl_pcie_apm_init(trans); | 626 | iwl_pcie_apm_init(trans); |
@@ -601,15 +631,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | |||
601 | hw_rfkill = iwl_is_rfkill_set(trans); | 631 | hw_rfkill = iwl_is_rfkill_set(trans); |
602 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 632 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); |
603 | 633 | ||
604 | return err; | 634 | return 0; |
605 | |||
606 | err_free_irq: | ||
607 | trans_pcie->irq_requested = false; | ||
608 | free_irq(trans_pcie->irq, trans); | ||
609 | error: | ||
610 | iwl_pcie_free_ict(trans); | ||
611 | tasklet_kill(&trans_pcie->irq_tasklet); | ||
612 | return err; | ||
613 | } | 635 | } |
614 | 636 | ||
615 | static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, | 637 | static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, |
@@ -703,19 +725,21 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, | |||
703 | msecs_to_jiffies(trans_cfg->queue_watchdog_timeout); | 725 | msecs_to_jiffies(trans_cfg->queue_watchdog_timeout); |
704 | 726 | ||
705 | trans_pcie->command_names = trans_cfg->command_names; | 727 | trans_pcie->command_names = trans_cfg->command_names; |
728 | trans_pcie->bc_table_dword = trans_cfg->bc_table_dword; | ||
706 | } | 729 | } |
707 | 730 | ||
708 | void iwl_trans_pcie_free(struct iwl_trans *trans) | 731 | void iwl_trans_pcie_free(struct iwl_trans *trans) |
709 | { | 732 | { |
710 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 733 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
711 | 734 | ||
735 | synchronize_irq(trans_pcie->pci_dev->irq); | ||
736 | tasklet_kill(&trans_pcie->irq_tasklet); | ||
737 | |||
712 | iwl_pcie_tx_free(trans); | 738 | iwl_pcie_tx_free(trans); |
713 | iwl_pcie_rx_free(trans); | 739 | iwl_pcie_rx_free(trans); |
714 | 740 | ||
715 | if (trans_pcie->irq_requested == true) { | 741 | free_irq(trans_pcie->pci_dev->irq, trans); |
716 | free_irq(trans_pcie->irq, trans); | 742 | iwl_pcie_free_ict(trans); |
717 | iwl_pcie_free_ict(trans); | ||
718 | } | ||
719 | 743 | ||
720 | pci_disable_msi(trans_pcie->pci_dev); | 744 | pci_disable_msi(trans_pcie->pci_dev); |
721 | iounmap(trans_pcie->hw_base); | 745 | iounmap(trans_pcie->hw_base); |
@@ -751,13 +775,112 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) | |||
751 | hw_rfkill = iwl_is_rfkill_set(trans); | 775 | hw_rfkill = iwl_is_rfkill_set(trans); |
752 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | 776 | iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); |
753 | 777 | ||
754 | if (!hw_rfkill) | ||
755 | iwl_enable_interrupts(trans); | ||
756 | |||
757 | return 0; | 778 | return 0; |
758 | } | 779 | } |
759 | #endif /* CONFIG_PM_SLEEP */ | 780 | #endif /* CONFIG_PM_SLEEP */ |
760 | 781 | ||
782 | static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) | ||
783 | { | ||
784 | int ret; | ||
785 | |||
786 | lockdep_assert_held(&trans->reg_lock); | ||
787 | |||
788 | /* this bit wakes up the NIC */ | ||
789 | __iwl_set_bit(trans, CSR_GP_CNTRL, | ||
790 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
791 | |||
792 | /* | ||
793 | * These bits say the device is running, and should keep running for | ||
794 | * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), | ||
795 | * but they do not indicate that embedded SRAM is restored yet; | ||
796 | * 3945 and 4965 have volatile SRAM, and must save/restore contents | ||
797 | * to/from host DRAM when sleeping/waking for power-saving. | ||
798 | * Each direction takes approximately 1/4 millisecond; with this | ||
799 | * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a | ||
800 | * series of register accesses are expected (e.g. reading Event Log), | ||
801 | * to keep device from sleeping. | ||
802 | * | ||
803 | * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that | ||
804 | * SRAM is okay/restored. We don't check that here because this call | ||
805 | * is just for hardware register access; but GP1 MAC_SLEEP check is a | ||
806 | * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). | ||
807 | * | ||
808 | * 5000 series and later (including 1000 series) have non-volatile SRAM, | ||
809 | * and do not save/restore SRAM when power cycling. | ||
810 | */ | ||
811 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
812 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, | ||
813 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | | ||
814 | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); | ||
815 | if (unlikely(ret < 0)) { | ||
816 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); | ||
817 | if (!silent) { | ||
818 | u32 val = iwl_read32(trans, CSR_GP_CNTRL); | ||
819 | WARN_ONCE(1, | ||
820 | "Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n", | ||
821 | val); | ||
822 | return false; | ||
823 | } | ||
824 | } | ||
825 | |||
826 | return true; | ||
827 | } | ||
828 | |||
829 | static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) | ||
830 | { | ||
831 | lockdep_assert_held(&trans->reg_lock); | ||
832 | __iwl_clear_bit(trans, CSR_GP_CNTRL, | ||
833 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
834 | /* | ||
835 | * Above we read the CSR_GP_CNTRL register, which will flush | ||
836 | * any previous writes, but we need the write that clears the | ||
837 | * MAC_ACCESS_REQ bit to be performed before any other writes | ||
838 | * scheduled on different CPUs (after we drop reg_lock). | ||
839 | */ | ||
840 | mmiowb(); | ||
841 | } | ||
842 | |||
843 | static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, | ||
844 | void *buf, int dwords) | ||
845 | { | ||
846 | unsigned long flags; | ||
847 | int offs, ret = 0; | ||
848 | u32 *vals = buf; | ||
849 | |||
850 | spin_lock_irqsave(&trans->reg_lock, flags); | ||
851 | if (iwl_trans_grab_nic_access(trans, false)) { | ||
852 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); | ||
853 | for (offs = 0; offs < dwords; offs++) | ||
854 | vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); | ||
855 | iwl_trans_release_nic_access(trans); | ||
856 | } else { | ||
857 | ret = -EBUSY; | ||
858 | } | ||
859 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
860 | return ret; | ||
861 | } | ||
862 | |||
863 | static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, | ||
864 | void *buf, int dwords) | ||
865 | { | ||
866 | unsigned long flags; | ||
867 | int offs, ret = 0; | ||
868 | u32 *vals = buf; | ||
869 | |||
870 | spin_lock_irqsave(&trans->reg_lock, flags); | ||
871 | if (iwl_trans_grab_nic_access(trans, false)) { | ||
872 | iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); | ||
873 | for (offs = 0; offs < dwords; offs++) | ||
874 | iwl_write32(trans, HBUS_TARG_MEM_WDAT, | ||
875 | vals ? vals[offs] : 0); | ||
876 | iwl_trans_release_nic_access(trans); | ||
877 | } else { | ||
878 | ret = -EBUSY; | ||
879 | } | ||
880 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
881 | return ret; | ||
882 | } | ||
883 | |||
761 | #define IWL_FLUSH_WAIT_MS 2000 | 884 | #define IWL_FLUSH_WAIT_MS 2000 |
762 | 885 | ||
763 | static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) | 886 | static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) |
@@ -767,6 +890,8 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) | |||
767 | struct iwl_queue *q; | 890 | struct iwl_queue *q; |
768 | int cnt; | 891 | int cnt; |
769 | unsigned long now = jiffies; | 892 | unsigned long now = jiffies; |
893 | u32 scd_sram_addr; | ||
894 | u8 buf[16]; | ||
770 | int ret = 0; | 895 | int ret = 0; |
771 | 896 | ||
772 | /* waiting for all the tx frames complete might take a while */ | 897 | /* waiting for all the tx frames complete might take a while */ |
@@ -780,11 +905,50 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) | |||
780 | msleep(1); | 905 | msleep(1); |
781 | 906 | ||
782 | if (q->read_ptr != q->write_ptr) { | 907 | if (q->read_ptr != q->write_ptr) { |
783 | IWL_ERR(trans, "fail to flush all tx fifo queues\n"); | 908 | IWL_ERR(trans, |
909 | "fail to flush all tx fifo queues Q %d\n", cnt); | ||
784 | ret = -ETIMEDOUT; | 910 | ret = -ETIMEDOUT; |
785 | break; | 911 | break; |
786 | } | 912 | } |
787 | } | 913 | } |
914 | |||
915 | if (!ret) | ||
916 | return 0; | ||
917 | |||
918 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", | ||
919 | txq->q.read_ptr, txq->q.write_ptr); | ||
920 | |||
921 | scd_sram_addr = trans_pcie->scd_base_addr + | ||
922 | SCD_TX_STTS_QUEUE_OFFSET(txq->q.id); | ||
923 | iwl_trans_read_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf)); | ||
924 | |||
925 | iwl_print_hex_error(trans, buf, sizeof(buf)); | ||
926 | |||
927 | for (cnt = 0; cnt < FH_TCSR_CHNL_NUM; cnt++) | ||
928 | IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", cnt, | ||
929 | iwl_read_direct32(trans, FH_TX_TRB_REG(cnt))); | ||
930 | |||
931 | for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) { | ||
932 | u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(cnt)); | ||
933 | u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7; | ||
934 | bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE)); | ||
935 | u32 tbl_dw = | ||
936 | iwl_trans_read_mem32(trans, trans_pcie->scd_base_addr + | ||
937 | SCD_TRANS_TBL_OFFSET_QUEUE(cnt)); | ||
938 | |||
939 | if (cnt & 0x1) | ||
940 | tbl_dw = (tbl_dw & 0xFFFF0000) >> 16; | ||
941 | else | ||
942 | tbl_dw = tbl_dw & 0x0000FFFF; | ||
943 | |||
944 | IWL_ERR(trans, | ||
945 | "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n", | ||
946 | cnt, active ? "" : "in", fifo, tbl_dw, | ||
947 | iwl_read_prph(trans, | ||
948 | SCD_QUEUE_RDPTR(cnt)) & (txq->q.n_bd - 1), | ||
949 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt))); | ||
950 | } | ||
951 | |||
788 | return ret; | 952 | return ret; |
789 | } | 953 | } |
790 | 954 | ||
@@ -1212,7 +1376,8 @@ static const struct iwl_trans_ops trans_ops_pcie = { | |||
1212 | .start_fw = iwl_trans_pcie_start_fw, | 1376 | .start_fw = iwl_trans_pcie_start_fw, |
1213 | .stop_device = iwl_trans_pcie_stop_device, | 1377 | .stop_device = iwl_trans_pcie_stop_device, |
1214 | 1378 | ||
1215 | .wowlan_suspend = iwl_trans_pcie_wowlan_suspend, | 1379 | .d3_suspend = iwl_trans_pcie_d3_suspend, |
1380 | .d3_resume = iwl_trans_pcie_d3_resume, | ||
1216 | 1381 | ||
1217 | .send_cmd = iwl_trans_pcie_send_hcmd, | 1382 | .send_cmd = iwl_trans_pcie_send_hcmd, |
1218 | 1383 | ||
@@ -1235,8 +1400,12 @@ static const struct iwl_trans_ops trans_ops_pcie = { | |||
1235 | .read32 = iwl_trans_pcie_read32, | 1400 | .read32 = iwl_trans_pcie_read32, |
1236 | .read_prph = iwl_trans_pcie_read_prph, | 1401 | .read_prph = iwl_trans_pcie_read_prph, |
1237 | .write_prph = iwl_trans_pcie_write_prph, | 1402 | .write_prph = iwl_trans_pcie_write_prph, |
1403 | .read_mem = iwl_trans_pcie_read_mem, | ||
1404 | .write_mem = iwl_trans_pcie_write_mem, | ||
1238 | .configure = iwl_trans_pcie_configure, | 1405 | .configure = iwl_trans_pcie_configure, |
1239 | .set_pmi = iwl_trans_pcie_set_pmi, | 1406 | .set_pmi = iwl_trans_pcie_set_pmi, |
1407 | .grab_nic_access = iwl_trans_pcie_grab_nic_access, | ||
1408 | .release_nic_access = iwl_trans_pcie_release_nic_access | ||
1240 | }; | 1409 | }; |
1241 | 1410 | ||
1242 | struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | 1411 | struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, |
@@ -1318,7 +1487,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
1318 | } | 1487 | } |
1319 | 1488 | ||
1320 | trans->dev = &pdev->dev; | 1489 | trans->dev = &pdev->dev; |
1321 | trans_pcie->irq = pdev->irq; | ||
1322 | trans_pcie->pci_dev = pdev; | 1490 | trans_pcie->pci_dev = pdev; |
1323 | trans->hw_rev = iwl_read32(trans, CSR_HW_REV); | 1491 | trans->hw_rev = iwl_read32(trans, CSR_HW_REV); |
1324 | trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; | 1492 | trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; |
@@ -1344,8 +1512,27 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
1344 | if (!trans->dev_cmd_pool) | 1512 | if (!trans->dev_cmd_pool) |
1345 | goto out_pci_disable_msi; | 1513 | goto out_pci_disable_msi; |
1346 | 1514 | ||
1515 | trans_pcie->inta_mask = CSR_INI_SET_MASK; | ||
1516 | |||
1517 | tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) | ||
1518 | iwl_pcie_tasklet, (unsigned long)trans); | ||
1519 | |||
1520 | if (iwl_pcie_alloc_ict(trans)) | ||
1521 | goto out_free_cmd_pool; | ||
1522 | |||
1523 | err = request_irq(pdev->irq, iwl_pcie_isr_ict, | ||
1524 | IRQF_SHARED, DRV_NAME, trans); | ||
1525 | if (err) { | ||
1526 | IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq); | ||
1527 | goto out_free_ict; | ||
1528 | } | ||
1529 | |||
1347 | return trans; | 1530 | return trans; |
1348 | 1531 | ||
1532 | out_free_ict: | ||
1533 | iwl_pcie_free_ict(trans); | ||
1534 | out_free_cmd_pool: | ||
1535 | kmem_cache_destroy(trans->dev_cmd_pool); | ||
1349 | out_pci_disable_msi: | 1536 | out_pci_disable_msi: |
1350 | pci_disable_msi(pdev); | 1537 | pci_disable_msi(pdev); |
1351 | out_pci_release_regions: | 1538 | out_pci_release_regions: |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 6c5b867c353a..a93f06762b96 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -160,7 +160,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
160 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", | 160 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", |
161 | txq->q.read_ptr, txq->q.write_ptr); | 161 | txq->q.read_ptr, txq->q.write_ptr); |
162 | 162 | ||
163 | iwl_read_targ_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf)); | 163 | iwl_trans_read_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf)); |
164 | 164 | ||
165 | iwl_print_hex_error(trans, buf, sizeof(buf)); | 165 | iwl_print_hex_error(trans, buf, sizeof(buf)); |
166 | 166 | ||
@@ -173,9 +173,9 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
173 | u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7; | 173 | u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7; |
174 | bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE)); | 174 | bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE)); |
175 | u32 tbl_dw = | 175 | u32 tbl_dw = |
176 | iwl_read_targ_mem(trans, | 176 | iwl_trans_read_mem32(trans, |
177 | trans_pcie->scd_base_addr + | 177 | trans_pcie->scd_base_addr + |
178 | SCD_TRANS_TBL_OFFSET_QUEUE(i)); | 178 | SCD_TRANS_TBL_OFFSET_QUEUE(i)); |
179 | 179 | ||
180 | if (i & 0x1) | 180 | if (i & 0x1) |
181 | tbl_dw = (tbl_dw & 0xFFFF0000) >> 16; | 181 | tbl_dw = (tbl_dw & 0xFFFF0000) >> 16; |
@@ -237,7 +237,10 @@ static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans, | |||
237 | break; | 237 | break; |
238 | } | 238 | } |
239 | 239 | ||
240 | bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); | 240 | if (trans_pcie->bc_table_dword) |
241 | len = DIV_ROUND_UP(len, 4); | ||
242 | |||
243 | bc_ent = cpu_to_le16(len | (sta_id << 12)); | ||
241 | 244 | ||
242 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; | 245 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; |
243 | 246 | ||
@@ -306,6 +309,9 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) | |||
306 | return; | 309 | return; |
307 | } | 310 | } |
308 | 311 | ||
312 | IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, | ||
313 | txq->q.write_ptr); | ||
314 | |||
309 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, | 315 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, |
310 | txq->q.write_ptr | (txq_id << 8)); | 316 | txq->q.write_ptr | (txq_id << 8)); |
311 | 317 | ||
@@ -612,7 +618,7 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id) | |||
612 | if (txq->q.n_bd) { | 618 | if (txq->q.n_bd) { |
613 | dma_free_coherent(dev, sizeof(struct iwl_tfd) * | 619 | dma_free_coherent(dev, sizeof(struct iwl_tfd) * |
614 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | 620 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); |
615 | memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr)); | 621 | txq->q.dma_addr = 0; |
616 | } | 622 | } |
617 | 623 | ||
618 | kfree(txq->entries); | 624 | kfree(txq->entries); |
@@ -638,9 +644,11 @@ static void iwl_pcie_txq_set_sched(struct iwl_trans *trans, u32 mask) | |||
638 | void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr) | 644 | void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr) |
639 | { | 645 | { |
640 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 646 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
641 | u32 a; | 647 | int nq = trans->cfg->base_params->num_of_queues; |
642 | int chan; | 648 | int chan; |
643 | u32 reg_val; | 649 | u32 reg_val; |
650 | int clear_dwords = (SCD_TRANS_TBL_OFFSET_QUEUE(nq) - | ||
651 | SCD_CONTEXT_MEM_LOWER_BOUND) / sizeof(u32); | ||
644 | 652 | ||
645 | /* make sure all queue are not stopped/used */ | 653 | /* make sure all queue are not stopped/used */ |
646 | memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); | 654 | memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); |
@@ -652,20 +660,10 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr) | |||
652 | WARN_ON(scd_base_addr != 0 && | 660 | WARN_ON(scd_base_addr != 0 && |
653 | scd_base_addr != trans_pcie->scd_base_addr); | 661 | scd_base_addr != trans_pcie->scd_base_addr); |
654 | 662 | ||
655 | a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; | 663 | /* reset context data, TX status and translation data */ |
656 | /* reset conext data memory */ | 664 | iwl_trans_write_mem(trans, trans_pcie->scd_base_addr + |
657 | for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; | 665 | SCD_CONTEXT_MEM_LOWER_BOUND, |
658 | a += 4) | 666 | NULL, clear_dwords); |
659 | iwl_write_targ_mem(trans, a, 0); | ||
660 | /* reset tx status memory */ | ||
661 | for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; | ||
662 | a += 4) | ||
663 | iwl_write_targ_mem(trans, a, 0); | ||
664 | for (; a < trans_pcie->scd_base_addr + | ||
665 | SCD_TRANS_TBL_OFFSET_QUEUE( | ||
666 | trans->cfg->base_params->num_of_queues); | ||
667 | a += 4) | ||
668 | iwl_write_targ_mem(trans, a, 0); | ||
669 | 667 | ||
670 | iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, | 668 | iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, |
671 | trans_pcie->scd_bc_tbls.dma >> 10); | 669 | trans_pcie->scd_bc_tbls.dma >> 10); |
@@ -697,6 +695,29 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr) | |||
697 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 695 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); |
698 | } | 696 | } |
699 | 697 | ||
698 | void iwl_trans_pcie_tx_reset(struct iwl_trans *trans) | ||
699 | { | ||
700 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
701 | int txq_id; | ||
702 | |||
703 | for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues; | ||
704 | txq_id++) { | ||
705 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; | ||
706 | |||
707 | iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(txq_id), | ||
708 | txq->q.dma_addr >> 8); | ||
709 | iwl_pcie_txq_unmap(trans, txq_id); | ||
710 | txq->q.read_ptr = 0; | ||
711 | txq->q.write_ptr = 0; | ||
712 | } | ||
713 | |||
714 | /* Tell NIC where to find the "keep warm" buffer */ | ||
715 | iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, | ||
716 | trans_pcie->kw.dma >> 4); | ||
717 | |||
718 | iwl_pcie_tx_start(trans, trans_pcie->scd_base_addr); | ||
719 | } | ||
720 | |||
700 | /* | 721 | /* |
701 | * iwl_pcie_tx_stop - Stop all Tx DMA channels | 722 | * iwl_pcie_tx_stop - Stop all Tx DMA channels |
702 | */ | 723 | */ |
@@ -1002,14 +1023,14 @@ static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, | |||
1002 | tbl_dw_addr = trans_pcie->scd_base_addr + | 1023 | tbl_dw_addr = trans_pcie->scd_base_addr + |
1003 | SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); | 1024 | SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); |
1004 | 1025 | ||
1005 | tbl_dw = iwl_read_targ_mem(trans, tbl_dw_addr); | 1026 | tbl_dw = iwl_trans_read_mem32(trans, tbl_dw_addr); |
1006 | 1027 | ||
1007 | if (txq_id & 0x1) | 1028 | if (txq_id & 0x1) |
1008 | tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); | 1029 | tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); |
1009 | else | 1030 | else |
1010 | tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); | 1031 | tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); |
1011 | 1032 | ||
1012 | iwl_write_targ_mem(trans, tbl_dw_addr, tbl_dw); | 1033 | iwl_trans_write_mem32(trans, tbl_dw_addr, tbl_dw); |
1013 | 1034 | ||
1014 | return 0; | 1035 | return 0; |
1015 | } | 1036 | } |
@@ -1068,9 +1089,9 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, | |||
1068 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn); | 1089 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn); |
1069 | 1090 | ||
1070 | /* Set up Tx window size and frame limit for this queue */ | 1091 | /* Set up Tx window size and frame limit for this queue */ |
1071 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | 1092 | iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr + |
1072 | SCD_CONTEXT_QUEUE_OFFSET(txq_id), 0); | 1093 | SCD_CONTEXT_QUEUE_OFFSET(txq_id), 0); |
1073 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | 1094 | iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr + |
1074 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), | 1095 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), |
1075 | ((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | 1096 | ((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & |
1076 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | 1097 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | |
@@ -1101,8 +1122,8 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) | |||
1101 | 1122 | ||
1102 | iwl_pcie_txq_set_inactive(trans, txq_id); | 1123 | iwl_pcie_txq_set_inactive(trans, txq_id); |
1103 | 1124 | ||
1104 | _iwl_write_targ_mem_dwords(trans, stts_addr, | 1125 | iwl_trans_write_mem(trans, stts_addr, (void *)zero_val, |
1105 | zero_val, ARRAY_SIZE(zero_val)); | 1126 | ARRAY_SIZE(zero_val)); |
1106 | 1127 | ||
1107 | iwl_pcie_txq_unmap(trans, txq_id); | 1128 | iwl_pcie_txq_unmap(trans, txq_id); |
1108 | 1129 | ||
@@ -1642,10 +1663,6 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1642 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | 1663 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); |
1643 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | 1664 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); |
1644 | 1665 | ||
1645 | IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n", | ||
1646 | le16_to_cpu(dev_cmd->hdr.sequence)); | ||
1647 | IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); | ||
1648 | |||
1649 | /* Set up entry for this TFD in Tx byte-count array */ | 1666 | /* Set up entry for this TFD in Tx byte-count array */ |
1650 | iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); | 1667 | iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); |
1651 | 1668 | ||
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index ec6d5d6b452e..230f8ebbe289 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -2132,6 +2132,21 @@ static void lbs_cfg_set_regulatory_hint(struct lbs_private *priv) | |||
2132 | lbs_deb_leave(LBS_DEB_CFG80211); | 2132 | lbs_deb_leave(LBS_DEB_CFG80211); |
2133 | } | 2133 | } |
2134 | 2134 | ||
2135 | static void lbs_reg_notifier(struct wiphy *wiphy, | ||
2136 | struct regulatory_request *request) | ||
2137 | { | ||
2138 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
2139 | |||
2140 | lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain " | ||
2141 | "callback for domain %c%c\n", request->alpha2[0], | ||
2142 | request->alpha2[1]); | ||
2143 | |||
2144 | memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2)); | ||
2145 | if (lbs_iface_active(priv)) | ||
2146 | lbs_set_11d_domain_info(priv); | ||
2147 | |||
2148 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
2149 | } | ||
2135 | 2150 | ||
2136 | /* | 2151 | /* |
2137 | * This function get's called after lbs_setup_firmware() determined the | 2152 | * This function get's called after lbs_setup_firmware() determined the |
@@ -2184,24 +2199,6 @@ int lbs_cfg_register(struct lbs_private *priv) | |||
2184 | return ret; | 2199 | return ret; |
2185 | } | 2200 | } |
2186 | 2201 | ||
2187 | int lbs_reg_notifier(struct wiphy *wiphy, | ||
2188 | struct regulatory_request *request) | ||
2189 | { | ||
2190 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
2191 | int ret = 0; | ||
2192 | |||
2193 | lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain " | ||
2194 | "callback for domain %c%c\n", request->alpha2[0], | ||
2195 | request->alpha2[1]); | ||
2196 | |||
2197 | memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2)); | ||
2198 | if (lbs_iface_active(priv)) | ||
2199 | ret = lbs_set_11d_domain_info(priv); | ||
2200 | |||
2201 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
2202 | return ret; | ||
2203 | } | ||
2204 | |||
2205 | void lbs_scan_deinit(struct lbs_private *priv) | 2202 | void lbs_scan_deinit(struct lbs_private *priv) |
2206 | { | 2203 | { |
2207 | lbs_deb_enter(LBS_DEB_CFG80211); | 2204 | lbs_deb_enter(LBS_DEB_CFG80211); |
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h index 558168ce634d..10995f59fe34 100644 --- a/drivers/net/wireless/libertas/cfg.h +++ b/drivers/net/wireless/libertas/cfg.h | |||
@@ -10,9 +10,6 @@ struct wireless_dev *lbs_cfg_alloc(struct device *dev); | |||
10 | int lbs_cfg_register(struct lbs_private *priv); | 10 | int lbs_cfg_register(struct lbs_private *priv); |
11 | void lbs_cfg_free(struct lbs_private *priv); | 11 | void lbs_cfg_free(struct lbs_private *priv); |
12 | 12 | ||
13 | int lbs_reg_notifier(struct wiphy *wiphy, | ||
14 | struct regulatory_request *request); | ||
15 | |||
16 | void lbs_send_disconnect_notification(struct lbs_private *priv); | 13 | void lbs_send_disconnect_notification(struct lbs_private *priv); |
17 | void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event); | 14 | void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event); |
18 | 15 | ||
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index ff9085502bea..b73e497fe770 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -48,6 +48,10 @@ static int channels = 1; | |||
48 | module_param(channels, int, 0444); | 48 | module_param(channels, int, 0444); |
49 | MODULE_PARM_DESC(channels, "Number of concurrent channels"); | 49 | MODULE_PARM_DESC(channels, "Number of concurrent channels"); |
50 | 50 | ||
51 | static bool paged_rx = false; | ||
52 | module_param(paged_rx, bool, 0644); | ||
53 | MODULE_PARM_DESC(paged_rx, "Use paged SKBs for RX instead of linear ones"); | ||
54 | |||
51 | /** | 55 | /** |
52 | * enum hwsim_regtest - the type of regulatory tests we offer | 56 | * enum hwsim_regtest - the type of regulatory tests we offer |
53 | * | 57 | * |
@@ -333,11 +337,11 @@ struct mac80211_hwsim_data { | |||
333 | int scan_chan_idx; | 337 | int scan_chan_idx; |
334 | 338 | ||
335 | struct ieee80211_channel *channel; | 339 | struct ieee80211_channel *channel; |
336 | unsigned long beacon_int; /* in jiffies unit */ | 340 | u64 beacon_int /* beacon interval in us */; |
337 | unsigned int rx_filter; | 341 | unsigned int rx_filter; |
338 | bool started, idle, scanning; | 342 | bool started, idle, scanning; |
339 | struct mutex mutex; | 343 | struct mutex mutex; |
340 | struct timer_list beacon_timer; | 344 | struct tasklet_hrtimer beacon_timer; |
341 | enum ps_mode { | 345 | enum ps_mode { |
342 | PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL | 346 | PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL |
343 | } ps; | 347 | } ps; |
@@ -357,7 +361,10 @@ struct mac80211_hwsim_data { | |||
357 | int power_level; | 361 | int power_level; |
358 | 362 | ||
359 | /* difference between this hw's clock and the real clock, in usecs */ | 363 | /* difference between this hw's clock and the real clock, in usecs */ |
360 | u64 tsf_offset; | 364 | s64 tsf_offset; |
365 | s64 bcn_delta; | ||
366 | /* absolute beacon transmission time. Used to cover up "tx" delay. */ | ||
367 | u64 abs_bcn_ts; | ||
361 | }; | 368 | }; |
362 | 369 | ||
363 | 370 | ||
@@ -405,15 +412,19 @@ static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb, | |||
405 | return NETDEV_TX_OK; | 412 | return NETDEV_TX_OK; |
406 | } | 413 | } |
407 | 414 | ||
415 | static inline u64 mac80211_hwsim_get_tsf_raw(void) | ||
416 | { | ||
417 | return ktime_to_us(ktime_get_real()); | ||
418 | } | ||
419 | |||
408 | static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) | 420 | static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) |
409 | { | 421 | { |
410 | struct timeval tv = ktime_to_timeval(ktime_get_real()); | 422 | u64 now = mac80211_hwsim_get_tsf_raw(); |
411 | u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec; | ||
412 | return cpu_to_le64(now + data->tsf_offset); | 423 | return cpu_to_le64(now + data->tsf_offset); |
413 | } | 424 | } |
414 | 425 | ||
415 | static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw, | 426 | static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw, |
416 | struct ieee80211_vif *vif) | 427 | struct ieee80211_vif *vif) |
417 | { | 428 | { |
418 | struct mac80211_hwsim_data *data = hw->priv; | 429 | struct mac80211_hwsim_data *data = hw->priv; |
419 | return le64_to_cpu(__mac80211_hwsim_get_tsf(data)); | 430 | return le64_to_cpu(__mac80211_hwsim_get_tsf(data)); |
@@ -423,9 +434,13 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw, | |||
423 | struct ieee80211_vif *vif, u64 tsf) | 434 | struct ieee80211_vif *vif, u64 tsf) |
424 | { | 435 | { |
425 | struct mac80211_hwsim_data *data = hw->priv; | 436 | struct mac80211_hwsim_data *data = hw->priv; |
426 | struct timeval tv = ktime_to_timeval(ktime_get_real()); | 437 | u64 now = mac80211_hwsim_get_tsf(hw, vif); |
427 | u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec; | 438 | u32 bcn_int = data->beacon_int; |
428 | data->tsf_offset = tsf - now; | 439 | s64 delta = tsf - now; |
440 | |||
441 | data->tsf_offset += delta; | ||
442 | /* adjust after beaconing with new timestamp at old TBTT */ | ||
443 | data->bcn_delta = do_div(delta, bcn_int); | ||
429 | } | 444 | } |
430 | 445 | ||
431 | static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, | 446 | static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, |
@@ -696,7 +711,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
696 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 711 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
697 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 712 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
698 | struct ieee80211_rx_status rx_status; | 713 | struct ieee80211_rx_status rx_status; |
699 | struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); | 714 | u64 now; |
700 | 715 | ||
701 | memset(&rx_status, 0, sizeof(rx_status)); | 716 | memset(&rx_status, 0, sizeof(rx_status)); |
702 | rx_status.flag |= RX_FLAG_MACTIME_START; | 717 | rx_status.flag |= RX_FLAG_MACTIME_START; |
@@ -722,11 +737,23 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
722 | secpath_reset(skb); | 737 | secpath_reset(skb); |
723 | nf_reset(skb); | 738 | nf_reset(skb); |
724 | 739 | ||
740 | /* | ||
741 | * Get absolute mactime here so all HWs RX at the "same time", and | ||
742 | * absolute TX time for beacon mactime so the timestamp matches. | ||
743 | * Giving beacons a different mactime than non-beacons looks messy, but | ||
744 | * it helps the Toffset be exact and a ~10us mactime discrepancy | ||
745 | * probably doesn't really matter. | ||
746 | */ | ||
747 | if (ieee80211_is_beacon(hdr->frame_control) || | ||
748 | ieee80211_is_probe_resp(hdr->frame_control)) | ||
749 | now = data->abs_bcn_ts; | ||
750 | else | ||
751 | now = mac80211_hwsim_get_tsf_raw(); | ||
752 | |||
725 | /* Copy skb to all enabled radios that are on the current frequency */ | 753 | /* Copy skb to all enabled radios that are on the current frequency */ |
726 | spin_lock(&hwsim_radio_lock); | 754 | spin_lock(&hwsim_radio_lock); |
727 | list_for_each_entry(data2, &hwsim_radios, list) { | 755 | list_for_each_entry(data2, &hwsim_radios, list) { |
728 | struct sk_buff *nskb; | 756 | struct sk_buff *nskb; |
729 | struct ieee80211_mgmt *mgmt; | ||
730 | struct tx_iter_data tx_iter_data = { | 757 | struct tx_iter_data tx_iter_data = { |
731 | .receive = false, | 758 | .receive = false, |
732 | .channel = chan, | 759 | .channel = chan, |
@@ -755,24 +782,30 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
755 | * reserve some space for our vendor and the normal | 782 | * reserve some space for our vendor and the normal |
756 | * radiotap header, since we're copying anyway | 783 | * radiotap header, since we're copying anyway |
757 | */ | 784 | */ |
758 | nskb = skb_copy_expand(skb, 64, 0, GFP_ATOMIC); | 785 | if (skb->len < PAGE_SIZE && paged_rx) { |
759 | if (nskb == NULL) | 786 | struct page *page = alloc_page(GFP_ATOMIC); |
760 | continue; | 787 | |
788 | if (!page) | ||
789 | continue; | ||
790 | |||
791 | nskb = dev_alloc_skb(128); | ||
792 | if (!nskb) { | ||
793 | __free_page(page); | ||
794 | continue; | ||
795 | } | ||
796 | |||
797 | memcpy(page_address(page), skb->data, skb->len); | ||
798 | skb_add_rx_frag(nskb, 0, page, 0, skb->len, skb->len); | ||
799 | } else { | ||
800 | nskb = skb_copy(skb, GFP_ATOMIC); | ||
801 | if (!nskb) | ||
802 | continue; | ||
803 | } | ||
761 | 804 | ||
762 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) | 805 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) |
763 | ack = true; | 806 | ack = true; |
764 | 807 | ||
765 | /* set bcn timestamp relative to receiver mactime */ | 808 | rx_status.mactime = now + data2->tsf_offset; |
766 | rx_status.mactime = | ||
767 | le64_to_cpu(__mac80211_hwsim_get_tsf(data2)); | ||
768 | mgmt = (struct ieee80211_mgmt *) nskb->data; | ||
769 | if (ieee80211_is_beacon(mgmt->frame_control) || | ||
770 | ieee80211_is_probe_resp(mgmt->frame_control)) | ||
771 | mgmt->u.beacon.timestamp = cpu_to_le64( | ||
772 | rx_status.mactime + | ||
773 | (data->tsf_offset - data2->tsf_offset) + | ||
774 | 24 * 8 * 10 / txrate->bitrate); | ||
775 | |||
776 | #if 0 | 809 | #if 0 |
777 | /* | 810 | /* |
778 | * Don't enable this code by default as the OUI 00:00:00 | 811 | * Don't enable this code by default as the OUI 00:00:00 |
@@ -896,7 +929,7 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw) | |||
896 | { | 929 | { |
897 | struct mac80211_hwsim_data *data = hw->priv; | 930 | struct mac80211_hwsim_data *data = hw->priv; |
898 | data->started = false; | 931 | data->started = false; |
899 | del_timer(&data->beacon_timer); | 932 | tasklet_hrtimer_cancel(&data->beacon_timer); |
900 | wiphy_debug(hw->wiphy, "%s\n", __func__); | 933 | wiphy_debug(hw->wiphy, "%s\n", __func__); |
901 | } | 934 | } |
902 | 935 | ||
@@ -962,7 +995,11 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | |||
962 | static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | 995 | static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, |
963 | struct ieee80211_vif *vif) | 996 | struct ieee80211_vif *vif) |
964 | { | 997 | { |
965 | struct ieee80211_hw *hw = arg; | 998 | struct mac80211_hwsim_data *data = arg; |
999 | struct ieee80211_hw *hw = data->hw; | ||
1000 | struct ieee80211_tx_info *info; | ||
1001 | struct ieee80211_rate *txrate; | ||
1002 | struct ieee80211_mgmt *mgmt; | ||
966 | struct sk_buff *skb; | 1003 | struct sk_buff *skb; |
967 | 1004 | ||
968 | hwsim_check_magic(vif); | 1005 | hwsim_check_magic(vif); |
@@ -975,26 +1012,48 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
975 | skb = ieee80211_beacon_get(hw, vif); | 1012 | skb = ieee80211_beacon_get(hw, vif); |
976 | if (skb == NULL) | 1013 | if (skb == NULL) |
977 | return; | 1014 | return; |
1015 | info = IEEE80211_SKB_CB(skb); | ||
1016 | txrate = ieee80211_get_tx_rate(hw, info); | ||
1017 | |||
1018 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
1019 | /* fake header transmission time */ | ||
1020 | data->abs_bcn_ts = mac80211_hwsim_get_tsf_raw(); | ||
1021 | mgmt->u.beacon.timestamp = cpu_to_le64(data->abs_bcn_ts + | ||
1022 | data->tsf_offset + | ||
1023 | 24 * 8 * 10 / txrate->bitrate); | ||
978 | 1024 | ||
979 | mac80211_hwsim_tx_frame(hw, skb, | 1025 | mac80211_hwsim_tx_frame(hw, skb, |
980 | rcu_dereference(vif->chanctx_conf)->def.chan); | 1026 | rcu_dereference(vif->chanctx_conf)->def.chan); |
981 | } | 1027 | } |
982 | 1028 | ||
983 | 1029 | static enum hrtimer_restart | |
984 | static void mac80211_hwsim_beacon(unsigned long arg) | 1030 | mac80211_hwsim_beacon(struct hrtimer *timer) |
985 | { | 1031 | { |
986 | struct ieee80211_hw *hw = (struct ieee80211_hw *) arg; | 1032 | struct mac80211_hwsim_data *data = |
987 | struct mac80211_hwsim_data *data = hw->priv; | 1033 | container_of(timer, struct mac80211_hwsim_data, |
1034 | beacon_timer.timer); | ||
1035 | struct ieee80211_hw *hw = data->hw; | ||
1036 | u64 bcn_int = data->beacon_int; | ||
1037 | ktime_t next_bcn; | ||
988 | 1038 | ||
989 | if (!data->started) | 1039 | if (!data->started) |
990 | return; | 1040 | goto out; |
991 | 1041 | ||
992 | ieee80211_iterate_active_interfaces_atomic( | 1042 | ieee80211_iterate_active_interfaces_atomic( |
993 | hw, IEEE80211_IFACE_ITER_NORMAL, | 1043 | hw, IEEE80211_IFACE_ITER_NORMAL, |
994 | mac80211_hwsim_beacon_tx, hw); | 1044 | mac80211_hwsim_beacon_tx, data); |
1045 | |||
1046 | /* beacon at new TBTT + beacon interval */ | ||
1047 | if (data->bcn_delta) { | ||
1048 | bcn_int -= data->bcn_delta; | ||
1049 | data->bcn_delta = 0; | ||
1050 | } | ||
995 | 1051 | ||
996 | data->beacon_timer.expires = jiffies + data->beacon_int; | 1052 | next_bcn = ktime_add(hrtimer_get_expires(timer), |
997 | add_timer(&data->beacon_timer); | 1053 | ns_to_ktime(bcn_int * 1000)); |
1054 | tasklet_hrtimer_start(&data->beacon_timer, next_bcn, HRTIMER_MODE_ABS); | ||
1055 | out: | ||
1056 | return HRTIMER_NORESTART; | ||
998 | } | 1057 | } |
999 | 1058 | ||
1000 | static const char *hwsim_chantypes[] = { | 1059 | static const char *hwsim_chantypes[] = { |
@@ -1032,9 +1091,16 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) | |||
1032 | 1091 | ||
1033 | data->power_level = conf->power_level; | 1092 | data->power_level = conf->power_level; |
1034 | if (!data->started || !data->beacon_int) | 1093 | if (!data->started || !data->beacon_int) |
1035 | del_timer(&data->beacon_timer); | 1094 | tasklet_hrtimer_cancel(&data->beacon_timer); |
1036 | else | 1095 | else if (!hrtimer_is_queued(&data->beacon_timer.timer)) { |
1037 | mod_timer(&data->beacon_timer, jiffies + data->beacon_int); | 1096 | u64 tsf = mac80211_hwsim_get_tsf(hw, NULL); |
1097 | u32 bcn_int = data->beacon_int; | ||
1098 | u64 until_tbtt = bcn_int - do_div(tsf, bcn_int); | ||
1099 | |||
1100 | tasklet_hrtimer_start(&data->beacon_timer, | ||
1101 | ns_to_ktime(until_tbtt * 1000), | ||
1102 | HRTIMER_MODE_REL); | ||
1103 | } | ||
1038 | 1104 | ||
1039 | return 0; | 1105 | return 0; |
1040 | } | 1106 | } |
@@ -1084,12 +1150,26 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
1084 | 1150 | ||
1085 | if (changed & BSS_CHANGED_BEACON_INT) { | 1151 | if (changed & BSS_CHANGED_BEACON_INT) { |
1086 | wiphy_debug(hw->wiphy, " BCNINT: %d\n", info->beacon_int); | 1152 | wiphy_debug(hw->wiphy, " BCNINT: %d\n", info->beacon_int); |
1087 | data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000; | 1153 | data->beacon_int = info->beacon_int * 1024; |
1088 | if (WARN_ON(!data->beacon_int)) | 1154 | } |
1089 | data->beacon_int = 1; | 1155 | |
1090 | if (data->started) | 1156 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
1091 | mod_timer(&data->beacon_timer, | 1157 | wiphy_debug(hw->wiphy, " BCN EN: %d\n", info->enable_beacon); |
1092 | jiffies + data->beacon_int); | 1158 | if (data->started && |
1159 | !hrtimer_is_queued(&data->beacon_timer.timer) && | ||
1160 | info->enable_beacon) { | ||
1161 | u64 tsf, until_tbtt; | ||
1162 | u32 bcn_int; | ||
1163 | if (WARN_ON(!data->beacon_int)) | ||
1164 | data->beacon_int = 1000 * 1024; | ||
1165 | tsf = mac80211_hwsim_get_tsf(hw, vif); | ||
1166 | bcn_int = data->beacon_int; | ||
1167 | until_tbtt = bcn_int - do_div(tsf, bcn_int); | ||
1168 | tasklet_hrtimer_start(&data->beacon_timer, | ||
1169 | ns_to_ktime(until_tbtt * 1000), | ||
1170 | HRTIMER_MODE_REL); | ||
1171 | } else if (!info->enable_beacon) | ||
1172 | tasklet_hrtimer_cancel(&data->beacon_timer); | ||
1093 | } | 1173 | } |
1094 | 1174 | ||
1095 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 1175 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { |
@@ -1292,7 +1372,9 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, | |||
1292 | case IEEE80211_AMPDU_TX_START: | 1372 | case IEEE80211_AMPDU_TX_START: |
1293 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1373 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1294 | break; | 1374 | break; |
1295 | case IEEE80211_AMPDU_TX_STOP: | 1375 | case IEEE80211_AMPDU_TX_STOP_CONT: |
1376 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
1377 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
1296 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1378 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1297 | break; | 1379 | break; |
1298 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 1380 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
@@ -2370,8 +2452,9 @@ static int __init init_mac80211_hwsim(void) | |||
2370 | data->debugfs, data, | 2452 | data->debugfs, data, |
2371 | &hwsim_fops_group); | 2453 | &hwsim_fops_group); |
2372 | 2454 | ||
2373 | setup_timer(&data->beacon_timer, mac80211_hwsim_beacon, | 2455 | tasklet_hrtimer_init(&data->beacon_timer, |
2374 | (unsigned long) hw); | 2456 | mac80211_hwsim_beacon, |
2457 | CLOCK_REALTIME, HRTIMER_MODE_ABS); | ||
2375 | 2458 | ||
2376 | list_add_tail(&data->list, &hwsim_radios); | 2459 | list_add_tail(&data->list, &hwsim_radios); |
2377 | } | 2460 | } |
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 245a371f1a43..9cd6216c61e6 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -53,7 +53,9 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, | |||
53 | sizeof(sband->ht_cap.mcs)); | 53 | sizeof(sband->ht_cap.mcs)); |
54 | 54 | ||
55 | if (priv->bss_mode == NL80211_IFTYPE_STATION || | 55 | if (priv->bss_mode == NL80211_IFTYPE_STATION || |
56 | sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | 56 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && |
57 | (priv->adapter->sec_chan_offset != | ||
58 | IEEE80211_HT_PARAM_CHA_SEC_NONE))) | ||
57 | /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ | 59 | /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ |
58 | SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); | 60 | SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); |
59 | 61 | ||
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 68d52cfc1ebd..af8fe6352eed 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c | |||
@@ -278,14 +278,16 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
278 | dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); | 278 | dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); |
279 | break; | 279 | break; |
280 | case -1: | 280 | case -1: |
281 | adapter->data_sent = false; | 281 | if (adapter->iface_type != MWIFIEX_PCIE) |
282 | adapter->data_sent = false; | ||
282 | dev_err(adapter->dev, "%s: host_to_card failed: %#x\n", | 283 | dev_err(adapter->dev, "%s: host_to_card failed: %#x\n", |
283 | __func__, ret); | 284 | __func__, ret); |
284 | adapter->dbg.num_tx_host_to_card_failure++; | 285 | adapter->dbg.num_tx_host_to_card_failure++; |
285 | mwifiex_write_data_complete(adapter, skb_aggr, 1, ret); | 286 | mwifiex_write_data_complete(adapter, skb_aggr, 1, ret); |
286 | return 0; | 287 | return 0; |
287 | case -EINPROGRESS: | 288 | case -EINPROGRESS: |
288 | adapter->data_sent = false; | 289 | if (adapter->iface_type != MWIFIEX_PCIE) |
290 | adapter->data_sent = false; | ||
289 | break; | 291 | break; |
290 | case 0: | 292 | case 0: |
291 | mwifiex_write_data_complete(adapter, skb_aggr, 1, ret); | 293 | mwifiex_write_data_complete(adapter, skb_aggr, 1, ret); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index ad3baa7e7982..ab92e799cf75 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -519,8 +519,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) | |||
519 | * - Set by user | 519 | * - Set by user |
520 | * - Set bt Country IE | 520 | * - Set bt Country IE |
521 | */ | 521 | */ |
522 | static int mwifiex_reg_notifier(struct wiphy *wiphy, | 522 | static void mwifiex_reg_notifier(struct wiphy *wiphy, |
523 | struct regulatory_request *request) | 523 | struct regulatory_request *request) |
524 | { | 524 | { |
525 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | 525 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
526 | 526 | ||
@@ -540,8 +540,6 @@ static int mwifiex_reg_notifier(struct wiphy *wiphy, | |||
540 | break; | 540 | break; |
541 | } | 541 | } |
542 | mwifiex_send_domain_info_cmd_fw(wiphy); | 542 | mwifiex_send_domain_info_cmd_fw(wiphy); |
543 | |||
544 | return 0; | ||
545 | } | 543 | } |
546 | 544 | ||
547 | /* | 545 | /* |
@@ -1327,6 +1325,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1327 | } | 1325 | } |
1328 | 1326 | ||
1329 | mwifiex_set_ht_params(priv, bss_cfg, params); | 1327 | mwifiex_set_ht_params(priv, bss_cfg, params); |
1328 | mwifiex_set_wmm_params(priv, bss_cfg, params); | ||
1330 | 1329 | ||
1331 | if (params->inactivity_timeout > 0) { | 1330 | if (params->inactivity_timeout > 0) { |
1332 | /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */ | 1331 | /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */ |
@@ -1459,7 +1458,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | |||
1459 | struct cfg80211_ssid req_ssid; | 1458 | struct cfg80211_ssid req_ssid; |
1460 | int ret, auth_type = 0; | 1459 | int ret, auth_type = 0; |
1461 | struct cfg80211_bss *bss = NULL; | 1460 | struct cfg80211_bss *bss = NULL; |
1462 | u8 is_scanning_required = 0, config_bands = 0; | 1461 | u8 is_scanning_required = 0; |
1463 | 1462 | ||
1464 | memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); | 1463 | memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); |
1465 | 1464 | ||
@@ -1478,19 +1477,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | |||
1478 | /* disconnect before try to associate */ | 1477 | /* disconnect before try to associate */ |
1479 | mwifiex_deauthenticate(priv, NULL); | 1478 | mwifiex_deauthenticate(priv, NULL); |
1480 | 1479 | ||
1481 | if (channel) { | ||
1482 | if (mode == NL80211_IFTYPE_STATION) { | ||
1483 | if (channel->band == IEEE80211_BAND_2GHZ) | ||
1484 | config_bands = BAND_B | BAND_G | BAND_GN; | ||
1485 | else | ||
1486 | config_bands = BAND_A | BAND_AN; | ||
1487 | |||
1488 | if (!((config_bands | priv->adapter->fw_bands) & | ||
1489 | ~priv->adapter->fw_bands)) | ||
1490 | priv->adapter->config_bands = config_bands; | ||
1491 | } | ||
1492 | } | ||
1493 | |||
1494 | /* As this is new association, clear locally stored | 1480 | /* As this is new association, clear locally stored |
1495 | * keys and security related flags */ | 1481 | * keys and security related flags */ |
1496 | priv->sec_info.wpa_enabled = false; | 1482 | priv->sec_info.wpa_enabled = false; |
@@ -1707,7 +1693,7 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, | |||
1707 | 1693 | ||
1708 | if (cfg80211_get_chandef_type(¶ms->chandef) != | 1694 | if (cfg80211_get_chandef_type(¶ms->chandef) != |
1709 | NL80211_CHAN_NO_HT) | 1695 | NL80211_CHAN_NO_HT) |
1710 | config_bands |= BAND_GN; | 1696 | config_bands |= BAND_G | BAND_GN; |
1711 | } else { | 1697 | } else { |
1712 | if (cfg80211_get_chandef_type(¶ms->chandef) == | 1698 | if (cfg80211_get_chandef_type(¶ms->chandef) == |
1713 | NL80211_CHAN_NO_HT) | 1699 | NL80211_CHAN_NO_HT) |
@@ -2260,6 +2246,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2260 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 2246 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
2261 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | | 2247 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | |
2262 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | | 2248 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | |
2249 | WIPHY_FLAG_AP_UAPSD | | ||
2263 | WIPHY_FLAG_CUSTOM_REGULATORY | | 2250 | WIPHY_FLAG_CUSTOM_REGULATORY | |
2264 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 2251 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
2265 | 2252 | ||
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index e9357d87d327..e8a569aaa2e8 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/wait.h> | 26 | #include <linux/wait.h> |
27 | #include <linux/timer.h> | 27 | #include <linux/timer.h> |
28 | #include <linux/ieee80211.h> | 28 | #include <linux/ieee80211.h> |
29 | #include <net/mac80211.h> | ||
29 | 30 | ||
30 | 31 | ||
31 | #define MWIFIEX_MAX_BSS_NUM (3) | 32 | #define MWIFIEX_MAX_BSS_NUM (3) |
@@ -58,6 +59,8 @@ | |||
58 | #define MWIFIEX_RTS_MAX_VALUE (2347) | 59 | #define MWIFIEX_RTS_MAX_VALUE (2347) |
59 | #define MWIFIEX_FRAG_MIN_VALUE (256) | 60 | #define MWIFIEX_FRAG_MIN_VALUE (256) |
60 | #define MWIFIEX_FRAG_MAX_VALUE (2346) | 61 | #define MWIFIEX_FRAG_MAX_VALUE (2346) |
62 | #define MWIFIEX_WMM_VERSION 0x01 | ||
63 | #define MWIFIEX_WMM_SUBTYPE 0x01 | ||
61 | 64 | ||
62 | #define MWIFIEX_RETRY_LIMIT 14 | 65 | #define MWIFIEX_RETRY_LIMIT 14 |
63 | #define MWIFIEX_SDIO_BLOCK_SIZE 256 | 66 | #define MWIFIEX_SDIO_BLOCK_SIZE 256 |
@@ -126,4 +129,19 @@ enum mwifiex_wmm_ac_e { | |||
126 | WMM_AC_VI, | 129 | WMM_AC_VI, |
127 | WMM_AC_VO | 130 | WMM_AC_VO |
128 | } __packed; | 131 | } __packed; |
132 | |||
133 | struct ieee_types_wmm_ac_parameters { | ||
134 | u8 aci_aifsn_bitmap; | ||
135 | u8 ecw_bitmap; | ||
136 | __le16 tx_op_limit; | ||
137 | } __packed; | ||
138 | |||
139 | struct mwifiex_types_wmm_info { | ||
140 | u8 oui[4]; | ||
141 | u8 subtype; | ||
142 | u8 version; | ||
143 | u8 qos_info; | ||
144 | u8 reserved; | ||
145 | struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS]; | ||
146 | } __packed; | ||
129 | #endif /* !_MWIFIEX_DECL_H_ */ | 147 | #endif /* !_MWIFIEX_DECL_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 4dc8e2e9a889..ebe2f6a7984c 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -330,6 +330,9 @@ enum P2P_MODES { | |||
330 | #define HOST_SLEEP_CFG_GPIO_DEF 0xff | 330 | #define HOST_SLEEP_CFG_GPIO_DEF 0xff |
331 | #define HOST_SLEEP_CFG_GAP_DEF 0 | 331 | #define HOST_SLEEP_CFG_GAP_DEF 0 |
332 | 332 | ||
333 | #define MWIFIEX_TIMEOUT_FOR_AP_RESP 0xfffc | ||
334 | #define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT 2 | ||
335 | |||
333 | #define CMD_F_HOSTCMD (1 << 0) | 336 | #define CMD_F_HOSTCMD (1 << 0) |
334 | #define CMD_F_CANCELED (1 << 1) | 337 | #define CMD_F_CANCELED (1 << 1) |
335 | 338 | ||
@@ -1131,12 +1134,6 @@ struct ieee_types_vendor_header { | |||
1131 | u8 version; | 1134 | u8 version; |
1132 | } __packed; | 1135 | } __packed; |
1133 | 1136 | ||
1134 | struct ieee_types_wmm_ac_parameters { | ||
1135 | u8 aci_aifsn_bitmap; | ||
1136 | u8 ecw_bitmap; | ||
1137 | __le16 tx_op_limit; | ||
1138 | } __packed; | ||
1139 | |||
1140 | struct ieee_types_wmm_parameter { | 1137 | struct ieee_types_wmm_parameter { |
1141 | /* | 1138 | /* |
1142 | * WMM Parameter IE - Vendor Specific Header: | 1139 | * WMM Parameter IE - Vendor Specific Header: |
@@ -1186,6 +1183,11 @@ struct mwifiex_ie_types_htcap { | |||
1186 | struct ieee80211_ht_cap ht_cap; | 1183 | struct ieee80211_ht_cap ht_cap; |
1187 | } __packed; | 1184 | } __packed; |
1188 | 1185 | ||
1186 | struct mwifiex_ie_types_wmmcap { | ||
1187 | struct mwifiex_ie_types_header header; | ||
1188 | struct mwifiex_types_wmm_info wmm_info; | ||
1189 | } __packed; | ||
1190 | |||
1189 | struct mwifiex_ie_types_htinfo { | 1191 | struct mwifiex_ie_types_htinfo { |
1190 | struct mwifiex_ie_types_header header; | 1192 | struct mwifiex_ie_types_header header; |
1191 | struct ieee80211_ht_operation ht_oper; | 1193 | struct ieee80211_ht_operation ht_oper; |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 39f03ce5a5b1..e00b8060aff7 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -591,6 +591,12 @@ int mwifiex_init_fw(struct mwifiex_adapter *adapter) | |||
591 | return -1; | 591 | return -1; |
592 | } | 592 | } |
593 | } | 593 | } |
594 | |||
595 | if (adapter->if_ops.init_fw_port) { | ||
596 | if (adapter->if_ops.init_fw_port(adapter)) | ||
597 | return -1; | ||
598 | } | ||
599 | |||
594 | for (i = 0; i < adapter->priv_num; i++) { | 600 | for (i = 0; i < adapter->priv_num; i++) { |
595 | if (adapter->priv[i]) { | 601 | if (adapter->priv[i]) { |
596 | ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta); | 602 | ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta); |
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 4e31c6013ebe..6095b3e53f4e 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -20,7 +20,6 @@ | |||
20 | #ifndef _MWIFIEX_IOCTL_H_ | 20 | #ifndef _MWIFIEX_IOCTL_H_ |
21 | #define _MWIFIEX_IOCTL_H_ | 21 | #define _MWIFIEX_IOCTL_H_ |
22 | 22 | ||
23 | #include <net/mac80211.h> | ||
24 | #include <net/lib80211.h> | 23 | #include <net/lib80211.h> |
25 | 24 | ||
26 | enum { | 25 | enum { |
@@ -107,6 +106,8 @@ struct mwifiex_uap_bss_param { | |||
107 | u8 rates[MWIFIEX_SUPPORTED_RATES]; | 106 | u8 rates[MWIFIEX_SUPPORTED_RATES]; |
108 | u32 sta_ao_timer; | 107 | u32 sta_ao_timer; |
109 | u32 ps_sta_ao_timer; | 108 | u32 ps_sta_ao_timer; |
109 | u8 qos_info; | ||
110 | struct mwifiex_types_wmm_info wmm_info; | ||
110 | }; | 111 | }; |
111 | 112 | ||
112 | enum { | 113 | enum { |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 88664ae667ba..893d809ba83c 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -615,23 +615,33 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, | |||
615 | struct ieee_types_assoc_rsp *assoc_rsp; | 615 | struct ieee_types_assoc_rsp *assoc_rsp; |
616 | struct mwifiex_bssdescriptor *bss_desc; | 616 | struct mwifiex_bssdescriptor *bss_desc; |
617 | u8 enable_data = true; | 617 | u8 enable_data = true; |
618 | u16 cap_info, status_code; | ||
618 | 619 | ||
619 | assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; | 620 | assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; |
620 | 621 | ||
622 | cap_info = le16_to_cpu(assoc_rsp->cap_info_bitmap); | ||
623 | status_code = le16_to_cpu(assoc_rsp->status_code); | ||
624 | |||
621 | priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN, | 625 | priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN, |
622 | sizeof(priv->assoc_rsp_buf)); | 626 | sizeof(priv->assoc_rsp_buf)); |
623 | 627 | ||
624 | memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); | 628 | memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); |
625 | 629 | ||
626 | if (le16_to_cpu(assoc_rsp->status_code)) { | 630 | if (status_code) { |
627 | priv->adapter->dbg.num_cmd_assoc_failure++; | 631 | priv->adapter->dbg.num_cmd_assoc_failure++; |
628 | dev_err(priv->adapter->dev, | 632 | dev_err(priv->adapter->dev, |
629 | "ASSOC_RESP: failed, status code=%d err=%#x a_id=%#x\n", | 633 | "ASSOC_RESP: failed, status code=%d err=%#x a_id=%#x\n", |
630 | le16_to_cpu(assoc_rsp->status_code), | 634 | status_code, cap_info, le16_to_cpu(assoc_rsp->a_id)); |
631 | le16_to_cpu(assoc_rsp->cap_info_bitmap), | 635 | |
632 | le16_to_cpu(assoc_rsp->a_id)); | 636 | if (cap_info == MWIFIEX_TIMEOUT_FOR_AP_RESP) { |
637 | if (status_code == MWIFIEX_STATUS_CODE_AUTH_TIMEOUT) | ||
638 | ret = WLAN_STATUS_AUTH_TIMEOUT; | ||
639 | else | ||
640 | ret = WLAN_STATUS_UNSPECIFIED_FAILURE; | ||
641 | } else { | ||
642 | ret = status_code; | ||
643 | } | ||
633 | 644 | ||
634 | ret = le16_to_cpu(assoc_rsp->status_code); | ||
635 | goto done; | 645 | goto done; |
636 | } | 646 | } |
637 | 647 | ||
@@ -969,6 +979,16 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, | |||
969 | priv->adapter->config_bands); | 979 | priv->adapter->config_bands); |
970 | mwifiex_fill_cap_info(priv, radio_type, ht_cap); | 980 | mwifiex_fill_cap_info(priv, radio_type, ht_cap); |
971 | 981 | ||
982 | if (adapter->sec_chan_offset == | ||
983 | IEEE80211_HT_PARAM_CHA_SEC_NONE) { | ||
984 | u16 tmp_ht_cap; | ||
985 | |||
986 | tmp_ht_cap = le16_to_cpu(ht_cap->ht_cap.cap_info); | ||
987 | tmp_ht_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
988 | tmp_ht_cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
989 | ht_cap->ht_cap.cap_info = cpu_to_le16(tmp_ht_cap); | ||
990 | } | ||
991 | |||
972 | pos += sizeof(struct mwifiex_ie_types_htcap); | 992 | pos += sizeof(struct mwifiex_ie_types_htcap); |
973 | cmd_append_size += sizeof(struct mwifiex_ie_types_htcap); | 993 | cmd_append_size += sizeof(struct mwifiex_ie_types_htcap); |
974 | 994 | ||
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 1b3cfc821940..51044e3ea89b 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -599,8 +599,10 @@ struct mwifiex_if_ops { | |||
599 | int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *); | 599 | int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *); |
600 | int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *); | 600 | int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *); |
601 | int (*data_complete) (struct mwifiex_adapter *, struct sk_buff *); | 601 | int (*data_complete) (struct mwifiex_adapter *, struct sk_buff *); |
602 | int (*init_fw_port) (struct mwifiex_adapter *); | ||
602 | int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); | 603 | int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); |
603 | void (*card_reset) (struct mwifiex_adapter *); | 604 | void (*card_reset) (struct mwifiex_adapter *); |
605 | int (*clean_pcie_ring) (struct mwifiex_adapter *adapter); | ||
604 | }; | 606 | }; |
605 | 607 | ||
606 | struct mwifiex_adapter { | 608 | struct mwifiex_adapter { |
@@ -890,6 +892,10 @@ void mwifiex_set_ht_params(struct mwifiex_private *priv, | |||
890 | struct cfg80211_ap_settings *params); | 892 | struct cfg80211_ap_settings *params); |
891 | void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, | 893 | void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, |
892 | struct cfg80211_ap_settings *params); | 894 | struct cfg80211_ap_settings *params); |
895 | void | ||
896 | mwifiex_set_wmm_params(struct mwifiex_private *priv, | ||
897 | struct mwifiex_uap_bss_param *bss_cfg, | ||
898 | struct cfg80211_ap_settings *params); | ||
893 | 899 | ||
894 | /* | 900 | /* |
895 | * This function checks if the queuing is RA based or not. | 901 | * This function checks if the queuing is RA based or not. |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 13fbc4eb1595..237949c070cc 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -39,17 +39,20 @@ static struct semaphore add_remove_card_sem; | |||
39 | static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter); | 39 | static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter); |
40 | static int mwifiex_pcie_resume(struct pci_dev *pdev); | 40 | static int mwifiex_pcie_resume(struct pci_dev *pdev); |
41 | 41 | ||
42 | /* | 42 | static int |
43 | * This function is called after skb allocation to update | 43 | mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, |
44 | * "skb->cb" with physical address of data pointer. | 44 | int size, int flags) |
45 | */ | ||
46 | static phys_addr_t *mwifiex_update_sk_buff_pa(struct sk_buff *skb) | ||
47 | { | 45 | { |
48 | phys_addr_t *buf_pa = MWIFIEX_SKB_PACB(skb); | 46 | struct pcie_service_card *card = adapter->card; |
49 | 47 | dma_addr_t buf_pa; | |
50 | *buf_pa = (phys_addr_t)virt_to_phys(skb->data); | ||
51 | 48 | ||
52 | return buf_pa; | 49 | buf_pa = pci_map_single(card->dev, skb->data, size, flags); |
50 | if (pci_dma_mapping_error(card->dev, buf_pa)) { | ||
51 | dev_err(adapter->dev, "failed to map pci memory!\n"); | ||
52 | return -1; | ||
53 | } | ||
54 | memcpy(skb->cb, &buf_pa, sizeof(dma_addr_t)); | ||
55 | return 0; | ||
53 | } | 56 | } |
54 | 57 | ||
55 | /* | 58 | /* |
@@ -60,8 +63,8 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter) | |||
60 | u32 *cookie_addr; | 63 | u32 *cookie_addr; |
61 | struct pcie_service_card *card = adapter->card; | 64 | struct pcie_service_card *card = adapter->card; |
62 | 65 | ||
63 | if (card->sleep_cookie) { | 66 | if (card->sleep_cookie_vbase) { |
64 | cookie_addr = (u32 *)card->sleep_cookie->data; | 67 | cookie_addr = (u32 *)card->sleep_cookie_vbase; |
65 | dev_dbg(adapter->dev, "info: ACCESS_HW: sleep cookie=0x%x\n", | 68 | dev_dbg(adapter->dev, "info: ACCESS_HW: sleep cookie=0x%x\n", |
66 | *cookie_addr); | 69 | *cookie_addr); |
67 | if (*cookie_addr == FW_AWAKE_COOKIE) | 70 | if (*cookie_addr == FW_AWAKE_COOKIE) |
@@ -161,7 +164,7 @@ static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) | |||
161 | 164 | ||
162 | if (pdev) { | 165 | if (pdev) { |
163 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | 166 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); |
164 | if (!card || card->adapter) { | 167 | if (!card || !card->adapter) { |
165 | pr_err("Card or adapter structure is not valid\n"); | 168 | pr_err("Card or adapter structure is not valid\n"); |
166 | return 0; | 169 | return 0; |
167 | } | 170 | } |
@@ -366,9 +369,7 @@ static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter) | |||
366 | static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter) | 369 | static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter) |
367 | { | 370 | { |
368 | struct pcie_service_card *card = adapter->card; | 371 | struct pcie_service_card *card = adapter->card; |
369 | struct sk_buff *skb; | ||
370 | int i; | 372 | int i; |
371 | phys_addr_t *buf_pa; | ||
372 | 373 | ||
373 | /* | 374 | /* |
374 | * driver maintaines the write pointer and firmware maintaines the read | 375 | * driver maintaines the write pointer and firmware maintaines the read |
@@ -384,16 +385,18 @@ static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter) | |||
384 | MWIFIEX_MAX_TXRX_BD; | 385 | MWIFIEX_MAX_TXRX_BD; |
385 | dev_dbg(adapter->dev, "info: txbd_ring: Allocating %d bytes\n", | 386 | dev_dbg(adapter->dev, "info: txbd_ring: Allocating %d bytes\n", |
386 | card->txbd_ring_size); | 387 | card->txbd_ring_size); |
387 | card->txbd_ring_vbase = kzalloc(card->txbd_ring_size, GFP_KERNEL); | 388 | card->txbd_ring_vbase = pci_alloc_consistent(card->dev, |
389 | card->txbd_ring_size, | ||
390 | &card->txbd_ring_pbase); | ||
388 | if (!card->txbd_ring_vbase) { | 391 | if (!card->txbd_ring_vbase) { |
389 | dev_err(adapter->dev, "Unable to alloc buffer for txbd ring\n"); | 392 | dev_err(adapter->dev, |
393 | "allocate consistent memory (%d bytes) failed!\n", | ||
394 | card->txbd_ring_size); | ||
390 | return -ENOMEM; | 395 | return -ENOMEM; |
391 | } | 396 | } |
392 | card->txbd_ring_pbase = virt_to_phys(card->txbd_ring_vbase); | ||
393 | |||
394 | dev_dbg(adapter->dev, | 397 | dev_dbg(adapter->dev, |
395 | "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n", | 398 | "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n", |
396 | card->txbd_ring_vbase, (u32)card->txbd_ring_pbase, | 399 | card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase, |
397 | (u32)((u64)card->txbd_ring_pbase >> 32), card->txbd_ring_size); | 400 | (u32)((u64)card->txbd_ring_pbase >> 32), card->txbd_ring_size); |
398 | 401 | ||
399 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { | 402 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { |
@@ -402,24 +405,9 @@ static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter) | |||
402 | (sizeof(struct mwifiex_pcie_buf_desc) | 405 | (sizeof(struct mwifiex_pcie_buf_desc) |
403 | * i)); | 406 | * i)); |
404 | 407 | ||
405 | /* Allocate buffer here so that firmware can DMA data from it */ | 408 | card->tx_buf_list[i] = NULL; |
406 | skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE); | 409 | card->txbd_ring[i]->paddr = 0; |
407 | if (!skb) { | 410 | card->txbd_ring[i]->len = 0; |
408 | dev_err(adapter->dev, "Unable to allocate skb for TX ring.\n"); | ||
409 | kfree(card->txbd_ring_vbase); | ||
410 | return -ENOMEM; | ||
411 | } | ||
412 | buf_pa = mwifiex_update_sk_buff_pa(skb); | ||
413 | |||
414 | skb_put(skb, MWIFIEX_RX_DATA_BUF_SIZE); | ||
415 | dev_dbg(adapter->dev, "info: TX ring: add new skb base: %p, " | ||
416 | "buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n", | ||
417 | skb, skb->data, (u32)*buf_pa, | ||
418 | (u32)(((u64)*buf_pa >> 32)), skb->len); | ||
419 | |||
420 | card->tx_buf_list[i] = skb; | ||
421 | card->txbd_ring[i]->paddr = *buf_pa; | ||
422 | card->txbd_ring[i]->len = (u16)skb->len; | ||
423 | card->txbd_ring[i]->flags = 0; | 411 | card->txbd_ring[i]->flags = 0; |
424 | } | 412 | } |
425 | 413 | ||
@@ -429,11 +417,16 @@ static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter) | |||
429 | static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter) | 417 | static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter) |
430 | { | 418 | { |
431 | struct pcie_service_card *card = adapter->card; | 419 | struct pcie_service_card *card = adapter->card; |
420 | struct sk_buff *skb; | ||
432 | int i; | 421 | int i; |
433 | 422 | ||
434 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { | 423 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { |
435 | if (card->tx_buf_list[i]) | 424 | if (card->tx_buf_list[i]) { |
436 | dev_kfree_skb_any(card->tx_buf_list[i]); | 425 | skb = card->tx_buf_list[i]; |
426 | pci_unmap_single(card->dev, card->txbd_ring[i]->paddr, | ||
427 | skb->len, PCI_DMA_TODEVICE); | ||
428 | dev_kfree_skb_any(skb); | ||
429 | } | ||
437 | card->tx_buf_list[i] = NULL; | 430 | card->tx_buf_list[i] = NULL; |
438 | card->txbd_ring[i]->paddr = 0; | 431 | card->txbd_ring[i]->paddr = 0; |
439 | card->txbd_ring[i]->len = 0; | 432 | card->txbd_ring[i]->len = 0; |
@@ -441,11 +434,15 @@ static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter) | |||
441 | card->txbd_ring[i] = NULL; | 434 | card->txbd_ring[i] = NULL; |
442 | } | 435 | } |
443 | 436 | ||
444 | kfree(card->txbd_ring_vbase); | 437 | if (card->txbd_ring_vbase) |
438 | pci_free_consistent(card->dev, card->txbd_ring_size, | ||
439 | card->txbd_ring_vbase, | ||
440 | card->txbd_ring_pbase); | ||
445 | card->txbd_ring_size = 0; | 441 | card->txbd_ring_size = 0; |
446 | card->txbd_wrptr = 0; | 442 | card->txbd_wrptr = 0; |
447 | card->txbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; | 443 | card->txbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; |
448 | card->txbd_ring_vbase = NULL; | 444 | card->txbd_ring_vbase = NULL; |
445 | card->txbd_ring_pbase = 0; | ||
449 | 446 | ||
450 | return 0; | 447 | return 0; |
451 | } | 448 | } |
@@ -458,7 +455,7 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) | |||
458 | struct pcie_service_card *card = adapter->card; | 455 | struct pcie_service_card *card = adapter->card; |
459 | struct sk_buff *skb; | 456 | struct sk_buff *skb; |
460 | int i; | 457 | int i; |
461 | phys_addr_t *buf_pa; | 458 | dma_addr_t buf_pa; |
462 | 459 | ||
463 | /* | 460 | /* |
464 | * driver maintaines the read pointer and firmware maintaines the write | 461 | * driver maintaines the read pointer and firmware maintaines the write |
@@ -472,13 +469,15 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) | |||
472 | MWIFIEX_MAX_TXRX_BD; | 469 | MWIFIEX_MAX_TXRX_BD; |
473 | dev_dbg(adapter->dev, "info: rxbd_ring: Allocating %d bytes\n", | 470 | dev_dbg(adapter->dev, "info: rxbd_ring: Allocating %d bytes\n", |
474 | card->rxbd_ring_size); | 471 | card->rxbd_ring_size); |
475 | card->rxbd_ring_vbase = kzalloc(card->rxbd_ring_size, GFP_KERNEL); | 472 | card->rxbd_ring_vbase = pci_alloc_consistent(card->dev, |
473 | card->rxbd_ring_size, | ||
474 | &card->rxbd_ring_pbase); | ||
476 | if (!card->rxbd_ring_vbase) { | 475 | if (!card->rxbd_ring_vbase) { |
477 | dev_err(adapter->dev, "Unable to allocate buffer for " | 476 | dev_err(adapter->dev, |
478 | "rxbd_ring.\n"); | 477 | "allocate consistent memory (%d bytes) failed!\n", |
478 | card->rxbd_ring_size); | ||
479 | return -ENOMEM; | 479 | return -ENOMEM; |
480 | } | 480 | } |
481 | card->rxbd_ring_pbase = virt_to_phys(card->rxbd_ring_vbase); | ||
482 | 481 | ||
483 | dev_dbg(adapter->dev, | 482 | dev_dbg(adapter->dev, |
484 | "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n", | 483 | "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n", |
@@ -500,16 +499,20 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) | |||
500 | kfree(card->rxbd_ring_vbase); | 499 | kfree(card->rxbd_ring_vbase); |
501 | return -ENOMEM; | 500 | return -ENOMEM; |
502 | } | 501 | } |
503 | buf_pa = mwifiex_update_sk_buff_pa(skb); | 502 | if (mwifiex_map_pci_memory(adapter, skb, |
504 | skb_put(skb, MWIFIEX_RX_DATA_BUF_SIZE); | 503 | MWIFIEX_RX_DATA_BUF_SIZE, |
504 | PCI_DMA_FROMDEVICE)) | ||
505 | return -1; | ||
506 | |||
507 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
505 | 508 | ||
506 | dev_dbg(adapter->dev, "info: RX ring: add new skb base: %p, " | 509 | dev_dbg(adapter->dev, "info: RX ring: add new skb base: %p, " |
507 | "buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n", | 510 | "buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n", |
508 | skb, skb->data, (u32)*buf_pa, (u32)((u64)*buf_pa >> 32), | 511 | skb, skb->data, (u32)buf_pa, (u32)((u64)buf_pa >> 32), |
509 | skb->len); | 512 | skb->len); |
510 | 513 | ||
511 | card->rx_buf_list[i] = skb; | 514 | card->rx_buf_list[i] = skb; |
512 | card->rxbd_ring[i]->paddr = *buf_pa; | 515 | card->rxbd_ring[i]->paddr = buf_pa; |
513 | card->rxbd_ring[i]->len = (u16)skb->len; | 516 | card->rxbd_ring[i]->len = (u16)skb->len; |
514 | card->rxbd_ring[i]->flags = 0; | 517 | card->rxbd_ring[i]->flags = 0; |
515 | } | 518 | } |
@@ -523,11 +526,17 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) | |||
523 | static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter) | 526 | static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter) |
524 | { | 527 | { |
525 | struct pcie_service_card *card = adapter->card; | 528 | struct pcie_service_card *card = adapter->card; |
529 | struct sk_buff *skb; | ||
526 | int i; | 530 | int i; |
527 | 531 | ||
528 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { | 532 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { |
529 | if (card->rx_buf_list[i]) | 533 | if (card->rx_buf_list[i]) { |
530 | dev_kfree_skb_any(card->rx_buf_list[i]); | 534 | skb = card->rx_buf_list[i]; |
535 | pci_unmap_single(card->dev, card->rxbd_ring[i]->paddr , | ||
536 | MWIFIEX_RX_DATA_BUF_SIZE, | ||
537 | PCI_DMA_FROMDEVICE); | ||
538 | dev_kfree_skb_any(skb); | ||
539 | } | ||
531 | card->rx_buf_list[i] = NULL; | 540 | card->rx_buf_list[i] = NULL; |
532 | card->rxbd_ring[i]->paddr = 0; | 541 | card->rxbd_ring[i]->paddr = 0; |
533 | card->rxbd_ring[i]->len = 0; | 542 | card->rxbd_ring[i]->len = 0; |
@@ -535,11 +544,15 @@ static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter) | |||
535 | card->rxbd_ring[i] = NULL; | 544 | card->rxbd_ring[i] = NULL; |
536 | } | 545 | } |
537 | 546 | ||
538 | kfree(card->rxbd_ring_vbase); | 547 | if (card->rxbd_ring_vbase) |
548 | pci_free_consistent(card->dev, card->rxbd_ring_size, | ||
549 | card->rxbd_ring_vbase, | ||
550 | card->rxbd_ring_pbase); | ||
539 | card->rxbd_ring_size = 0; | 551 | card->rxbd_ring_size = 0; |
540 | card->rxbd_wrptr = 0; | 552 | card->rxbd_wrptr = 0; |
541 | card->rxbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; | 553 | card->rxbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; |
542 | card->rxbd_ring_vbase = NULL; | 554 | card->rxbd_ring_vbase = NULL; |
555 | card->rxbd_ring_pbase = 0; | ||
543 | 556 | ||
544 | return 0; | 557 | return 0; |
545 | } | 558 | } |
@@ -552,7 +565,7 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) | |||
552 | struct pcie_service_card *card = adapter->card; | 565 | struct pcie_service_card *card = adapter->card; |
553 | struct sk_buff *skb; | 566 | struct sk_buff *skb; |
554 | int i; | 567 | int i; |
555 | phys_addr_t *buf_pa; | 568 | dma_addr_t buf_pa; |
556 | 569 | ||
557 | /* | 570 | /* |
558 | * driver maintaines the read pointer and firmware maintaines the write | 571 | * driver maintaines the read pointer and firmware maintaines the write |
@@ -566,13 +579,15 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) | |||
566 | MWIFIEX_MAX_EVT_BD; | 579 | MWIFIEX_MAX_EVT_BD; |
567 | dev_dbg(adapter->dev, "info: evtbd_ring: Allocating %d bytes\n", | 580 | dev_dbg(adapter->dev, "info: evtbd_ring: Allocating %d bytes\n", |
568 | card->evtbd_ring_size); | 581 | card->evtbd_ring_size); |
569 | card->evtbd_ring_vbase = kzalloc(card->evtbd_ring_size, GFP_KERNEL); | 582 | card->evtbd_ring_vbase = pci_alloc_consistent(card->dev, |
583 | card->evtbd_ring_size, | ||
584 | &card->evtbd_ring_pbase); | ||
570 | if (!card->evtbd_ring_vbase) { | 585 | if (!card->evtbd_ring_vbase) { |
571 | dev_err(adapter->dev, | 586 | dev_err(adapter->dev, |
572 | "Unable to allocate buffer. Terminating download\n"); | 587 | "allocate consistent memory (%d bytes) failed!\n", |
588 | card->evtbd_ring_size); | ||
573 | return -ENOMEM; | 589 | return -ENOMEM; |
574 | } | 590 | } |
575 | card->evtbd_ring_pbase = virt_to_phys(card->evtbd_ring_vbase); | ||
576 | 591 | ||
577 | dev_dbg(adapter->dev, | 592 | dev_dbg(adapter->dev, |
578 | "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n", | 593 | "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n", |
@@ -594,16 +609,20 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) | |||
594 | kfree(card->evtbd_ring_vbase); | 609 | kfree(card->evtbd_ring_vbase); |
595 | return -ENOMEM; | 610 | return -ENOMEM; |
596 | } | 611 | } |
597 | buf_pa = mwifiex_update_sk_buff_pa(skb); | ||
598 | skb_put(skb, MAX_EVENT_SIZE); | 612 | skb_put(skb, MAX_EVENT_SIZE); |
599 | 613 | ||
614 | if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE, | ||
615 | PCI_DMA_FROMDEVICE)) | ||
616 | return -1; | ||
617 | |||
618 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
600 | dev_dbg(adapter->dev, "info: Evt ring: add new skb. base: %p, " | 619 | dev_dbg(adapter->dev, "info: Evt ring: add new skb. base: %p, " |
601 | "buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n", | 620 | "buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n", |
602 | skb, skb->data, (u32)*buf_pa, (u32)((u64)*buf_pa >> 32), | 621 | skb, skb->data, (u32)buf_pa, (u32)((u64)buf_pa >> 32), |
603 | skb->len); | 622 | skb->len); |
604 | 623 | ||
605 | card->evt_buf_list[i] = skb; | 624 | card->evt_buf_list[i] = skb; |
606 | card->evtbd_ring[i]->paddr = *buf_pa; | 625 | card->evtbd_ring[i]->paddr = buf_pa; |
607 | card->evtbd_ring[i]->len = (u16)skb->len; | 626 | card->evtbd_ring[i]->len = (u16)skb->len; |
608 | card->evtbd_ring[i]->flags = 0; | 627 | card->evtbd_ring[i]->flags = 0; |
609 | } | 628 | } |
@@ -617,11 +636,16 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) | |||
617 | static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter) | 636 | static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter) |
618 | { | 637 | { |
619 | struct pcie_service_card *card = adapter->card; | 638 | struct pcie_service_card *card = adapter->card; |
639 | struct sk_buff *skb; | ||
620 | int i; | 640 | int i; |
621 | 641 | ||
622 | for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) { | 642 | for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) { |
623 | if (card->evt_buf_list[i]) | 643 | if (card->evt_buf_list[i]) { |
624 | dev_kfree_skb_any(card->evt_buf_list[i]); | 644 | skb = card->evt_buf_list[i]; |
645 | pci_unmap_single(card->dev, card->evtbd_ring[i]->paddr, | ||
646 | MAX_EVENT_SIZE, PCI_DMA_FROMDEVICE); | ||
647 | dev_kfree_skb_any(skb); | ||
648 | } | ||
625 | card->evt_buf_list[i] = NULL; | 649 | card->evt_buf_list[i] = NULL; |
626 | card->evtbd_ring[i]->paddr = 0; | 650 | card->evtbd_ring[i]->paddr = 0; |
627 | card->evtbd_ring[i]->len = 0; | 651 | card->evtbd_ring[i]->len = 0; |
@@ -629,11 +653,15 @@ static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter) | |||
629 | card->evtbd_ring[i] = NULL; | 653 | card->evtbd_ring[i] = NULL; |
630 | } | 654 | } |
631 | 655 | ||
632 | kfree(card->evtbd_ring_vbase); | 656 | if (card->evtbd_ring_vbase) |
657 | pci_free_consistent(card->dev, card->evtbd_ring_size, | ||
658 | card->evtbd_ring_vbase, | ||
659 | card->evtbd_ring_pbase); | ||
633 | card->evtbd_wrptr = 0; | 660 | card->evtbd_wrptr = 0; |
634 | card->evtbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; | 661 | card->evtbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; |
635 | card->evtbd_ring_size = 0; | 662 | card->evtbd_ring_size = 0; |
636 | card->evtbd_ring_vbase = NULL; | 663 | card->evtbd_ring_vbase = NULL; |
664 | card->evtbd_ring_pbase = 0; | ||
637 | 665 | ||
638 | return 0; | 666 | return 0; |
639 | } | 667 | } |
@@ -653,21 +681,12 @@ static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter) | |||
653 | "Unable to allocate skb for command response data.\n"); | 681 | "Unable to allocate skb for command response data.\n"); |
654 | return -ENOMEM; | 682 | return -ENOMEM; |
655 | } | 683 | } |
656 | mwifiex_update_sk_buff_pa(skb); | ||
657 | skb_put(skb, MWIFIEX_UPLD_SIZE); | 684 | skb_put(skb, MWIFIEX_UPLD_SIZE); |
658 | card->cmdrsp_buf = skb; | 685 | if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, |
686 | PCI_DMA_FROMDEVICE)) | ||
687 | return -1; | ||
659 | 688 | ||
660 | skb = NULL; | 689 | card->cmdrsp_buf = skb; |
661 | /* Allocate memory for sending command to firmware */ | ||
662 | skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER); | ||
663 | if (!skb) { | ||
664 | dev_err(adapter->dev, | ||
665 | "Unable to allocate skb for command data.\n"); | ||
666 | return -ENOMEM; | ||
667 | } | ||
668 | mwifiex_update_sk_buff_pa(skb); | ||
669 | skb_put(skb, MWIFIEX_SIZE_OF_CMD_BUFFER); | ||
670 | card->cmd_buf = skb; | ||
671 | 690 | ||
672 | return 0; | 691 | return 0; |
673 | } | 692 | } |
@@ -678,18 +697,26 @@ static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter) | |||
678 | static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) | 697 | static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) |
679 | { | 698 | { |
680 | struct pcie_service_card *card; | 699 | struct pcie_service_card *card; |
700 | dma_addr_t buf_pa; | ||
681 | 701 | ||
682 | if (!adapter) | 702 | if (!adapter) |
683 | return 0; | 703 | return 0; |
684 | 704 | ||
685 | card = adapter->card; | 705 | card = adapter->card; |
686 | 706 | ||
687 | if (card && card->cmdrsp_buf) | 707 | if (card && card->cmdrsp_buf) { |
708 | MWIFIEX_SKB_PACB(card->cmdrsp_buf, &buf_pa); | ||
709 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | ||
710 | PCI_DMA_FROMDEVICE); | ||
688 | dev_kfree_skb_any(card->cmdrsp_buf); | 711 | dev_kfree_skb_any(card->cmdrsp_buf); |
712 | } | ||
689 | 713 | ||
690 | if (card && card->cmd_buf) | 714 | if (card && card->cmd_buf) { |
715 | MWIFIEX_SKB_PACB(card->cmd_buf, &buf_pa); | ||
716 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_SIZE_OF_CMD_BUFFER, | ||
717 | PCI_DMA_TODEVICE); | ||
691 | dev_kfree_skb_any(card->cmd_buf); | 718 | dev_kfree_skb_any(card->cmd_buf); |
692 | 719 | } | |
693 | return 0; | 720 | return 0; |
694 | } | 721 | } |
695 | 722 | ||
@@ -698,27 +725,19 @@ static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) | |||
698 | */ | 725 | */ |
699 | static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter) | 726 | static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter) |
700 | { | 727 | { |
701 | struct sk_buff *skb; | ||
702 | struct pcie_service_card *card = adapter->card; | 728 | struct pcie_service_card *card = adapter->card; |
703 | 729 | ||
704 | /* Allocate memory for sleep cookie */ | 730 | card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32), |
705 | skb = dev_alloc_skb(sizeof(u32)); | 731 | &card->sleep_cookie_pbase); |
706 | if (!skb) { | 732 | if (!card->sleep_cookie_vbase) { |
707 | dev_err(adapter->dev, | 733 | dev_err(adapter->dev, "pci_alloc_consistent failed!\n"); |
708 | "Unable to allocate skb for sleep cookie!\n"); | ||
709 | return -ENOMEM; | 734 | return -ENOMEM; |
710 | } | 735 | } |
711 | mwifiex_update_sk_buff_pa(skb); | ||
712 | skb_put(skb, sizeof(u32)); | ||
713 | |||
714 | /* Init val of Sleep Cookie */ | 736 | /* Init val of Sleep Cookie */ |
715 | *(u32 *)skb->data = FW_AWAKE_COOKIE; | 737 | *(u32 *)card->sleep_cookie_vbase = FW_AWAKE_COOKIE; |
716 | 738 | ||
717 | dev_dbg(adapter->dev, "alloc_scook: sleep cookie=0x%x\n", | 739 | dev_dbg(adapter->dev, "alloc_scook: sleep cookie=0x%x\n", |
718 | *((u32 *)skb->data)); | 740 | *((u32 *)card->sleep_cookie_vbase)); |
719 | |||
720 | /* Save the sleep cookie */ | ||
721 | card->sleep_cookie = skb; | ||
722 | 741 | ||
723 | return 0; | 742 | return 0; |
724 | } | 743 | } |
@@ -735,24 +754,57 @@ static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter) | |||
735 | 754 | ||
736 | card = adapter->card; | 755 | card = adapter->card; |
737 | 756 | ||
738 | if (card && card->sleep_cookie) { | 757 | if (card && card->sleep_cookie_vbase) { |
739 | dev_kfree_skb_any(card->sleep_cookie); | 758 | pci_free_consistent(card->dev, sizeof(u32), |
740 | card->sleep_cookie = NULL; | 759 | card->sleep_cookie_vbase, |
760 | card->sleep_cookie_pbase); | ||
761 | card->sleep_cookie_vbase = NULL; | ||
741 | } | 762 | } |
742 | 763 | ||
743 | return 0; | 764 | return 0; |
744 | } | 765 | } |
745 | 766 | ||
767 | /* This function flushes the TX buffer descriptor ring | ||
768 | * This function defined as handler is also called while cleaning TXRX | ||
769 | * during disconnect/ bss stop. | ||
770 | */ | ||
771 | static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter) | ||
772 | { | ||
773 | struct pcie_service_card *card = adapter->card; | ||
774 | u32 rdptr; | ||
775 | |||
776 | /* Read the TX ring read pointer set by firmware */ | ||
777 | if (mwifiex_read_reg(adapter, REG_TXBD_RDPTR, &rdptr)) { | ||
778 | dev_err(adapter->dev, | ||
779 | "Flush TXBD: failed to read REG_TXBD_RDPTR\n"); | ||
780 | return -1; | ||
781 | } | ||
782 | |||
783 | if (!mwifiex_pcie_txbd_empty(card, rdptr)) { | ||
784 | card->txbd_flush = 1; | ||
785 | /* write pointer already set at last send | ||
786 | * send dnld-rdy intr again, wait for completion. | ||
787 | */ | ||
788 | if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, | ||
789 | CPU_INTR_DNLD_RDY)) { | ||
790 | dev_err(adapter->dev, | ||
791 | "failed to assert dnld-rdy interrupt.\n"); | ||
792 | return -1; | ||
793 | } | ||
794 | } | ||
795 | return 0; | ||
796 | } | ||
797 | |||
746 | /* | 798 | /* |
747 | * This function sends data buffer to device | 799 | * This function unmaps and frees downloaded data buffer |
748 | */ | 800 | */ |
749 | static int | 801 | static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) |
750 | mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb) | ||
751 | { | 802 | { |
803 | const u32 num_tx_buffs = MWIFIEX_MAX_TXRX_BD; | ||
804 | struct sk_buff *skb; | ||
805 | dma_addr_t buf_pa; | ||
806 | u32 wrdoneidx, rdptr, unmap_count = 0; | ||
752 | struct pcie_service_card *card = adapter->card; | 807 | struct pcie_service_card *card = adapter->card; |
753 | u32 wrindx, rdptr; | ||
754 | phys_addr_t *buf_pa; | ||
755 | __le16 *tmp; | ||
756 | 808 | ||
757 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) | 809 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) |
758 | mwifiex_pm_wakeup_card(adapter); | 810 | mwifiex_pm_wakeup_card(adapter); |
@@ -760,34 +812,112 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
760 | /* Read the TX ring read pointer set by firmware */ | 812 | /* Read the TX ring read pointer set by firmware */ |
761 | if (mwifiex_read_reg(adapter, REG_TXBD_RDPTR, &rdptr)) { | 813 | if (mwifiex_read_reg(adapter, REG_TXBD_RDPTR, &rdptr)) { |
762 | dev_err(adapter->dev, | 814 | dev_err(adapter->dev, |
763 | "SEND DATA: failed to read REG_TXBD_RDPTR\n"); | 815 | "SEND COMP: failed to read REG_TXBD_RDPTR\n"); |
764 | return -1; | 816 | return -1; |
765 | } | 817 | } |
766 | 818 | ||
767 | wrindx = card->txbd_wrptr & MWIFIEX_TXBD_MASK; | 819 | dev_dbg(adapter->dev, "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n", |
820 | card->txbd_rdptr, rdptr); | ||
768 | 821 | ||
769 | dev_dbg(adapter->dev, "info: SEND DATA: <Rd: %#x, Wr: %#x>\n", rdptr, | 822 | /* free from previous txbd_rdptr to current txbd_rdptr */ |
770 | card->txbd_wrptr); | 823 | while (((card->txbd_rdptr & MWIFIEX_TXBD_MASK) != |
771 | if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) != | 824 | (rdptr & MWIFIEX_TXBD_MASK)) || |
772 | (rdptr & MWIFIEX_TXBD_MASK)) || | 825 | ((card->txbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) != |
773 | ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) != | 826 | (rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) { |
774 | (rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) { | 827 | wrdoneidx = card->txbd_rdptr & MWIFIEX_TXBD_MASK; |
775 | struct sk_buff *skb_data; | 828 | |
829 | skb = card->tx_buf_list[wrdoneidx]; | ||
830 | if (skb) { | ||
831 | dev_dbg(adapter->dev, | ||
832 | "SEND COMP: Detach skb %p at txbd_rdidx=%d\n", | ||
833 | skb, wrdoneidx); | ||
834 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
835 | pci_unmap_single(card->dev, buf_pa, skb->len, | ||
836 | PCI_DMA_TODEVICE); | ||
837 | |||
838 | unmap_count++; | ||
839 | |||
840 | if (card->txbd_flush) | ||
841 | mwifiex_write_data_complete(adapter, skb, 0, | ||
842 | -1); | ||
843 | else | ||
844 | mwifiex_write_data_complete(adapter, skb, 0, 0); | ||
845 | } | ||
846 | |||
847 | card->tx_buf_list[wrdoneidx] = NULL; | ||
848 | card->txbd_ring[wrdoneidx]->paddr = 0; | ||
849 | card->rxbd_ring[wrdoneidx]->len = 0; | ||
850 | card->rxbd_ring[wrdoneidx]->flags = 0; | ||
851 | card->txbd_rdptr++; | ||
852 | |||
853 | if ((card->txbd_rdptr & MWIFIEX_TXBD_MASK) == num_tx_buffs) | ||
854 | card->txbd_rdptr = ((card->txbd_rdptr & | ||
855 | MWIFIEX_BD_FLAG_ROLLOVER_IND) ^ | ||
856 | MWIFIEX_BD_FLAG_ROLLOVER_IND); | ||
857 | } | ||
858 | |||
859 | if (unmap_count) | ||
860 | adapter->data_sent = false; | ||
861 | |||
862 | if (card->txbd_flush) { | ||
863 | if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) == | ||
864 | (card->txbd_rdptr & MWIFIEX_TXBD_MASK)) && | ||
865 | ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) != | ||
866 | (card->txbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) | ||
867 | card->txbd_flush = 0; | ||
868 | else | ||
869 | mwifiex_clean_pcie_ring_buf(adapter); | ||
870 | } | ||
871 | |||
872 | return 0; | ||
873 | } | ||
874 | |||
875 | /* This function sends data buffer to device. First 4 bytes of payload | ||
876 | * are filled with payload length and payload type. Then this payload | ||
877 | * is mapped to PCI device memory. Tx ring pointers are advanced accordingly. | ||
878 | * Download ready interrupt to FW is deffered if Tx ring is not full and | ||
879 | * additional payload can be accomodated. | ||
880 | */ | ||
881 | static int | ||
882 | mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, | ||
883 | struct mwifiex_tx_param *tx_param) | ||
884 | { | ||
885 | struct pcie_service_card *card = adapter->card; | ||
886 | u32 wrindx; | ||
887 | int ret; | ||
888 | dma_addr_t buf_pa; | ||
889 | __le16 *tmp; | ||
890 | |||
891 | if (!(skb->data && skb->len)) { | ||
892 | dev_err(adapter->dev, "%s(): invalid parameter <%p, %#x>\n", | ||
893 | __func__, skb->data, skb->len); | ||
894 | return -1; | ||
895 | } | ||
896 | |||
897 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) | ||
898 | mwifiex_pm_wakeup_card(adapter); | ||
899 | |||
900 | dev_dbg(adapter->dev, "info: SEND DATA: <Rd: %#x, Wr: %#x>\n", | ||
901 | card->txbd_rdptr, card->txbd_wrptr); | ||
902 | if (mwifiex_pcie_txbd_not_full(card)) { | ||
776 | u8 *payload; | 903 | u8 *payload; |
777 | 904 | ||
778 | adapter->data_sent = true; | 905 | adapter->data_sent = true; |
779 | skb_data = card->tx_buf_list[wrindx]; | 906 | payload = skb->data; |
780 | memcpy(skb_data->data, skb->data, skb->len); | ||
781 | payload = skb_data->data; | ||
782 | tmp = (__le16 *)&payload[0]; | 907 | tmp = (__le16 *)&payload[0]; |
783 | *tmp = cpu_to_le16((u16)skb->len); | 908 | *tmp = cpu_to_le16((u16)skb->len); |
784 | tmp = (__le16 *)&payload[2]; | 909 | tmp = (__le16 *)&payload[2]; |
785 | *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA); | 910 | *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA); |
786 | skb_put(skb_data, MWIFIEX_RX_DATA_BUF_SIZE - skb_data->len); | 911 | |
787 | skb_trim(skb_data, skb->len); | 912 | if (mwifiex_map_pci_memory(adapter, skb, skb->len , |
788 | buf_pa = MWIFIEX_SKB_PACB(skb_data); | 913 | PCI_DMA_TODEVICE)) |
789 | card->txbd_ring[wrindx]->paddr = *buf_pa; | 914 | return -1; |
790 | card->txbd_ring[wrindx]->len = (u16)skb_data->len; | 915 | |
916 | wrindx = card->txbd_wrptr & MWIFIEX_TXBD_MASK; | ||
917 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
918 | card->tx_buf_list[wrindx] = skb; | ||
919 | card->txbd_ring[wrindx]->paddr = buf_pa; | ||
920 | card->txbd_ring[wrindx]->len = (u16)skb->len; | ||
791 | card->txbd_ring[wrindx]->flags = MWIFIEX_BD_FLAG_FIRST_DESC | | 921 | card->txbd_ring[wrindx]->flags = MWIFIEX_BD_FLAG_FIRST_DESC | |
792 | MWIFIEX_BD_FLAG_LAST_DESC; | 922 | MWIFIEX_BD_FLAG_LAST_DESC; |
793 | 923 | ||
@@ -802,19 +932,28 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
802 | card->txbd_wrptr)) { | 932 | card->txbd_wrptr)) { |
803 | dev_err(adapter->dev, | 933 | dev_err(adapter->dev, |
804 | "SEND DATA: failed to write REG_TXBD_WRPTR\n"); | 934 | "SEND DATA: failed to write REG_TXBD_WRPTR\n"); |
805 | return 0; | 935 | ret = -1; |
936 | goto done_unmap; | ||
806 | } | 937 | } |
807 | 938 | if ((mwifiex_pcie_txbd_not_full(card)) && | |
808 | /* Send the TX ready interrupt */ | 939 | tx_param->next_pkt_len) { |
809 | if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, | 940 | /* have more packets and TxBD still can hold more */ |
810 | CPU_INTR_DNLD_RDY)) { | 941 | dev_dbg(adapter->dev, |
811 | dev_err(adapter->dev, | 942 | "SEND DATA: delay dnld-rdy interrupt.\n"); |
812 | "SEND DATA: failed to assert door-bell intr\n"); | 943 | adapter->data_sent = false; |
813 | return -1; | 944 | } else { |
945 | /* Send the TX ready interrupt */ | ||
946 | if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, | ||
947 | CPU_INTR_DNLD_RDY)) { | ||
948 | dev_err(adapter->dev, | ||
949 | "SEND DATA: failed to assert dnld-rdy interrupt.\n"); | ||
950 | ret = -1; | ||
951 | goto done_unmap; | ||
952 | } | ||
814 | } | 953 | } |
815 | dev_dbg(adapter->dev, "info: SEND DATA: Updated <Rd: %#x, Wr: " | 954 | dev_dbg(adapter->dev, "info: SEND DATA: Updated <Rd: %#x, Wr: " |
816 | "%#x> and sent packet to firmware successfully\n", | 955 | "%#x> and sent packet to firmware successfully\n", |
817 | rdptr, card->txbd_wrptr); | 956 | card->txbd_rdptr, card->txbd_wrptr); |
818 | } else { | 957 | } else { |
819 | dev_dbg(adapter->dev, | 958 | dev_dbg(adapter->dev, |
820 | "info: TX Ring full, can't send packets to fw\n"); | 959 | "info: TX Ring full, can't send packets to fw\n"); |
@@ -827,7 +966,15 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
827 | return -EBUSY; | 966 | return -EBUSY; |
828 | } | 967 | } |
829 | 968 | ||
830 | return 0; | 969 | return -EINPROGRESS; |
970 | done_unmap: | ||
971 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
972 | pci_unmap_single(card->dev, buf_pa, skb->len, PCI_DMA_TODEVICE); | ||
973 | card->tx_buf_list[wrindx] = NULL; | ||
974 | card->txbd_ring[wrindx]->paddr = 0; | ||
975 | card->txbd_ring[wrindx]->len = 0; | ||
976 | card->txbd_ring[wrindx]->flags = 0; | ||
977 | return ret; | ||
831 | } | 978 | } |
832 | 979 | ||
833 | /* | 980 | /* |
@@ -838,9 +985,13 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | |||
838 | { | 985 | { |
839 | struct pcie_service_card *card = adapter->card; | 986 | struct pcie_service_card *card = adapter->card; |
840 | u32 wrptr, rd_index; | 987 | u32 wrptr, rd_index; |
988 | dma_addr_t buf_pa; | ||
841 | int ret = 0; | 989 | int ret = 0; |
842 | struct sk_buff *skb_tmp = NULL; | 990 | struct sk_buff *skb_tmp = NULL; |
843 | 991 | ||
992 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) | ||
993 | mwifiex_pm_wakeup_card(adapter); | ||
994 | |||
844 | /* Read the RX ring Write pointer set by firmware */ | 995 | /* Read the RX ring Write pointer set by firmware */ |
845 | if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) { | 996 | if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) { |
846 | dev_err(adapter->dev, | 997 | dev_err(adapter->dev, |
@@ -848,6 +999,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | |||
848 | ret = -1; | 999 | ret = -1; |
849 | goto done; | 1000 | goto done; |
850 | } | 1001 | } |
1002 | card->rxbd_wrptr = wrptr; | ||
851 | 1003 | ||
852 | while (((wrptr & MWIFIEX_RXBD_MASK) != | 1004 | while (((wrptr & MWIFIEX_RXBD_MASK) != |
853 | (card->rxbd_rdptr & MWIFIEX_RXBD_MASK)) || | 1005 | (card->rxbd_rdptr & MWIFIEX_RXBD_MASK)) || |
@@ -855,27 +1007,50 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | |||
855 | (card->rxbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) { | 1007 | (card->rxbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) { |
856 | struct sk_buff *skb_data; | 1008 | struct sk_buff *skb_data; |
857 | u16 rx_len; | 1009 | u16 rx_len; |
1010 | __le16 pkt_len; | ||
858 | 1011 | ||
859 | rd_index = card->rxbd_rdptr & MWIFIEX_RXBD_MASK; | 1012 | rd_index = card->rxbd_rdptr & MWIFIEX_RXBD_MASK; |
860 | skb_data = card->rx_buf_list[rd_index]; | 1013 | skb_data = card->rx_buf_list[rd_index]; |
861 | 1014 | ||
1015 | MWIFIEX_SKB_PACB(skb_data, &buf_pa); | ||
1016 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_RX_DATA_BUF_SIZE, | ||
1017 | PCI_DMA_FROMDEVICE); | ||
1018 | card->rx_buf_list[rd_index] = NULL; | ||
1019 | |||
862 | /* Get data length from interface header - | 1020 | /* Get data length from interface header - |
863 | first byte is len, second byte is type */ | 1021 | * first 2 bytes for len, next 2 bytes is for type |
864 | rx_len = *((u16 *)skb_data->data); | 1022 | */ |
1023 | pkt_len = *((__le16 *)skb_data->data); | ||
1024 | rx_len = le16_to_cpu(pkt_len); | ||
1025 | skb_put(skb_data, rx_len); | ||
865 | dev_dbg(adapter->dev, | 1026 | dev_dbg(adapter->dev, |
866 | "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n", | 1027 | "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n", |
867 | card->rxbd_rdptr, wrptr, rx_len); | 1028 | card->rxbd_rdptr, wrptr, rx_len); |
868 | skb_tmp = dev_alloc_skb(rx_len); | 1029 | skb_pull(skb_data, INTF_HEADER_LEN); |
1030 | mwifiex_handle_rx_packet(adapter, skb_data); | ||
1031 | |||
1032 | skb_tmp = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE); | ||
869 | if (!skb_tmp) { | 1033 | if (!skb_tmp) { |
870 | dev_dbg(adapter->dev, | 1034 | dev_err(adapter->dev, |
871 | "info: Failed to alloc skb for RX\n"); | 1035 | "Unable to allocate skb.\n"); |
872 | ret = -EBUSY; | 1036 | return -ENOMEM; |
873 | goto done; | ||
874 | } | 1037 | } |
875 | 1038 | ||
876 | skb_put(skb_tmp, rx_len); | 1039 | if (mwifiex_map_pci_memory(adapter, skb_tmp, |
1040 | MWIFIEX_RX_DATA_BUF_SIZE, | ||
1041 | PCI_DMA_FROMDEVICE)) | ||
1042 | return -1; | ||
1043 | |||
1044 | MWIFIEX_SKB_PACB(skb_tmp, &buf_pa); | ||
1045 | |||
1046 | dev_dbg(adapter->dev, | ||
1047 | "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n", | ||
1048 | skb_tmp, rd_index); | ||
1049 | card->rx_buf_list[rd_index] = skb_tmp; | ||
1050 | card->rxbd_ring[rd_index]->paddr = buf_pa; | ||
1051 | card->rxbd_ring[rd_index]->len = skb_tmp->len; | ||
1052 | card->rxbd_ring[rd_index]->flags = 0; | ||
877 | 1053 | ||
878 | memcpy(skb_tmp->data, skb_data->data + INTF_HEADER_LEN, rx_len); | ||
879 | if ((++card->rxbd_rdptr & MWIFIEX_RXBD_MASK) == | 1054 | if ((++card->rxbd_rdptr & MWIFIEX_RXBD_MASK) == |
880 | MWIFIEX_MAX_TXRX_BD) { | 1055 | MWIFIEX_MAX_TXRX_BD) { |
881 | card->rxbd_rdptr = ((card->rxbd_rdptr & | 1056 | card->rxbd_rdptr = ((card->rxbd_rdptr & |
@@ -903,12 +1078,10 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | |||
903 | } | 1078 | } |
904 | dev_dbg(adapter->dev, | 1079 | dev_dbg(adapter->dev, |
905 | "info: RECV DATA: Rcvd packet from fw successfully\n"); | 1080 | "info: RECV DATA: Rcvd packet from fw successfully\n"); |
906 | mwifiex_handle_rx_packet(adapter, skb_tmp); | 1081 | card->rxbd_wrptr = wrptr; |
907 | } | 1082 | } |
908 | 1083 | ||
909 | done: | 1084 | done: |
910 | if (ret && skb_tmp) | ||
911 | dev_kfree_skb_any(skb_tmp); | ||
912 | return ret; | 1085 | return ret; |
913 | } | 1086 | } |
914 | 1087 | ||
@@ -918,32 +1091,41 @@ done: | |||
918 | static int | 1091 | static int |
919 | mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | 1092 | mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) |
920 | { | 1093 | { |
921 | phys_addr_t *buf_pa = MWIFIEX_SKB_PACB(skb); | 1094 | dma_addr_t buf_pa; |
1095 | struct pcie_service_card *card = adapter->card; | ||
922 | 1096 | ||
923 | if (!(skb->data && skb->len && *buf_pa)) { | 1097 | if (!(skb->data && skb->len)) { |
924 | dev_err(adapter->dev, | 1098 | dev_err(adapter->dev, |
925 | "Invalid parameter in %s <%p, %#x:%x, %x>\n", | 1099 | "Invalid parameter in %s <%p. len %d>\n", |
926 | __func__, skb->data, skb->len, | 1100 | __func__, skb->data, skb->len); |
927 | (u32)*buf_pa, (u32)((u64)*buf_pa >> 32)); | ||
928 | return -1; | 1101 | return -1; |
929 | } | 1102 | } |
930 | 1103 | ||
1104 | if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE)) | ||
1105 | return -1; | ||
1106 | |||
1107 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1108 | |||
931 | /* Write the lower 32bits of the physical address to scratch | 1109 | /* Write the lower 32bits of the physical address to scratch |
932 | * register 0 */ | 1110 | * register 0 */ |
933 | if (mwifiex_write_reg(adapter, PCIE_SCRATCH_0_REG, (u32)*buf_pa)) { | 1111 | if (mwifiex_write_reg(adapter, PCIE_SCRATCH_0_REG, (u32)buf_pa)) { |
934 | dev_err(adapter->dev, | 1112 | dev_err(adapter->dev, |
935 | "%s: failed to write download command to boot code.\n", | 1113 | "%s: failed to write download command to boot code.\n", |
936 | __func__); | 1114 | __func__); |
1115 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | ||
1116 | PCI_DMA_TODEVICE); | ||
937 | return -1; | 1117 | return -1; |
938 | } | 1118 | } |
939 | 1119 | ||
940 | /* Write the upper 32bits of the physical address to scratch | 1120 | /* Write the upper 32bits of the physical address to scratch |
941 | * register 1 */ | 1121 | * register 1 */ |
942 | if (mwifiex_write_reg(adapter, PCIE_SCRATCH_1_REG, | 1122 | if (mwifiex_write_reg(adapter, PCIE_SCRATCH_1_REG, |
943 | (u32)((u64)*buf_pa >> 32))) { | 1123 | (u32)((u64)buf_pa >> 32))) { |
944 | dev_err(adapter->dev, | 1124 | dev_err(adapter->dev, |
945 | "%s: failed to write download command to boot code.\n", | 1125 | "%s: failed to write download command to boot code.\n", |
946 | __func__); | 1126 | __func__); |
1127 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | ||
1128 | PCI_DMA_TODEVICE); | ||
947 | return -1; | 1129 | return -1; |
948 | } | 1130 | } |
949 | 1131 | ||
@@ -952,6 +1134,8 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
952 | dev_err(adapter->dev, | 1134 | dev_err(adapter->dev, |
953 | "%s: failed to write command len to scratch reg 2\n", | 1135 | "%s: failed to write command len to scratch reg 2\n", |
954 | __func__); | 1136 | __func__); |
1137 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | ||
1138 | PCI_DMA_TODEVICE); | ||
955 | return -1; | 1139 | return -1; |
956 | } | 1140 | } |
957 | 1141 | ||
@@ -960,22 +1144,39 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
960 | CPU_INTR_DOOR_BELL)) { | 1144 | CPU_INTR_DOOR_BELL)) { |
961 | dev_err(adapter->dev, | 1145 | dev_err(adapter->dev, |
962 | "%s: failed to assert door-bell intr\n", __func__); | 1146 | "%s: failed to assert door-bell intr\n", __func__); |
1147 | pci_unmap_single(card->dev, buf_pa, | ||
1148 | MWIFIEX_UPLD_SIZE, PCI_DMA_TODEVICE); | ||
963 | return -1; | 1149 | return -1; |
964 | } | 1150 | } |
965 | 1151 | ||
966 | return 0; | 1152 | return 0; |
967 | } | 1153 | } |
968 | 1154 | ||
969 | /* | 1155 | /* This function init rx port in firmware which in turn enables to receive data |
970 | * This function downloads commands to the device | 1156 | * from device before transmitting any packet. |
1157 | */ | ||
1158 | static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter) | ||
1159 | { | ||
1160 | struct pcie_service_card *card = adapter->card; | ||
1161 | |||
1162 | /* Write the RX ring read pointer in to REG_RXBD_RDPTR */ | ||
1163 | if (mwifiex_write_reg(adapter, REG_RXBD_RDPTR, card->rxbd_rdptr | 0)) { | ||
1164 | dev_err(adapter->dev, | ||
1165 | "RECV DATA: failed to write REG_RXBD_RDPTR\n"); | ||
1166 | return -1; | ||
1167 | } | ||
1168 | return 0; | ||
1169 | } | ||
1170 | |||
1171 | /* This function downloads commands to the device | ||
971 | */ | 1172 | */ |
972 | static int | 1173 | static int |
973 | mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | 1174 | mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) |
974 | { | 1175 | { |
975 | struct pcie_service_card *card = adapter->card; | 1176 | struct pcie_service_card *card = adapter->card; |
976 | int ret = 0; | 1177 | int ret = 0; |
977 | phys_addr_t *cmd_buf_pa; | 1178 | dma_addr_t cmd_buf_pa, cmdrsp_buf_pa; |
978 | phys_addr_t *cmdrsp_buf_pa; | 1179 | u8 *payload = (u8 *)skb->data; |
979 | 1180 | ||
980 | if (!(skb->data && skb->len)) { | 1181 | if (!(skb->data && skb->len)) { |
981 | dev_err(adapter->dev, "Invalid parameter in %s <%p, %#x>\n", | 1182 | dev_err(adapter->dev, "Invalid parameter in %s <%p, %#x>\n", |
@@ -990,17 +1191,18 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
990 | return -EBUSY; | 1191 | return -EBUSY; |
991 | } | 1192 | } |
992 | 1193 | ||
993 | /* Make sure a command buffer is available */ | 1194 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) |
994 | if (!card->cmd_buf) { | 1195 | mwifiex_pm_wakeup_card(adapter); |
995 | dev_err(adapter->dev, "Command buffer not available\n"); | ||
996 | return -EBUSY; | ||
997 | } | ||
998 | 1196 | ||
999 | adapter->cmd_sent = true; | 1197 | adapter->cmd_sent = true; |
1000 | /* Copy the given skb in to DMA accessable shared buffer */ | 1198 | |
1001 | skb_put(card->cmd_buf, MWIFIEX_SIZE_OF_CMD_BUFFER - card->cmd_buf->len); | 1199 | *(__le16 *)&payload[0] = cpu_to_le16((u16)skb->len); |
1002 | skb_trim(card->cmd_buf, skb->len); | 1200 | *(__le16 *)&payload[2] = cpu_to_le16(MWIFIEX_TYPE_CMD); |
1003 | memcpy(card->cmd_buf->data, skb->data, skb->len); | 1201 | |
1202 | if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE)) | ||
1203 | return -1; | ||
1204 | |||
1205 | card->cmd_buf = skb; | ||
1004 | 1206 | ||
1005 | /* To send a command, the driver will: | 1207 | /* To send a command, the driver will: |
1006 | 1. Write the 64bit physical address of the data buffer to | 1208 | 1. Write the 64bit physical address of the data buffer to |
@@ -1013,11 +1215,11 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1013 | */ | 1215 | */ |
1014 | 1216 | ||
1015 | if (card->cmdrsp_buf) { | 1217 | if (card->cmdrsp_buf) { |
1016 | cmdrsp_buf_pa = MWIFIEX_SKB_PACB(card->cmdrsp_buf); | 1218 | MWIFIEX_SKB_PACB(card->cmdrsp_buf, &cmdrsp_buf_pa); |
1017 | /* Write the lower 32bits of the cmdrsp buffer physical | 1219 | /* Write the lower 32bits of the cmdrsp buffer physical |
1018 | address */ | 1220 | address */ |
1019 | if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO, | 1221 | if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO, |
1020 | (u32)*cmdrsp_buf_pa)) { | 1222 | (u32)cmdrsp_buf_pa)) { |
1021 | dev_err(adapter->dev, | 1223 | dev_err(adapter->dev, |
1022 | "Failed to write download cmd to boot code.\n"); | 1224 | "Failed to write download cmd to boot code.\n"); |
1023 | ret = -1; | 1225 | ret = -1; |
@@ -1026,7 +1228,7 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1026 | /* Write the upper 32bits of the cmdrsp buffer physical | 1228 | /* Write the upper 32bits of the cmdrsp buffer physical |
1027 | address */ | 1229 | address */ |
1028 | if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI, | 1230 | if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI, |
1029 | (u32)((u64)*cmdrsp_buf_pa >> 32))) { | 1231 | (u32)((u64)cmdrsp_buf_pa >> 32))) { |
1030 | dev_err(adapter->dev, | 1232 | dev_err(adapter->dev, |
1031 | "Failed to write download cmd to boot code.\n"); | 1233 | "Failed to write download cmd to boot code.\n"); |
1032 | ret = -1; | 1234 | ret = -1; |
@@ -1034,9 +1236,9 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1034 | } | 1236 | } |
1035 | } | 1237 | } |
1036 | 1238 | ||
1037 | cmd_buf_pa = MWIFIEX_SKB_PACB(card->cmd_buf); | 1239 | MWIFIEX_SKB_PACB(card->cmd_buf, &cmd_buf_pa); |
1038 | /* Write the lower 32bits of the physical address to REG_CMD_ADDR_LO */ | 1240 | /* Write the lower 32bits of the physical address to REG_CMD_ADDR_LO */ |
1039 | if (mwifiex_write_reg(adapter, REG_CMD_ADDR_LO, (u32)*cmd_buf_pa)) { | 1241 | if (mwifiex_write_reg(adapter, REG_CMD_ADDR_LO, (u32)cmd_buf_pa)) { |
1040 | dev_err(adapter->dev, | 1242 | dev_err(adapter->dev, |
1041 | "Failed to write download cmd to boot code.\n"); | 1243 | "Failed to write download cmd to boot code.\n"); |
1042 | ret = -1; | 1244 | ret = -1; |
@@ -1044,7 +1246,7 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1044 | } | 1246 | } |
1045 | /* Write the upper 32bits of the physical address to REG_CMD_ADDR_HI */ | 1247 | /* Write the upper 32bits of the physical address to REG_CMD_ADDR_HI */ |
1046 | if (mwifiex_write_reg(adapter, REG_CMD_ADDR_HI, | 1248 | if (mwifiex_write_reg(adapter, REG_CMD_ADDR_HI, |
1047 | (u32)((u64)*cmd_buf_pa >> 32))) { | 1249 | (u32)((u64)cmd_buf_pa >> 32))) { |
1048 | dev_err(adapter->dev, | 1250 | dev_err(adapter->dev, |
1049 | "Failed to write download cmd to boot code.\n"); | 1251 | "Failed to write download cmd to boot code.\n"); |
1050 | ret = -1; | 1252 | ret = -1; |
@@ -1083,11 +1285,22 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | |||
1083 | struct pcie_service_card *card = adapter->card; | 1285 | struct pcie_service_card *card = adapter->card; |
1084 | struct sk_buff *skb = card->cmdrsp_buf; | 1286 | struct sk_buff *skb = card->cmdrsp_buf; |
1085 | int count = 0; | 1287 | int count = 0; |
1288 | u16 rx_len; | ||
1289 | __le16 pkt_len; | ||
1290 | dma_addr_t buf_pa; | ||
1086 | 1291 | ||
1087 | dev_dbg(adapter->dev, "info: Rx CMD Response\n"); | 1292 | dev_dbg(adapter->dev, "info: Rx CMD Response\n"); |
1088 | 1293 | ||
1294 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1295 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | ||
1296 | PCI_DMA_FROMDEVICE); | ||
1297 | |||
1298 | pkt_len = *((__le16 *)skb->data); | ||
1299 | rx_len = le16_to_cpu(pkt_len); | ||
1300 | skb_trim(skb, rx_len); | ||
1301 | skb_pull(skb, INTF_HEADER_LEN); | ||
1302 | |||
1089 | if (!adapter->curr_cmd) { | 1303 | if (!adapter->curr_cmd) { |
1090 | skb_pull(skb, INTF_HEADER_LEN); | ||
1091 | if (adapter->ps_state == PS_STATE_SLEEP_CFM) { | 1304 | if (adapter->ps_state == PS_STATE_SLEEP_CFM) { |
1092 | mwifiex_process_sleep_confirm_resp(adapter, skb->data, | 1305 | mwifiex_process_sleep_confirm_resp(adapter, skb->data, |
1093 | skb->len); | 1306 | skb->len); |
@@ -1100,9 +1313,12 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | |||
1100 | } | 1313 | } |
1101 | memcpy(adapter->upld_buf, skb->data, | 1314 | memcpy(adapter->upld_buf, skb->data, |
1102 | min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len)); | 1315 | min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len)); |
1103 | skb_push(skb, INTF_HEADER_LEN); | 1316 | if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, |
1317 | PCI_DMA_FROMDEVICE)) | ||
1318 | return -1; | ||
1319 | |||
1320 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1104 | } else if (mwifiex_pcie_ok_to_access_hw(adapter)) { | 1321 | } else if (mwifiex_pcie_ok_to_access_hw(adapter)) { |
1105 | skb_pull(skb, INTF_HEADER_LEN); | ||
1106 | adapter->curr_cmd->resp_skb = skb; | 1322 | adapter->curr_cmd->resp_skb = skb; |
1107 | adapter->cmd_resp_received = true; | 1323 | adapter->cmd_resp_received = true; |
1108 | /* Take the pointer and set it to CMD node and will | 1324 | /* Take the pointer and set it to CMD node and will |
@@ -1136,10 +1352,23 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter, | |||
1136 | struct sk_buff *skb) | 1352 | struct sk_buff *skb) |
1137 | { | 1353 | { |
1138 | struct pcie_service_card *card = adapter->card; | 1354 | struct pcie_service_card *card = adapter->card; |
1355 | dma_addr_t buf_pa; | ||
1356 | struct sk_buff *skb_tmp; | ||
1139 | 1357 | ||
1140 | if (skb) { | 1358 | if (skb) { |
1141 | card->cmdrsp_buf = skb; | 1359 | card->cmdrsp_buf = skb; |
1142 | skb_push(card->cmdrsp_buf, INTF_HEADER_LEN); | 1360 | skb_push(card->cmdrsp_buf, INTF_HEADER_LEN); |
1361 | if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, | ||
1362 | PCI_DMA_FROMDEVICE)) | ||
1363 | return -1; | ||
1364 | } | ||
1365 | |||
1366 | skb_tmp = card->cmd_buf; | ||
1367 | if (skb_tmp) { | ||
1368 | MWIFIEX_SKB_PACB(skb_tmp, &buf_pa); | ||
1369 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | ||
1370 | PCI_DMA_FROMDEVICE); | ||
1371 | card->cmd_buf = NULL; | ||
1143 | } | 1372 | } |
1144 | 1373 | ||
1145 | return 0; | 1374 | return 0; |
@@ -1153,6 +1382,10 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) | |||
1153 | struct pcie_service_card *card = adapter->card; | 1382 | struct pcie_service_card *card = adapter->card; |
1154 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; | 1383 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; |
1155 | u32 wrptr, event; | 1384 | u32 wrptr, event; |
1385 | dma_addr_t buf_pa; | ||
1386 | |||
1387 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) | ||
1388 | mwifiex_pm_wakeup_card(adapter); | ||
1156 | 1389 | ||
1157 | if (adapter->event_received) { | 1390 | if (adapter->event_received) { |
1158 | dev_dbg(adapter->dev, "info: Event being processed, " | 1391 | dev_dbg(adapter->dev, "info: Event being processed, " |
@@ -1184,6 +1417,10 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) | |||
1184 | 1417 | ||
1185 | dev_dbg(adapter->dev, "info: Read Index: %d\n", rdptr); | 1418 | dev_dbg(adapter->dev, "info: Read Index: %d\n", rdptr); |
1186 | skb_cmd = card->evt_buf_list[rdptr]; | 1419 | skb_cmd = card->evt_buf_list[rdptr]; |
1420 | MWIFIEX_SKB_PACB(skb_cmd, &buf_pa); | ||
1421 | pci_unmap_single(card->dev, buf_pa, MAX_EVENT_SIZE, | ||
1422 | PCI_DMA_FROMDEVICE); | ||
1423 | |||
1187 | /* Take the pointer and set it to event pointer in adapter | 1424 | /* Take the pointer and set it to event pointer in adapter |
1188 | and will return back after event handling callback */ | 1425 | and will return back after event handling callback */ |
1189 | card->evt_buf_list[rdptr] = NULL; | 1426 | card->evt_buf_list[rdptr] = NULL; |
@@ -1228,7 +1465,7 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, | |||
1228 | int ret = 0; | 1465 | int ret = 0; |
1229 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; | 1466 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; |
1230 | u32 wrptr; | 1467 | u32 wrptr; |
1231 | phys_addr_t *buf_pa; | 1468 | dma_addr_t buf_pa; |
1232 | 1469 | ||
1233 | if (!skb) | 1470 | if (!skb) |
1234 | return 0; | 1471 | return 0; |
@@ -1248,9 +1485,14 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, | |||
1248 | 1485 | ||
1249 | if (!card->evt_buf_list[rdptr]) { | 1486 | if (!card->evt_buf_list[rdptr]) { |
1250 | skb_push(skb, INTF_HEADER_LEN); | 1487 | skb_push(skb, INTF_HEADER_LEN); |
1488 | if (mwifiex_map_pci_memory(adapter, skb, | ||
1489 | MAX_EVENT_SIZE, | ||
1490 | PCI_DMA_FROMDEVICE)) | ||
1491 | return -1; | ||
1492 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1251 | card->evt_buf_list[rdptr] = skb; | 1493 | card->evt_buf_list[rdptr] = skb; |
1252 | buf_pa = MWIFIEX_SKB_PACB(skb); | 1494 | MWIFIEX_SKB_PACB(skb, &buf_pa); |
1253 | card->evtbd_ring[rdptr]->paddr = *buf_pa; | 1495 | card->evtbd_ring[rdptr]->paddr = buf_pa; |
1254 | card->evtbd_ring[rdptr]->len = (u16)skb->len; | 1496 | card->evtbd_ring[rdptr]->len = (u16)skb->len; |
1255 | card->evtbd_ring[rdptr]->flags = 0; | 1497 | card->evtbd_ring[rdptr]->flags = 0; |
1256 | skb = NULL; | 1498 | skb = NULL; |
@@ -1299,11 +1541,8 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
1299 | struct sk_buff *skb; | 1541 | struct sk_buff *skb; |
1300 | u32 txlen, tx_blocks = 0, tries, len; | 1542 | u32 txlen, tx_blocks = 0, tries, len; |
1301 | u32 block_retry_cnt = 0; | 1543 | u32 block_retry_cnt = 0; |
1302 | 1544 | dma_addr_t buf_pa; | |
1303 | if (!adapter) { | 1545 | struct pcie_service_card *card = adapter->card; |
1304 | pr_err("adapter structure is not valid\n"); | ||
1305 | return -1; | ||
1306 | } | ||
1307 | 1546 | ||
1308 | if (!firmware || !firmware_len) { | 1547 | if (!firmware || !firmware_len) { |
1309 | dev_err(adapter->dev, | 1548 | dev_err(adapter->dev, |
@@ -1325,7 +1564,6 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
1325 | ret = -ENOMEM; | 1564 | ret = -ENOMEM; |
1326 | goto done; | 1565 | goto done; |
1327 | } | 1566 | } |
1328 | mwifiex_update_sk_buff_pa(skb); | ||
1329 | 1567 | ||
1330 | /* Perform firmware data transfer */ | 1568 | /* Perform firmware data transfer */ |
1331 | do { | 1569 | do { |
@@ -1400,6 +1638,9 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
1400 | ret = -1; | 1638 | ret = -1; |
1401 | goto done; | 1639 | goto done; |
1402 | } | 1640 | } |
1641 | |||
1642 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1643 | |||
1403 | /* Wait for the command done interrupt */ | 1644 | /* Wait for the command done interrupt */ |
1404 | do { | 1645 | do { |
1405 | if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, | 1646 | if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, |
@@ -1407,11 +1648,17 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
1407 | dev_err(adapter->dev, "%s: Failed to read " | 1648 | dev_err(adapter->dev, "%s: Failed to read " |
1408 | "interrupt status during fw dnld.\n", | 1649 | "interrupt status during fw dnld.\n", |
1409 | __func__); | 1650 | __func__); |
1651 | pci_unmap_single(card->dev, buf_pa, skb->len, | ||
1652 | PCI_DMA_TODEVICE); | ||
1410 | ret = -1; | 1653 | ret = -1; |
1411 | goto done; | 1654 | goto done; |
1412 | } | 1655 | } |
1413 | } while ((ireg_intr & CPU_INTR_DOOR_BELL) == | 1656 | } while ((ireg_intr & CPU_INTR_DOOR_BELL) == |
1414 | CPU_INTR_DOOR_BELL); | 1657 | CPU_INTR_DOOR_BELL); |
1658 | |||
1659 | pci_unmap_single(card->dev, buf_pa, skb->len, | ||
1660 | PCI_DMA_TODEVICE); | ||
1661 | |||
1415 | offset += txlen; | 1662 | offset += txlen; |
1416 | } while (true); | 1663 | } while (true); |
1417 | 1664 | ||
@@ -1594,39 +1841,40 @@ exit: | |||
1594 | static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | 1841 | static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) |
1595 | { | 1842 | { |
1596 | int ret; | 1843 | int ret; |
1597 | u32 pcie_ireg = 0; | 1844 | u32 pcie_ireg; |
1598 | unsigned long flags; | 1845 | unsigned long flags; |
1599 | 1846 | ||
1600 | spin_lock_irqsave(&adapter->int_lock, flags); | 1847 | spin_lock_irqsave(&adapter->int_lock, flags); |
1601 | /* Clear out unused interrupts */ | 1848 | /* Clear out unused interrupts */ |
1602 | adapter->int_status &= HOST_INTR_MASK; | 1849 | pcie_ireg = adapter->int_status; |
1850 | adapter->int_status = 0; | ||
1603 | spin_unlock_irqrestore(&adapter->int_lock, flags); | 1851 | spin_unlock_irqrestore(&adapter->int_lock, flags); |
1604 | 1852 | ||
1605 | while (adapter->int_status & HOST_INTR_MASK) { | 1853 | while (pcie_ireg & HOST_INTR_MASK) { |
1606 | if (adapter->int_status & HOST_INTR_DNLD_DONE) { | 1854 | if (pcie_ireg & HOST_INTR_DNLD_DONE) { |
1607 | adapter->int_status &= ~HOST_INTR_DNLD_DONE; | 1855 | pcie_ireg &= ~HOST_INTR_DNLD_DONE; |
1608 | if (adapter->data_sent) { | 1856 | dev_dbg(adapter->dev, "info: TX DNLD Done\n"); |
1609 | dev_dbg(adapter->dev, "info: DATA sent intr\n"); | 1857 | ret = mwifiex_pcie_send_data_complete(adapter); |
1610 | adapter->data_sent = false; | 1858 | if (ret) |
1611 | } | 1859 | return ret; |
1612 | } | 1860 | } |
1613 | if (adapter->int_status & HOST_INTR_UPLD_RDY) { | 1861 | if (pcie_ireg & HOST_INTR_UPLD_RDY) { |
1614 | adapter->int_status &= ~HOST_INTR_UPLD_RDY; | 1862 | pcie_ireg &= ~HOST_INTR_UPLD_RDY; |
1615 | dev_dbg(adapter->dev, "info: Rx DATA\n"); | 1863 | dev_dbg(adapter->dev, "info: Rx DATA\n"); |
1616 | ret = mwifiex_pcie_process_recv_data(adapter); | 1864 | ret = mwifiex_pcie_process_recv_data(adapter); |
1617 | if (ret) | 1865 | if (ret) |
1618 | return ret; | 1866 | return ret; |
1619 | } | 1867 | } |
1620 | if (adapter->int_status & HOST_INTR_EVENT_RDY) { | 1868 | if (pcie_ireg & HOST_INTR_EVENT_RDY) { |
1621 | adapter->int_status &= ~HOST_INTR_EVENT_RDY; | 1869 | pcie_ireg &= ~HOST_INTR_EVENT_RDY; |
1622 | dev_dbg(adapter->dev, "info: Rx EVENT\n"); | 1870 | dev_dbg(adapter->dev, "info: Rx EVENT\n"); |
1623 | ret = mwifiex_pcie_process_event_ready(adapter); | 1871 | ret = mwifiex_pcie_process_event_ready(adapter); |
1624 | if (ret) | 1872 | if (ret) |
1625 | return ret; | 1873 | return ret; |
1626 | } | 1874 | } |
1627 | 1875 | ||
1628 | if (adapter->int_status & HOST_INTR_CMD_DONE) { | 1876 | if (pcie_ireg & HOST_INTR_CMD_DONE) { |
1629 | adapter->int_status &= ~HOST_INTR_CMD_DONE; | 1877 | pcie_ireg &= ~HOST_INTR_CMD_DONE; |
1630 | if (adapter->cmd_sent) { | 1878 | if (adapter->cmd_sent) { |
1631 | dev_dbg(adapter->dev, | 1879 | dev_dbg(adapter->dev, |
1632 | "info: CMD sent Interrupt\n"); | 1880 | "info: CMD sent Interrupt\n"); |
@@ -1654,8 +1902,6 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | |||
1654 | "Write register failed\n"); | 1902 | "Write register failed\n"); |
1655 | return -1; | 1903 | return -1; |
1656 | } | 1904 | } |
1657 | adapter->int_status |= pcie_ireg; | ||
1658 | adapter->int_status &= HOST_INTR_MASK; | ||
1659 | } | 1905 | } |
1660 | 1906 | ||
1661 | } | 1907 | } |
@@ -1687,7 +1933,7 @@ static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type, | |||
1687 | } | 1933 | } |
1688 | 1934 | ||
1689 | if (type == MWIFIEX_TYPE_DATA) | 1935 | if (type == MWIFIEX_TYPE_DATA) |
1690 | return mwifiex_pcie_send_data(adapter, skb); | 1936 | return mwifiex_pcie_send_data(adapter, skb, tx_param); |
1691 | else if (type == MWIFIEX_TYPE_CMD) | 1937 | else if (type == MWIFIEX_TYPE_CMD) |
1692 | return mwifiex_pcie_send_cmd(adapter, skb); | 1938 | return mwifiex_pcie_send_cmd(adapter, skb); |
1693 | 1939 | ||
@@ -1814,15 +2060,8 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter) | |||
1814 | struct pcie_service_card *card = adapter->card; | 2060 | struct pcie_service_card *card = adapter->card; |
1815 | struct pci_dev *pdev = card->dev; | 2061 | struct pci_dev *pdev = card->dev; |
1816 | 2062 | ||
1817 | mwifiex_pcie_delete_sleep_cookie_buf(adapter); | ||
1818 | mwifiex_pcie_delete_cmdrsp_buf(adapter); | ||
1819 | mwifiex_pcie_delete_evtbd_ring(adapter); | ||
1820 | mwifiex_pcie_delete_rxbd_ring(adapter); | ||
1821 | mwifiex_pcie_delete_txbd_ring(adapter); | ||
1822 | card->cmdrsp_buf = NULL; | ||
1823 | |||
1824 | dev_dbg(adapter->dev, "Clearing driver ready signature\n"); | ||
1825 | if (user_rmmod) { | 2063 | if (user_rmmod) { |
2064 | dev_dbg(adapter->dev, "Clearing driver ready signature\n"); | ||
1826 | if (mwifiex_write_reg(adapter, REG_DRV_READY, 0x00000000)) | 2065 | if (mwifiex_write_reg(adapter, REG_DRV_READY, 0x00000000)) |
1827 | dev_err(adapter->dev, | 2066 | dev_err(adapter->dev, |
1828 | "Failed to write driver not-ready signature\n"); | 2067 | "Failed to write driver not-ready signature\n"); |
@@ -1879,6 +2118,13 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter) | |||
1879 | if (card) { | 2118 | if (card) { |
1880 | dev_dbg(adapter->dev, "%s(): calling free_irq()\n", __func__); | 2119 | dev_dbg(adapter->dev, "%s(): calling free_irq()\n", __func__); |
1881 | free_irq(card->dev->irq, card->dev); | 2120 | free_irq(card->dev->irq, card->dev); |
2121 | |||
2122 | mwifiex_pcie_delete_sleep_cookie_buf(adapter); | ||
2123 | mwifiex_pcie_delete_cmdrsp_buf(adapter); | ||
2124 | mwifiex_pcie_delete_evtbd_ring(adapter); | ||
2125 | mwifiex_pcie_delete_rxbd_ring(adapter); | ||
2126 | mwifiex_pcie_delete_txbd_ring(adapter); | ||
2127 | card->cmdrsp_buf = NULL; | ||
1882 | } | 2128 | } |
1883 | } | 2129 | } |
1884 | 2130 | ||
@@ -1900,6 +2146,8 @@ static struct mwifiex_if_ops pcie_ops = { | |||
1900 | .event_complete = mwifiex_pcie_event_complete, | 2146 | .event_complete = mwifiex_pcie_event_complete, |
1901 | .update_mp_end_port = NULL, | 2147 | .update_mp_end_port = NULL, |
1902 | .cleanup_mpa_buf = NULL, | 2148 | .cleanup_mpa_buf = NULL, |
2149 | .init_fw_port = mwifiex_pcie_init_fw_port, | ||
2150 | .clean_pcie_ring = mwifiex_clean_pcie_ring_buf, | ||
1903 | }; | 2151 | }; |
1904 | 2152 | ||
1905 | /* | 2153 | /* |
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h index 2f218f9a3fd3..37eeb2ca6b29 100644 --- a/drivers/net/wireless/mwifiex/pcie.h +++ b/drivers/net/wireless/mwifiex/pcie.h | |||
@@ -114,11 +114,12 @@ struct pcie_service_card { | |||
114 | struct pci_dev *dev; | 114 | struct pci_dev *dev; |
115 | struct mwifiex_adapter *adapter; | 115 | struct mwifiex_adapter *adapter; |
116 | 116 | ||
117 | u8 txbd_flush; | ||
117 | u32 txbd_wrptr; | 118 | u32 txbd_wrptr; |
118 | u32 txbd_rdptr; | 119 | u32 txbd_rdptr; |
119 | u32 txbd_ring_size; | 120 | u32 txbd_ring_size; |
120 | u8 *txbd_ring_vbase; | 121 | u8 *txbd_ring_vbase; |
121 | phys_addr_t txbd_ring_pbase; | 122 | dma_addr_t txbd_ring_pbase; |
122 | struct mwifiex_pcie_buf_desc *txbd_ring[MWIFIEX_MAX_TXRX_BD]; | 123 | struct mwifiex_pcie_buf_desc *txbd_ring[MWIFIEX_MAX_TXRX_BD]; |
123 | struct sk_buff *tx_buf_list[MWIFIEX_MAX_TXRX_BD]; | 124 | struct sk_buff *tx_buf_list[MWIFIEX_MAX_TXRX_BD]; |
124 | 125 | ||
@@ -126,7 +127,7 @@ struct pcie_service_card { | |||
126 | u32 rxbd_rdptr; | 127 | u32 rxbd_rdptr; |
127 | u32 rxbd_ring_size; | 128 | u32 rxbd_ring_size; |
128 | u8 *rxbd_ring_vbase; | 129 | u8 *rxbd_ring_vbase; |
129 | phys_addr_t rxbd_ring_pbase; | 130 | dma_addr_t rxbd_ring_pbase; |
130 | struct mwifiex_pcie_buf_desc *rxbd_ring[MWIFIEX_MAX_TXRX_BD]; | 131 | struct mwifiex_pcie_buf_desc *rxbd_ring[MWIFIEX_MAX_TXRX_BD]; |
131 | struct sk_buff *rx_buf_list[MWIFIEX_MAX_TXRX_BD]; | 132 | struct sk_buff *rx_buf_list[MWIFIEX_MAX_TXRX_BD]; |
132 | 133 | ||
@@ -134,15 +135,39 @@ struct pcie_service_card { | |||
134 | u32 evtbd_rdptr; | 135 | u32 evtbd_rdptr; |
135 | u32 evtbd_ring_size; | 136 | u32 evtbd_ring_size; |
136 | u8 *evtbd_ring_vbase; | 137 | u8 *evtbd_ring_vbase; |
137 | phys_addr_t evtbd_ring_pbase; | 138 | dma_addr_t evtbd_ring_pbase; |
138 | struct mwifiex_pcie_buf_desc *evtbd_ring[MWIFIEX_MAX_EVT_BD]; | 139 | struct mwifiex_pcie_buf_desc *evtbd_ring[MWIFIEX_MAX_EVT_BD]; |
139 | struct sk_buff *evt_buf_list[MWIFIEX_MAX_EVT_BD]; | 140 | struct sk_buff *evt_buf_list[MWIFIEX_MAX_EVT_BD]; |
140 | 141 | ||
141 | struct sk_buff *cmd_buf; | 142 | struct sk_buff *cmd_buf; |
142 | struct sk_buff *cmdrsp_buf; | 143 | struct sk_buff *cmdrsp_buf; |
143 | struct sk_buff *sleep_cookie; | 144 | u8 *sleep_cookie_vbase; |
145 | dma_addr_t sleep_cookie_pbase; | ||
144 | void __iomem *pci_mmap; | 146 | void __iomem *pci_mmap; |
145 | void __iomem *pci_mmap1; | 147 | void __iomem *pci_mmap1; |
146 | }; | 148 | }; |
147 | 149 | ||
150 | static inline int | ||
151 | mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr) | ||
152 | { | ||
153 | if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) == | ||
154 | (rdptr & MWIFIEX_TXBD_MASK)) && | ||
155 | ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) != | ||
156 | (rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) | ||
157 | return 1; | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static inline int | ||
163 | mwifiex_pcie_txbd_not_full(struct pcie_service_card *card) | ||
164 | { | ||
165 | if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) != | ||
166 | (card->txbd_rdptr & MWIFIEX_TXBD_MASK)) || | ||
167 | ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) != | ||
168 | (card->txbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) | ||
169 | return 1; | ||
170 | |||
171 | return 0; | ||
172 | } | ||
148 | #endif /* _MWIFIEX_PCIE_H */ | 173 | #endif /* _MWIFIEX_PCIE_H */ |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 5d87195390f8..c4607859d59d 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -931,7 +931,6 @@ mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv, | |||
931 | struct host_cmd_ds_pcie_details *host_spec = | 931 | struct host_cmd_ds_pcie_details *host_spec = |
932 | &cmd->params.pcie_host_spec; | 932 | &cmd->params.pcie_host_spec; |
933 | struct pcie_service_card *card = priv->adapter->card; | 933 | struct pcie_service_card *card = priv->adapter->card; |
934 | phys_addr_t *buf_pa; | ||
935 | 934 | ||
936 | cmd->command = cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS); | 935 | cmd->command = cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS); |
937 | cmd->size = cpu_to_le16(sizeof(struct | 936 | cmd->size = cpu_to_le16(sizeof(struct |
@@ -953,10 +952,11 @@ mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv, | |||
953 | host_spec->evtbd_addr_lo = (u32)(card->evtbd_ring_pbase); | 952 | host_spec->evtbd_addr_lo = (u32)(card->evtbd_ring_pbase); |
954 | host_spec->evtbd_addr_hi = (u32)(((u64)card->evtbd_ring_pbase)>>32); | 953 | host_spec->evtbd_addr_hi = (u32)(((u64)card->evtbd_ring_pbase)>>32); |
955 | host_spec->evtbd_count = MWIFIEX_MAX_EVT_BD; | 954 | host_spec->evtbd_count = MWIFIEX_MAX_EVT_BD; |
956 | if (card->sleep_cookie) { | 955 | if (card->sleep_cookie_vbase) { |
957 | buf_pa = MWIFIEX_SKB_PACB(card->sleep_cookie); | 956 | host_spec->sleep_cookie_addr_lo = |
958 | host_spec->sleep_cookie_addr_lo = (u32) *buf_pa; | 957 | (u32)(card->sleep_cookie_pbase); |
959 | host_spec->sleep_cookie_addr_hi = (u32) (((u64)*buf_pa) >> 32); | 958 | host_spec->sleep_cookie_addr_hi = |
959 | (u32)(((u64)(card->sleep_cookie_pbase)) >> 32); | ||
960 | dev_dbg(priv->adapter->dev, "sleep_cook_lo phy addr: 0x%x\n", | 960 | dev_dbg(priv->adapter->dev, "sleep_cook_lo phy addr: 0x%x\n", |
961 | host_spec->sleep_cookie_addr_lo); | 961 | host_spec->sleep_cookie_addr_lo); |
962 | } | 962 | } |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 60e88b58039d..f542bb8ccbc8 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -283,6 +283,20 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
283 | if (ret) | 283 | if (ret) |
284 | goto done; | 284 | goto done; |
285 | 285 | ||
286 | if (bss_desc) { | ||
287 | u8 config_bands = 0; | ||
288 | |||
289 | if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band) | ||
290 | == HostCmd_SCAN_RADIO_TYPE_BG) | ||
291 | config_bands = BAND_B | BAND_G | BAND_GN; | ||
292 | else | ||
293 | config_bands = BAND_A | BAND_AN; | ||
294 | |||
295 | if (!((config_bands | adapter->fw_bands) & | ||
296 | ~adapter->fw_bands)) | ||
297 | adapter->config_bands = config_bands; | ||
298 | } | ||
299 | |||
286 | ret = mwifiex_check_network_compatibility(priv, bss_desc); | 300 | ret = mwifiex_check_network_compatibility(priv, bss_desc); |
287 | if (ret) | 301 | if (ret) |
288 | goto done; | 302 | goto done; |
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 8c80024c30ff..296faec14365 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -117,14 +117,16 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, | |||
117 | dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); | 117 | dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); |
118 | break; | 118 | break; |
119 | case -1: | 119 | case -1: |
120 | adapter->data_sent = false; | 120 | if (adapter->iface_type != MWIFIEX_PCIE) |
121 | adapter->data_sent = false; | ||
121 | dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n", | 122 | dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n", |
122 | ret); | 123 | ret); |
123 | adapter->dbg.num_tx_host_to_card_failure++; | 124 | adapter->dbg.num_tx_host_to_card_failure++; |
124 | mwifiex_write_data_complete(adapter, skb, 0, ret); | 125 | mwifiex_write_data_complete(adapter, skb, 0, ret); |
125 | break; | 126 | break; |
126 | case -EINPROGRESS: | 127 | case -EINPROGRESS: |
127 | adapter->data_sent = false; | 128 | if (adapter->iface_type != MWIFIEX_PCIE) |
129 | adapter->data_sent = false; | ||
128 | break; | 130 | break; |
129 | case 0: | 131 | case 0: |
130 | mwifiex_write_data_complete(adapter, skb, 0, ret); | 132 | mwifiex_write_data_complete(adapter, skb, 0, ret); |
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 8dd72240f162..6e76a15a8950 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -219,6 +219,7 @@ void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config) | |||
219 | config->rts_threshold = 0x7FFF; | 219 | config->rts_threshold = 0x7FFF; |
220 | config->frag_threshold = 0x7FFF; | 220 | config->frag_threshold = 0x7FFF; |
221 | config->retry_limit = 0x7F; | 221 | config->retry_limit = 0x7F; |
222 | config->qos_info = 0xFF; | ||
222 | } | 223 | } |
223 | 224 | ||
224 | /* This function parses BSS related parameters from structure | 225 | /* This function parses BSS related parameters from structure |
@@ -297,6 +298,38 @@ mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size) | |||
297 | return; | 298 | return; |
298 | } | 299 | } |
299 | 300 | ||
301 | /* This function parses WMM related parameters from cfg80211_ap_settings | ||
302 | * structure and updates bss_config structure. | ||
303 | */ | ||
304 | void | ||
305 | mwifiex_set_wmm_params(struct mwifiex_private *priv, | ||
306 | struct mwifiex_uap_bss_param *bss_cfg, | ||
307 | struct cfg80211_ap_settings *params) | ||
308 | { | ||
309 | const u8 *vendor_ie; | ||
310 | struct ieee_types_header *wmm_ie; | ||
311 | u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02}; | ||
312 | |||
313 | vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, | ||
314 | WLAN_OUI_TYPE_MICROSOFT_WMM, | ||
315 | params->beacon.tail, | ||
316 | params->beacon.tail_len); | ||
317 | if (vendor_ie) { | ||
318 | wmm_ie = (struct ieee_types_header *)vendor_ie; | ||
319 | memcpy(&bss_cfg->wmm_info, wmm_ie + 1, | ||
320 | sizeof(bss_cfg->wmm_info)); | ||
321 | priv->wmm_enabled = 1; | ||
322 | } else { | ||
323 | memset(&bss_cfg->wmm_info, 0, sizeof(bss_cfg->wmm_info)); | ||
324 | memcpy(&bss_cfg->wmm_info.oui, wmm_oui, sizeof(wmm_oui)); | ||
325 | bss_cfg->wmm_info.subtype = MWIFIEX_WMM_SUBTYPE; | ||
326 | bss_cfg->wmm_info.version = MWIFIEX_WMM_VERSION; | ||
327 | priv->wmm_enabled = 0; | ||
328 | } | ||
329 | |||
330 | bss_cfg->qos_info = 0x00; | ||
331 | return; | ||
332 | } | ||
300 | /* This function parses BSS related parameters from structure | 333 | /* This function parses BSS related parameters from structure |
301 | * and prepares TLVs specific to WEP encryption. | 334 | * and prepares TLVs specific to WEP encryption. |
302 | * These TLVs are appended to command buffer. | 335 | * These TLVs are appended to command buffer. |
@@ -354,6 +387,7 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) | |||
354 | struct host_cmd_tlv_rates *tlv_rates; | 387 | struct host_cmd_tlv_rates *tlv_rates; |
355 | struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer; | 388 | struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer; |
356 | struct mwifiex_ie_types_htcap *htcap; | 389 | struct mwifiex_ie_types_htcap *htcap; |
390 | struct mwifiex_ie_types_wmmcap *wmm_cap; | ||
357 | struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; | 391 | struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; |
358 | int i; | 392 | int i; |
359 | u16 cmd_size = *param_size; | 393 | u16 cmd_size = *param_size; |
@@ -507,6 +541,16 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) | |||
507 | tlv += sizeof(struct mwifiex_ie_types_htcap); | 541 | tlv += sizeof(struct mwifiex_ie_types_htcap); |
508 | } | 542 | } |
509 | 543 | ||
544 | if (bss_cfg->wmm_info.qos_info != 0xFF) { | ||
545 | wmm_cap = (struct mwifiex_ie_types_wmmcap *)tlv; | ||
546 | wmm_cap->header.type = cpu_to_le16(WLAN_EID_VENDOR_SPECIFIC); | ||
547 | wmm_cap->header.len = cpu_to_le16(sizeof(wmm_cap->wmm_info)); | ||
548 | memcpy(&wmm_cap->wmm_info, &bss_cfg->wmm_info, | ||
549 | sizeof(wmm_cap->wmm_info)); | ||
550 | cmd_size += sizeof(struct mwifiex_ie_types_wmmcap); | ||
551 | tlv += sizeof(struct mwifiex_ie_types_wmmcap); | ||
552 | } | ||
553 | |||
510 | if (bss_cfg->sta_ao_timer) { | 554 | if (bss_cfg->sta_ao_timer) { |
511 | ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; | 555 | ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; |
512 | ao_timer->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER); | 556 | ao_timer->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER); |
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 63ac9f2d11ae..5d4a10a8a005 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c | |||
@@ -786,21 +786,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
786 | return 0; | 786 | return 0; |
787 | } | 787 | } |
788 | 788 | ||
789 | /* This function reads one block of firmware data. */ | ||
790 | static int mwifiex_get_fw_data(struct mwifiex_adapter *adapter, | ||
791 | u32 offset, u32 len, u8 *buf) | ||
792 | { | ||
793 | if (!buf || !len) | ||
794 | return -1; | ||
795 | |||
796 | if (offset + len > adapter->firmware->size) | ||
797 | return -1; | ||
798 | |||
799 | memcpy(buf, adapter->firmware->data + offset, len); | ||
800 | |||
801 | return 0; | ||
802 | } | ||
803 | |||
804 | static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | 789 | static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, |
805 | struct mwifiex_fw_image *fw) | 790 | struct mwifiex_fw_image *fw) |
806 | { | 791 | { |
@@ -836,23 +821,14 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
836 | dlen = 0; | 821 | dlen = 0; |
837 | } else { | 822 | } else { |
838 | /* copy the header of the fw_data to get the length */ | 823 | /* copy the header of the fw_data to get the length */ |
839 | if (firmware) | 824 | memcpy(&fwdata->fw_hdr, &firmware[tlen], |
840 | memcpy(&fwdata->fw_hdr, &firmware[tlen], | 825 | sizeof(struct fw_header)); |
841 | sizeof(struct fw_header)); | ||
842 | else | ||
843 | mwifiex_get_fw_data(adapter, tlen, | ||
844 | sizeof(struct fw_header), | ||
845 | (u8 *)&fwdata->fw_hdr); | ||
846 | 826 | ||
847 | dlen = le32_to_cpu(fwdata->fw_hdr.data_len); | 827 | dlen = le32_to_cpu(fwdata->fw_hdr.data_len); |
848 | dnld_cmd = le32_to_cpu(fwdata->fw_hdr.dnld_cmd); | 828 | dnld_cmd = le32_to_cpu(fwdata->fw_hdr.dnld_cmd); |
849 | tlen += sizeof(struct fw_header); | 829 | tlen += sizeof(struct fw_header); |
850 | 830 | ||
851 | if (firmware) | 831 | memcpy(fwdata->data, &firmware[tlen], dlen); |
852 | memcpy(fwdata->data, &firmware[tlen], dlen); | ||
853 | else | ||
854 | mwifiex_get_fw_data(adapter, tlen, dlen, | ||
855 | (u8 *)fwdata->data); | ||
856 | 832 | ||
857 | fwdata->seq_num = cpu_to_le32(fw_seqnum); | 833 | fwdata->seq_num = cpu_to_le32(fw_seqnum); |
858 | tlen += dlen; | 834 | tlen += dlen; |
diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h index f6d36b9654a0..cb2d0582bd36 100644 --- a/drivers/net/wireless/mwifiex/util.h +++ b/drivers/net/wireless/mwifiex/util.h | |||
@@ -22,16 +22,16 @@ | |||
22 | 22 | ||
23 | static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb) | 23 | static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb) |
24 | { | 24 | { |
25 | return (struct mwifiex_rxinfo *)(skb->cb + sizeof(phys_addr_t)); | 25 | return (struct mwifiex_rxinfo *)(skb->cb + sizeof(dma_addr_t)); |
26 | } | 26 | } |
27 | 27 | ||
28 | static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) | 28 | static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) |
29 | { | 29 | { |
30 | return (struct mwifiex_txinfo *)(skb->cb + sizeof(phys_addr_t)); | 30 | return (struct mwifiex_txinfo *)(skb->cb + sizeof(dma_addr_t)); |
31 | } | 31 | } |
32 | 32 | ||
33 | static inline phys_addr_t *MWIFIEX_SKB_PACB(struct sk_buff *skb) | 33 | static inline void MWIFIEX_SKB_PACB(struct sk_buff *skb, dma_addr_t *buf_pa) |
34 | { | 34 | { |
35 | return (phys_addr_t *)skb->cb; | 35 | memcpy(buf_pa, skb->cb, sizeof(dma_addr_t)); |
36 | } | 36 | } |
37 | #endif /* !_MWIFIEX_UTIL_H_ */ | 37 | #endif /* !_MWIFIEX_UTIL_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 818f871ae987..135d96df2063 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -568,6 +568,8 @@ mwifiex_clean_txrx(struct mwifiex_private *priv) | |||
568 | mwifiex_wmm_delete_all_ralist(priv); | 568 | mwifiex_wmm_delete_all_ralist(priv); |
569 | memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); | 569 | memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); |
570 | 570 | ||
571 | if (priv->adapter->if_ops.clean_pcie_ring) | ||
572 | priv->adapter->if_ops.clean_pcie_ring(priv->adapter); | ||
571 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); | 573 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); |
572 | } | 574 | } |
573 | 575 | ||
@@ -1206,13 +1208,15 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, | |||
1206 | ra_list_flags); | 1208 | ra_list_flags); |
1207 | break; | 1209 | break; |
1208 | case -1: | 1210 | case -1: |
1209 | adapter->data_sent = false; | 1211 | if (adapter->iface_type != MWIFIEX_PCIE) |
1212 | adapter->data_sent = false; | ||
1210 | dev_err(adapter->dev, "host_to_card failed: %#x\n", ret); | 1213 | dev_err(adapter->dev, "host_to_card failed: %#x\n", ret); |
1211 | adapter->dbg.num_tx_host_to_card_failure++; | 1214 | adapter->dbg.num_tx_host_to_card_failure++; |
1212 | mwifiex_write_data_complete(adapter, skb, 0, ret); | 1215 | mwifiex_write_data_complete(adapter, skb, 0, ret); |
1213 | break; | 1216 | break; |
1214 | case -EINPROGRESS: | 1217 | case -EINPROGRESS: |
1215 | adapter->data_sent = false; | 1218 | if (adapter->iface_type != MWIFIEX_PCIE) |
1219 | adapter->data_sent = false; | ||
1216 | default: | 1220 | default: |
1217 | break; | 1221 | break; |
1218 | } | 1222 | } |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 83564d36e801..224cf917744a 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -101,6 +101,18 @@ MODULE_PARM_DESC(ap_mode_default, | |||
101 | #define MWL8K_MAX_TX_QUEUES (MWL8K_TX_WMM_QUEUES + MWL8K_MAX_AMPDU_QUEUES) | 101 | #define MWL8K_MAX_TX_QUEUES (MWL8K_TX_WMM_QUEUES + MWL8K_MAX_AMPDU_QUEUES) |
102 | #define mwl8k_tx_queues(priv) (MWL8K_TX_WMM_QUEUES + (priv)->num_ampdu_queues) | 102 | #define mwl8k_tx_queues(priv) (MWL8K_TX_WMM_QUEUES + (priv)->num_ampdu_queues) |
103 | 103 | ||
104 | /* txpriorities are mapped with hw queues. | ||
105 | * Each hw queue has a txpriority. | ||
106 | */ | ||
107 | #define TOTAL_HW_TX_QUEUES 8 | ||
108 | |||
109 | /* Each HW queue can have one AMPDU stream. | ||
110 | * But, because one of the hw queue is reserved, | ||
111 | * maximum AMPDU queues that can be created are | ||
112 | * one short of total tx queues. | ||
113 | */ | ||
114 | #define MWL8K_NUM_AMPDU_STREAMS (TOTAL_HW_TX_QUEUES - 1) | ||
115 | |||
104 | struct rxd_ops { | 116 | struct rxd_ops { |
105 | int rxd_size; | 117 | int rxd_size; |
106 | void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr); | 118 | void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr); |
@@ -160,7 +172,6 @@ struct mwl8k_ampdu_stream { | |||
160 | u8 tid; | 172 | u8 tid; |
161 | u8 state; | 173 | u8 state; |
162 | u8 idx; | 174 | u8 idx; |
163 | u8 txq_idx; /* index of this stream in priv->txq */ | ||
164 | }; | 175 | }; |
165 | 176 | ||
166 | struct mwl8k_priv { | 177 | struct mwl8k_priv { |
@@ -202,6 +213,8 @@ struct mwl8k_priv { | |||
202 | int fw_mutex_depth; | 213 | int fw_mutex_depth; |
203 | struct completion *hostcmd_wait; | 214 | struct completion *hostcmd_wait; |
204 | 215 | ||
216 | atomic_t watchdog_event_pending; | ||
217 | |||
205 | /* lock held over TX and TX reap */ | 218 | /* lock held over TX and TX reap */ |
206 | spinlock_t tx_lock; | 219 | spinlock_t tx_lock; |
207 | 220 | ||
@@ -1516,6 +1529,9 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) | |||
1516 | return -EBUSY; | 1529 | return -EBUSY; |
1517 | } | 1530 | } |
1518 | 1531 | ||
1532 | if (atomic_read(&priv->watchdog_event_pending)) | ||
1533 | return 0; | ||
1534 | |||
1519 | /* | 1535 | /* |
1520 | * The TX queues are stopped at this point, so this test | 1536 | * The TX queues are stopped at this point, so this test |
1521 | * doesn't need to take ->tx_lock. | 1537 | * doesn't need to take ->tx_lock. |
@@ -1537,6 +1553,14 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) | |||
1537 | spin_unlock_bh(&priv->tx_lock); | 1553 | spin_unlock_bh(&priv->tx_lock); |
1538 | timeout = wait_for_completion_timeout(&tx_wait, | 1554 | timeout = wait_for_completion_timeout(&tx_wait, |
1539 | msecs_to_jiffies(MWL8K_TX_WAIT_TIMEOUT_MS)); | 1555 | msecs_to_jiffies(MWL8K_TX_WAIT_TIMEOUT_MS)); |
1556 | |||
1557 | if (atomic_read(&priv->watchdog_event_pending)) { | ||
1558 | spin_lock_bh(&priv->tx_lock); | ||
1559 | priv->tx_wait = NULL; | ||
1560 | spin_unlock_bh(&priv->tx_lock); | ||
1561 | return 0; | ||
1562 | } | ||
1563 | |||
1540 | spin_lock_bh(&priv->tx_lock); | 1564 | spin_lock_bh(&priv->tx_lock); |
1541 | 1565 | ||
1542 | if (timeout) { | 1566 | if (timeout) { |
@@ -1564,6 +1588,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) | |||
1564 | 1588 | ||
1565 | rc = -ETIMEDOUT; | 1589 | rc = -ETIMEDOUT; |
1566 | } | 1590 | } |
1591 | priv->tx_wait = NULL; | ||
1567 | spin_unlock_bh(&priv->tx_lock); | 1592 | spin_unlock_bh(&priv->tx_lock); |
1568 | 1593 | ||
1569 | return rc; | 1594 | return rc; |
@@ -1734,14 +1759,13 @@ mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid) | |||
1734 | struct mwl8k_priv *priv = hw->priv; | 1759 | struct mwl8k_priv *priv = hw->priv; |
1735 | int i; | 1760 | int i; |
1736 | 1761 | ||
1737 | for (i = 0; i < priv->num_ampdu_queues; i++) { | 1762 | for (i = 0; i < MWL8K_NUM_AMPDU_STREAMS; i++) { |
1738 | stream = &priv->ampdu[i]; | 1763 | stream = &priv->ampdu[i]; |
1739 | if (stream->state == AMPDU_NO_STREAM) { | 1764 | if (stream->state == AMPDU_NO_STREAM) { |
1740 | stream->sta = sta; | 1765 | stream->sta = sta; |
1741 | stream->state = AMPDU_STREAM_NEW; | 1766 | stream->state = AMPDU_STREAM_NEW; |
1742 | stream->tid = tid; | 1767 | stream->tid = tid; |
1743 | stream->idx = i; | 1768 | stream->idx = i; |
1744 | stream->txq_idx = MWL8K_TX_WMM_QUEUES + i; | ||
1745 | wiphy_debug(hw->wiphy, "Added a new stream for %pM %d", | 1769 | wiphy_debug(hw->wiphy, "Added a new stream for %pM %d", |
1746 | sta->addr, tid); | 1770 | sta->addr, tid); |
1747 | return stream; | 1771 | return stream; |
@@ -1782,7 +1806,7 @@ mwl8k_lookup_stream(struct ieee80211_hw *hw, u8 *addr, u8 tid) | |||
1782 | struct mwl8k_priv *priv = hw->priv; | 1806 | struct mwl8k_priv *priv = hw->priv; |
1783 | int i; | 1807 | int i; |
1784 | 1808 | ||
1785 | for (i = 0 ; i < priv->num_ampdu_queues; i++) { | 1809 | for (i = 0; i < MWL8K_NUM_AMPDU_STREAMS; i++) { |
1786 | struct mwl8k_ampdu_stream *stream; | 1810 | struct mwl8k_ampdu_stream *stream; |
1787 | stream = &priv->ampdu[i]; | 1811 | stream = &priv->ampdu[i]; |
1788 | if (stream->state == AMPDU_NO_STREAM) | 1812 | if (stream->state == AMPDU_NO_STREAM) |
@@ -1829,6 +1853,13 @@ static inline void mwl8k_tx_count_packet(struct ieee80211_sta *sta, u8 tid) | |||
1829 | tx_stats->pkts++; | 1853 | tx_stats->pkts++; |
1830 | } | 1854 | } |
1831 | 1855 | ||
1856 | /* The hardware ampdu queues start from 5. | ||
1857 | * txpriorities for ampdu queues are | ||
1858 | * 5 6 7 0 1 2 3 4 ie., queue 5 is highest | ||
1859 | * and queue 3 is lowest (queue 4 is reserved) | ||
1860 | */ | ||
1861 | #define BA_QUEUE 5 | ||
1862 | |||
1832 | static void | 1863 | static void |
1833 | mwl8k_txq_xmit(struct ieee80211_hw *hw, | 1864 | mwl8k_txq_xmit(struct ieee80211_hw *hw, |
1834 | int index, | 1865 | int index, |
@@ -1928,8 +1959,13 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, | |||
1928 | stream = mwl8k_lookup_stream(hw, sta->addr, tid); | 1959 | stream = mwl8k_lookup_stream(hw, sta->addr, tid); |
1929 | if (stream != NULL) { | 1960 | if (stream != NULL) { |
1930 | if (stream->state == AMPDU_STREAM_ACTIVE) { | 1961 | if (stream->state == AMPDU_STREAM_ACTIVE) { |
1931 | txpriority = stream->txq_idx; | 1962 | WARN_ON(!(qos & MWL8K_QOS_ACK_POLICY_BLOCKACK)); |
1932 | index = stream->txq_idx; | 1963 | txpriority = (BA_QUEUE + stream->idx) % |
1964 | TOTAL_HW_TX_QUEUES; | ||
1965 | if (stream->idx <= 1) | ||
1966 | index = stream->idx + | ||
1967 | MWL8K_TX_WMM_QUEUES; | ||
1968 | |||
1933 | } else if (stream->state == AMPDU_STREAM_NEW) { | 1969 | } else if (stream->state == AMPDU_STREAM_NEW) { |
1934 | /* We get here if the driver sends us packets | 1970 | /* We get here if the driver sends us packets |
1935 | * after we've initiated a stream, but before | 1971 | * after we've initiated a stream, but before |
@@ -1971,6 +2007,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, | |||
1971 | } | 2007 | } |
1972 | } | 2008 | } |
1973 | spin_unlock(&priv->stream_lock); | 2009 | spin_unlock(&priv->stream_lock); |
2010 | } else { | ||
2011 | qos &= ~MWL8K_QOS_ACK_POLICY_MASK; | ||
2012 | qos |= MWL8K_QOS_ACK_POLICY_NORMAL; | ||
1974 | } | 2013 | } |
1975 | 2014 | ||
1976 | dma = pci_map_single(priv->pdev, skb->data, | 2015 | dma = pci_map_single(priv->pdev, skb->data, |
@@ -3578,7 +3617,11 @@ static int mwl8k_cmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap) | |||
3578 | return rc; | 3617 | return rc; |
3579 | } | 3618 | } |
3580 | 3619 | ||
3581 | #define INVALID_BA 0xAA | 3620 | #define MWL8K_WMM_QUEUE_NUMBER 3 |
3621 | |||
3622 | static void mwl8k_destroy_ba(struct ieee80211_hw *hw, | ||
3623 | u8 idx); | ||
3624 | |||
3582 | static void mwl8k_watchdog_ba_events(struct work_struct *work) | 3625 | static void mwl8k_watchdog_ba_events(struct work_struct *work) |
3583 | { | 3626 | { |
3584 | int rc; | 3627 | int rc; |
@@ -3586,24 +3629,41 @@ static void mwl8k_watchdog_ba_events(struct work_struct *work) | |||
3586 | struct mwl8k_ampdu_stream *streams; | 3629 | struct mwl8k_ampdu_stream *streams; |
3587 | struct mwl8k_priv *priv = | 3630 | struct mwl8k_priv *priv = |
3588 | container_of(work, struct mwl8k_priv, watchdog_ba_handle); | 3631 | container_of(work, struct mwl8k_priv, watchdog_ba_handle); |
3632 | struct ieee80211_hw *hw = priv->hw; | ||
3633 | int i; | ||
3634 | u32 status = 0; | ||
3635 | |||
3636 | mwl8k_fw_lock(hw); | ||
3589 | 3637 | ||
3590 | rc = mwl8k_cmd_get_watchdog_bitmap(priv->hw, &bitmap); | 3638 | rc = mwl8k_cmd_get_watchdog_bitmap(priv->hw, &bitmap); |
3591 | if (rc) | 3639 | if (rc) |
3592 | return; | 3640 | goto done; |
3593 | 3641 | ||
3594 | if (bitmap == INVALID_BA) | 3642 | spin_lock(&priv->stream_lock); |
3595 | return; | ||
3596 | 3643 | ||
3597 | /* the bitmap is the hw queue number. Map it to the ampdu queue. */ | 3644 | /* the bitmap is the hw queue number. Map it to the ampdu queue. */ |
3598 | stream_index = bitmap - MWL8K_TX_WMM_QUEUES; | 3645 | for (i = 0; i < TOTAL_HW_TX_QUEUES; i++) { |
3599 | 3646 | if (bitmap & (1 << i)) { | |
3600 | BUG_ON(stream_index >= priv->num_ampdu_queues); | 3647 | stream_index = (i + MWL8K_WMM_QUEUE_NUMBER) % |
3601 | 3648 | TOTAL_HW_TX_QUEUES; | |
3602 | streams = &priv->ampdu[stream_index]; | 3649 | streams = &priv->ampdu[stream_index]; |
3603 | 3650 | if (streams->state == AMPDU_STREAM_ACTIVE) { | |
3604 | if (streams->state == AMPDU_STREAM_ACTIVE) | 3651 | ieee80211_stop_tx_ba_session(streams->sta, |
3605 | ieee80211_stop_tx_ba_session(streams->sta, streams->tid); | 3652 | streams->tid); |
3653 | spin_unlock(&priv->stream_lock); | ||
3654 | mwl8k_destroy_ba(hw, stream_index); | ||
3655 | spin_lock(&priv->stream_lock); | ||
3656 | } | ||
3657 | } | ||
3658 | } | ||
3606 | 3659 | ||
3660 | spin_unlock(&priv->stream_lock); | ||
3661 | done: | ||
3662 | atomic_dec(&priv->watchdog_event_pending); | ||
3663 | status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); | ||
3664 | iowrite32((status | MWL8K_A2H_INT_BA_WATCHDOG), | ||
3665 | priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); | ||
3666 | mwl8k_fw_unlock(hw); | ||
3607 | return; | 3667 | return; |
3608 | } | 3668 | } |
3609 | 3669 | ||
@@ -3763,7 +3823,7 @@ mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream, | |||
3763 | } | 3823 | } |
3764 | 3824 | ||
3765 | static void mwl8k_destroy_ba(struct ieee80211_hw *hw, | 3825 | static void mwl8k_destroy_ba(struct ieee80211_hw *hw, |
3766 | struct mwl8k_ampdu_stream *stream) | 3826 | u8 idx) |
3767 | { | 3827 | { |
3768 | struct mwl8k_cmd_bastream *cmd; | 3828 | struct mwl8k_cmd_bastream *cmd; |
3769 | 3829 | ||
@@ -3775,10 +3835,10 @@ static void mwl8k_destroy_ba(struct ieee80211_hw *hw, | |||
3775 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 3835 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
3776 | cmd->action = cpu_to_le32(MWL8K_BA_DESTROY); | 3836 | cmd->action = cpu_to_le32(MWL8K_BA_DESTROY); |
3777 | 3837 | ||
3778 | cmd->destroy_params.ba_context = cpu_to_le32(stream->idx); | 3838 | cmd->destroy_params.ba_context = cpu_to_le32(idx); |
3779 | mwl8k_post_cmd(hw, &cmd->header); | 3839 | mwl8k_post_cmd(hw, &cmd->header); |
3780 | 3840 | ||
3781 | wiphy_debug(hw->wiphy, "Deleted BA stream index %d\n", stream->idx); | 3841 | wiphy_debug(hw->wiphy, "Deleted BA stream index %d\n", idx); |
3782 | 3842 | ||
3783 | kfree(cmd); | 3843 | kfree(cmd); |
3784 | } | 3844 | } |
@@ -3875,7 +3935,30 @@ static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw, | |||
3875 | struct ieee80211_vif *vif, u8 *addr) | 3935 | struct ieee80211_vif *vif, u8 *addr) |
3876 | { | 3936 | { |
3877 | struct mwl8k_cmd_set_new_stn *cmd; | 3937 | struct mwl8k_cmd_set_new_stn *cmd; |
3878 | int rc; | 3938 | struct mwl8k_priv *priv = hw->priv; |
3939 | int rc, i; | ||
3940 | u8 idx; | ||
3941 | |||
3942 | spin_lock(&priv->stream_lock); | ||
3943 | /* Destroy any active ampdu streams for this sta */ | ||
3944 | for (i = 0; i < MWL8K_NUM_AMPDU_STREAMS; i++) { | ||
3945 | struct mwl8k_ampdu_stream *s; | ||
3946 | s = &priv->ampdu[i]; | ||
3947 | if (s->state != AMPDU_NO_STREAM) { | ||
3948 | if (memcmp(s->sta->addr, addr, ETH_ALEN) == 0) { | ||
3949 | if (s->state == AMPDU_STREAM_ACTIVE) { | ||
3950 | idx = s->idx; | ||
3951 | spin_unlock(&priv->stream_lock); | ||
3952 | mwl8k_destroy_ba(hw, idx); | ||
3953 | spin_lock(&priv->stream_lock); | ||
3954 | } else if (s->state == AMPDU_STREAM_NEW) { | ||
3955 | mwl8k_remove_stream(hw, s); | ||
3956 | } | ||
3957 | } | ||
3958 | } | ||
3959 | } | ||
3960 | |||
3961 | spin_unlock(&priv->stream_lock); | ||
3879 | 3962 | ||
3880 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 3963 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
3881 | if (cmd == NULL) | 3964 | if (cmd == NULL) |
@@ -4303,6 +4386,10 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) | |||
4303 | } | 4386 | } |
4304 | 4387 | ||
4305 | if (status & MWL8K_A2H_INT_BA_WATCHDOG) { | 4388 | if (status & MWL8K_A2H_INT_BA_WATCHDOG) { |
4389 | iowrite32(~MWL8K_A2H_INT_BA_WATCHDOG, | ||
4390 | priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); | ||
4391 | |||
4392 | atomic_inc(&priv->watchdog_event_pending); | ||
4306 | status &= ~MWL8K_A2H_INT_BA_WATCHDOG; | 4393 | status &= ~MWL8K_A2H_INT_BA_WATCHDOG; |
4307 | ieee80211_queue_work(hw, &priv->watchdog_ba_handle); | 4394 | ieee80211_queue_work(hw, &priv->watchdog_ba_handle); |
4308 | } | 4395 | } |
@@ -4446,6 +4533,8 @@ static int mwl8k_start(struct ieee80211_hw *hw) | |||
4446 | priv->irq = -1; | 4533 | priv->irq = -1; |
4447 | tasklet_disable(&priv->poll_tx_task); | 4534 | tasklet_disable(&priv->poll_tx_task); |
4448 | tasklet_disable(&priv->poll_rx_task); | 4535 | tasklet_disable(&priv->poll_rx_task); |
4536 | } else { | ||
4537 | ieee80211_wake_queues(hw); | ||
4449 | } | 4538 | } |
4450 | 4539 | ||
4451 | return rc; | 4540 | return rc; |
@@ -5094,7 +5183,7 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5094 | int i, rc = 0; | 5183 | int i, rc = 0; |
5095 | struct mwl8k_priv *priv = hw->priv; | 5184 | struct mwl8k_priv *priv = hw->priv; |
5096 | struct mwl8k_ampdu_stream *stream; | 5185 | struct mwl8k_ampdu_stream *stream; |
5097 | u8 *addr = sta->addr; | 5186 | u8 *addr = sta->addr, idx; |
5098 | struct mwl8k_sta *sta_info = MWL8K_STA(sta); | 5187 | struct mwl8k_sta *sta_info = MWL8K_STA(sta); |
5099 | 5188 | ||
5100 | if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) | 5189 | if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) |
@@ -5172,11 +5261,14 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5172 | } | 5261 | } |
5173 | ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); | 5262 | ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); |
5174 | break; | 5263 | break; |
5175 | case IEEE80211_AMPDU_TX_STOP: | 5264 | case IEEE80211_AMPDU_TX_STOP_CONT: |
5265 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
5266 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
5176 | if (stream) { | 5267 | if (stream) { |
5177 | if (stream->state == AMPDU_STREAM_ACTIVE) { | 5268 | if (stream->state == AMPDU_STREAM_ACTIVE) { |
5269 | idx = stream->idx; | ||
5178 | spin_unlock(&priv->stream_lock); | 5270 | spin_unlock(&priv->stream_lock); |
5179 | mwl8k_destroy_ba(hw, stream); | 5271 | mwl8k_destroy_ba(hw, idx); |
5180 | spin_lock(&priv->stream_lock); | 5272 | spin_lock(&priv->stream_lock); |
5181 | } | 5273 | } |
5182 | mwl8k_remove_stream(hw, stream); | 5274 | mwl8k_remove_stream(hw, stream); |
@@ -5192,8 +5284,9 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5192 | if (!rc) | 5284 | if (!rc) |
5193 | stream->state = AMPDU_STREAM_ACTIVE; | 5285 | stream->state = AMPDU_STREAM_ACTIVE; |
5194 | else { | 5286 | else { |
5287 | idx = stream->idx; | ||
5195 | spin_unlock(&priv->stream_lock); | 5288 | spin_unlock(&priv->stream_lock); |
5196 | mwl8k_destroy_ba(hw, stream); | 5289 | mwl8k_destroy_ba(hw, idx); |
5197 | spin_lock(&priv->stream_lock); | 5290 | spin_lock(&priv->stream_lock); |
5198 | wiphy_debug(hw->wiphy, | 5291 | wiphy_debug(hw->wiphy, |
5199 | "Failed adding stream for sta %pM tid %d\n", | 5292 | "Failed adding stream for sta %pM tid %d\n", |
@@ -5256,7 +5349,7 @@ enum { | |||
5256 | MWL8366, | 5349 | MWL8366, |
5257 | }; | 5350 | }; |
5258 | 5351 | ||
5259 | #define MWL8K_8366_AP_FW_API 2 | 5352 | #define MWL8K_8366_AP_FW_API 3 |
5260 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" | 5353 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" |
5261 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) | 5354 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) |
5262 | 5355 | ||
@@ -5464,6 +5557,7 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) | |||
5464 | if (priv->rxd_ops == NULL) { | 5557 | if (priv->rxd_ops == NULL) { |
5465 | wiphy_err(hw->wiphy, | 5558 | wiphy_err(hw->wiphy, |
5466 | "Driver does not have AP firmware image support for this hardware\n"); | 5559 | "Driver does not have AP firmware image support for this hardware\n"); |
5560 | rc = -ENOENT; | ||
5467 | goto err_stop_firmware; | 5561 | goto err_stop_firmware; |
5468 | } | 5562 | } |
5469 | } else { | 5563 | } else { |
@@ -5473,6 +5567,7 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) | |||
5473 | priv->sniffer_enabled = false; | 5567 | priv->sniffer_enabled = false; |
5474 | priv->wmm_enabled = false; | 5568 | priv->wmm_enabled = false; |
5475 | priv->pending_tx_pkts = 0; | 5569 | priv->pending_tx_pkts = 0; |
5570 | atomic_set(&priv->watchdog_event_pending, 0); | ||
5476 | 5571 | ||
5477 | rc = mwl8k_rxq_init(hw, 0); | 5572 | rc = mwl8k_rxq_init(hw, 0); |
5478 | if (rc) | 5573 | if (rc) |
@@ -5809,6 +5904,7 @@ static int mwl8k_probe(struct pci_dev *pdev, | |||
5809 | priv->sram = pci_iomap(pdev, 0, 0x10000); | 5904 | priv->sram = pci_iomap(pdev, 0, 0x10000); |
5810 | if (priv->sram == NULL) { | 5905 | if (priv->sram == NULL) { |
5811 | wiphy_err(hw->wiphy, "Cannot map device SRAM\n"); | 5906 | wiphy_err(hw->wiphy, "Cannot map device SRAM\n"); |
5907 | rc = -EIO; | ||
5812 | goto err_iounmap; | 5908 | goto err_iounmap; |
5813 | } | 5909 | } |
5814 | 5910 | ||
@@ -5821,6 +5917,7 @@ static int mwl8k_probe(struct pci_dev *pdev, | |||
5821 | priv->regs = pci_iomap(pdev, 2, 0x10000); | 5917 | priv->regs = pci_iomap(pdev, 2, 0x10000); |
5822 | if (priv->regs == NULL) { | 5918 | if (priv->regs == NULL) { |
5823 | wiphy_err(hw->wiphy, "Cannot map device registers\n"); | 5919 | wiphy_err(hw->wiphy, "Cannot map device registers\n"); |
5920 | rc = -EIO; | ||
5824 | goto err_iounmap; | 5921 | goto err_iounmap; |
5825 | } | 5922 | } |
5826 | } | 5923 | } |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 933e5d941937..57e3af8ebb4b 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -559,6 +559,7 @@ static int p54p_probe(struct pci_dev *pdev, | |||
559 | mem_len = pci_resource_len(pdev, 0); | 559 | mem_len = pci_resource_len(pdev, 0); |
560 | if (mem_len < sizeof(struct p54p_csr)) { | 560 | if (mem_len < sizeof(struct p54p_csr)) { |
561 | dev_err(&pdev->dev, "Too short PCI resources\n"); | 561 | dev_err(&pdev->dev, "Too short PCI resources\n"); |
562 | err = -ENODEV; | ||
562 | goto err_disable_dev; | 563 | goto err_disable_dev; |
563 | } | 564 | } |
564 | 565 | ||
@@ -568,8 +569,10 @@ static int p54p_probe(struct pci_dev *pdev, | |||
568 | goto err_disable_dev; | 569 | goto err_disable_dev; |
569 | } | 570 | } |
570 | 571 | ||
571 | if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) || | 572 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
572 | pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { | 573 | if (!err) |
574 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
575 | if (err) { | ||
573 | dev_err(&pdev->dev, "No suitable DMA available\n"); | 576 | dev_err(&pdev->dev, "No suitable DMA available\n"); |
574 | goto err_free_reg; | 577 | goto err_free_reg; |
575 | } | 578 | } |
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 4e44b1af119a..1c22b81e6ef3 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c | |||
@@ -1503,6 +1503,7 @@ static int prism54_get_auth(struct net_device *ndev, | |||
1503 | case DOT11_AUTH_BOTH: | 1503 | case DOT11_AUTH_BOTH: |
1504 | case DOT11_AUTH_SK: | 1504 | case DOT11_AUTH_SK: |
1505 | param->value = IW_AUTH_ALG_SHARED_KEY; | 1505 | param->value = IW_AUTH_ALG_SHARED_KEY; |
1506 | break; | ||
1506 | case DOT11_AUTH_NONE: | 1507 | case DOT11_AUTH_NONE: |
1507 | default: | 1508 | default: |
1508 | param->value = 0; | 1509 | param->value = 0; |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 598ca1cafb95..e7cf37f550d1 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -1107,12 +1107,15 @@ static int ray_get_essid(struct net_device *dev, struct iw_request_info *info, | |||
1107 | union iwreq_data *wrqu, char *extra) | 1107 | union iwreq_data *wrqu, char *extra) |
1108 | { | 1108 | { |
1109 | ray_dev_t *local = netdev_priv(dev); | 1109 | ray_dev_t *local = netdev_priv(dev); |
1110 | UCHAR tmp[IW_ESSID_MAX_SIZE + 1]; | ||
1110 | 1111 | ||
1111 | /* Get the essid that was set */ | 1112 | /* Get the essid that was set */ |
1112 | memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE); | 1113 | memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE); |
1114 | memcpy(tmp, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE); | ||
1115 | tmp[IW_ESSID_MAX_SIZE] = '\0'; | ||
1113 | 1116 | ||
1114 | /* Push it out ! */ | 1117 | /* Push it out ! */ |
1115 | wrqu->essid.length = strlen(extra); | 1118 | wrqu->essid.length = strlen(tmp); |
1116 | wrqu->essid.flags = 1; /* active */ | 1119 | wrqu->essid.flags = 1; /* active */ |
1117 | 1120 | ||
1118 | return 0; | 1121 | return 0; |
@@ -1842,6 +1845,8 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id) | |||
1842 | UCHAR tmp; | 1845 | UCHAR tmp; |
1843 | UCHAR cmd; | 1846 | UCHAR cmd; |
1844 | UCHAR status; | 1847 | UCHAR status; |
1848 | UCHAR memtmp[ESSID_SIZE + 1]; | ||
1849 | |||
1845 | 1850 | ||
1846 | if (dev == NULL) /* Note that we want interrupts with dev->start == 0 */ | 1851 | if (dev == NULL) /* Note that we want interrupts with dev->start == 0 */ |
1847 | return IRQ_NONE; | 1852 | return IRQ_NONE; |
@@ -1901,17 +1906,21 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id) | |||
1901 | break; | 1906 | break; |
1902 | case CCS_START_NETWORK: | 1907 | case CCS_START_NETWORK: |
1903 | case CCS_JOIN_NETWORK: | 1908 | case CCS_JOIN_NETWORK: |
1909 | memcpy(memtmp, local->sparm.b4.a_current_ess_id, | ||
1910 | ESSID_SIZE); | ||
1911 | memtmp[ESSID_SIZE] = '\0'; | ||
1912 | |||
1904 | if (status == CCS_COMMAND_COMPLETE) { | 1913 | if (status == CCS_COMMAND_COMPLETE) { |
1905 | if (readb | 1914 | if (readb |
1906 | (&pccs->var.start_network.net_initiated) == | 1915 | (&pccs->var.start_network.net_initiated) == |
1907 | 1) { | 1916 | 1) { |
1908 | dev_dbg(&link->dev, | 1917 | dev_dbg(&link->dev, |
1909 | "ray_cs interrupt network \"%s\" started\n", | 1918 | "ray_cs interrupt network \"%s\" started\n", |
1910 | local->sparm.b4.a_current_ess_id); | 1919 | memtmp); |
1911 | } else { | 1920 | } else { |
1912 | dev_dbg(&link->dev, | 1921 | dev_dbg(&link->dev, |
1913 | "ray_cs interrupt network \"%s\" joined\n", | 1922 | "ray_cs interrupt network \"%s\" joined\n", |
1914 | local->sparm.b4.a_current_ess_id); | 1923 | memtmp); |
1915 | } | 1924 | } |
1916 | memcpy_fromio(&local->bss_id, | 1925 | memcpy_fromio(&local->bss_id, |
1917 | pccs->var.start_network.bssid, | 1926 | pccs->var.start_network.bssid, |
@@ -1939,12 +1948,12 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id) | |||
1939 | if (status == CCS_START_NETWORK) { | 1948 | if (status == CCS_START_NETWORK) { |
1940 | dev_dbg(&link->dev, | 1949 | dev_dbg(&link->dev, |
1941 | "ray_cs interrupt network \"%s\" start failed\n", | 1950 | "ray_cs interrupt network \"%s\" start failed\n", |
1942 | local->sparm.b4.a_current_ess_id); | 1951 | memtmp); |
1943 | local->timer.function = start_net; | 1952 | local->timer.function = start_net; |
1944 | } else { | 1953 | } else { |
1945 | dev_dbg(&link->dev, | 1954 | dev_dbg(&link->dev, |
1946 | "ray_cs interrupt network \"%s\" join failed\n", | 1955 | "ray_cs interrupt network \"%s\" join failed\n", |
1947 | local->sparm.b4.a_current_ess_id); | 1956 | memtmp); |
1948 | local->timer.function = join_net; | 1957 | local->timer.function = join_net; |
1949 | } | 1958 | } |
1950 | add_timer(&local->timer); | 1959 | add_timer(&local->timer); |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 197b4466a5d2..a5c694f23d33 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1296,8 +1296,7 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, | |||
1296 | !(filter_flags & FIF_CONTROL)); | 1296 | !(filter_flags & FIF_CONTROL)); |
1297 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, | 1297 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, |
1298 | !(filter_flags & FIF_PSPOLL)); | 1298 | !(filter_flags & FIF_PSPOLL)); |
1299 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, | 1299 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 0); |
1300 | !(filter_flags & FIF_CONTROL)); | ||
1301 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, | 1300 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, |
1302 | !(filter_flags & FIF_CONTROL)); | 1301 | !(filter_flags & FIF_CONTROL)); |
1303 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, | 1302 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, |
@@ -3866,6 +3865,400 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, | |||
3866 | return rfcsr24; | 3865 | return rfcsr24; |
3867 | } | 3866 | } |
3868 | 3867 | ||
3868 | static void rt2800_init_rfcsr_305x_soc(struct rt2x00_dev *rt2x00dev) | ||
3869 | { | ||
3870 | rt2800_rfcsr_write(rt2x00dev, 0, 0x50); | ||
3871 | rt2800_rfcsr_write(rt2x00dev, 1, 0x01); | ||
3872 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); | ||
3873 | rt2800_rfcsr_write(rt2x00dev, 3, 0x75); | ||
3874 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); | ||
3875 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); | ||
3876 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); | ||
3877 | rt2800_rfcsr_write(rt2x00dev, 7, 0x50); | ||
3878 | rt2800_rfcsr_write(rt2x00dev, 8, 0x39); | ||
3879 | rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); | ||
3880 | rt2800_rfcsr_write(rt2x00dev, 10, 0x60); | ||
3881 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); | ||
3882 | rt2800_rfcsr_write(rt2x00dev, 12, 0x75); | ||
3883 | rt2800_rfcsr_write(rt2x00dev, 13, 0x75); | ||
3884 | rt2800_rfcsr_write(rt2x00dev, 14, 0x90); | ||
3885 | rt2800_rfcsr_write(rt2x00dev, 15, 0x58); | ||
3886 | rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); | ||
3887 | rt2800_rfcsr_write(rt2x00dev, 17, 0x92); | ||
3888 | rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); | ||
3889 | rt2800_rfcsr_write(rt2x00dev, 19, 0x02); | ||
3890 | rt2800_rfcsr_write(rt2x00dev, 20, 0xba); | ||
3891 | rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); | ||
3892 | rt2800_rfcsr_write(rt2x00dev, 22, 0x00); | ||
3893 | rt2800_rfcsr_write(rt2x00dev, 23, 0x31); | ||
3894 | rt2800_rfcsr_write(rt2x00dev, 24, 0x08); | ||
3895 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); | ||
3896 | rt2800_rfcsr_write(rt2x00dev, 26, 0x25); | ||
3897 | rt2800_rfcsr_write(rt2x00dev, 27, 0x23); | ||
3898 | rt2800_rfcsr_write(rt2x00dev, 28, 0x13); | ||
3899 | rt2800_rfcsr_write(rt2x00dev, 29, 0x83); | ||
3900 | rt2800_rfcsr_write(rt2x00dev, 30, 0x00); | ||
3901 | rt2800_rfcsr_write(rt2x00dev, 31, 0x00); | ||
3902 | } | ||
3903 | |||
3904 | static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev) | ||
3905 | { | ||
3906 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); | ||
3907 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); | ||
3908 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); | ||
3909 | rt2800_rfcsr_write(rt2x00dev, 7, 0x60); | ||
3910 | rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); | ||
3911 | rt2800_rfcsr_write(rt2x00dev, 10, 0x41); | ||
3912 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); | ||
3913 | rt2800_rfcsr_write(rt2x00dev, 12, 0x7b); | ||
3914 | rt2800_rfcsr_write(rt2x00dev, 14, 0x90); | ||
3915 | rt2800_rfcsr_write(rt2x00dev, 15, 0x58); | ||
3916 | rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); | ||
3917 | rt2800_rfcsr_write(rt2x00dev, 17, 0x92); | ||
3918 | rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); | ||
3919 | rt2800_rfcsr_write(rt2x00dev, 19, 0x02); | ||
3920 | rt2800_rfcsr_write(rt2x00dev, 20, 0xba); | ||
3921 | rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); | ||
3922 | rt2800_rfcsr_write(rt2x00dev, 24, 0x16); | ||
3923 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); | ||
3924 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); | ||
3925 | } | ||
3926 | |||
3927 | static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev) | ||
3928 | { | ||
3929 | rt2800_rfcsr_write(rt2x00dev, 1, 0x0f); | ||
3930 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | ||
3931 | rt2800_rfcsr_write(rt2x00dev, 3, 0x08); | ||
3932 | rt2800_rfcsr_write(rt2x00dev, 4, 0x00); | ||
3933 | rt2800_rfcsr_write(rt2x00dev, 6, 0xa0); | ||
3934 | rt2800_rfcsr_write(rt2x00dev, 8, 0xf3); | ||
3935 | rt2800_rfcsr_write(rt2x00dev, 9, 0x02); | ||
3936 | rt2800_rfcsr_write(rt2x00dev, 10, 0x53); | ||
3937 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); | ||
3938 | rt2800_rfcsr_write(rt2x00dev, 12, 0x46); | ||
3939 | rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); | ||
3940 | rt2800_rfcsr_write(rt2x00dev, 18, 0x02); | ||
3941 | rt2800_rfcsr_write(rt2x00dev, 22, 0x20); | ||
3942 | rt2800_rfcsr_write(rt2x00dev, 25, 0x83); | ||
3943 | rt2800_rfcsr_write(rt2x00dev, 26, 0x82); | ||
3944 | rt2800_rfcsr_write(rt2x00dev, 27, 0x09); | ||
3945 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | ||
3946 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); | ||
3947 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | ||
3948 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); | ||
3949 | rt2800_rfcsr_write(rt2x00dev, 33, 0x00); | ||
3950 | rt2800_rfcsr_write(rt2x00dev, 34, 0x05); | ||
3951 | rt2800_rfcsr_write(rt2x00dev, 35, 0x12); | ||
3952 | rt2800_rfcsr_write(rt2x00dev, 36, 0x00); | ||
3953 | rt2800_rfcsr_write(rt2x00dev, 38, 0x85); | ||
3954 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); | ||
3955 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); | ||
3956 | rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); | ||
3957 | rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); | ||
3958 | rt2800_rfcsr_write(rt2x00dev, 43, 0x7b); | ||
3959 | rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); | ||
3960 | rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); | ||
3961 | rt2800_rfcsr_write(rt2x00dev, 46, 0x73); | ||
3962 | rt2800_rfcsr_write(rt2x00dev, 47, 0x00); | ||
3963 | rt2800_rfcsr_write(rt2x00dev, 48, 0x10); | ||
3964 | rt2800_rfcsr_write(rt2x00dev, 49, 0x98); | ||
3965 | rt2800_rfcsr_write(rt2x00dev, 52, 0x38); | ||
3966 | rt2800_rfcsr_write(rt2x00dev, 53, 0x00); | ||
3967 | rt2800_rfcsr_write(rt2x00dev, 54, 0x78); | ||
3968 | rt2800_rfcsr_write(rt2x00dev, 55, 0x43); | ||
3969 | rt2800_rfcsr_write(rt2x00dev, 56, 0x02); | ||
3970 | rt2800_rfcsr_write(rt2x00dev, 57, 0x80); | ||
3971 | rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); | ||
3972 | rt2800_rfcsr_write(rt2x00dev, 59, 0x09); | ||
3973 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | ||
3974 | rt2800_rfcsr_write(rt2x00dev, 61, 0xc1); | ||
3975 | } | ||
3976 | |||
3977 | static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev) | ||
3978 | { | ||
3979 | rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); | ||
3980 | rt2800_rfcsr_write(rt2x00dev, 1, 0x23); | ||
3981 | rt2800_rfcsr_write(rt2x00dev, 2, 0x50); | ||
3982 | rt2800_rfcsr_write(rt2x00dev, 3, 0x18); | ||
3983 | rt2800_rfcsr_write(rt2x00dev, 4, 0x00); | ||
3984 | rt2800_rfcsr_write(rt2x00dev, 5, 0x00); | ||
3985 | rt2800_rfcsr_write(rt2x00dev, 6, 0x33); | ||
3986 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); | ||
3987 | rt2800_rfcsr_write(rt2x00dev, 8, 0xf1); | ||
3988 | rt2800_rfcsr_write(rt2x00dev, 9, 0x02); | ||
3989 | rt2800_rfcsr_write(rt2x00dev, 10, 0xd2); | ||
3990 | rt2800_rfcsr_write(rt2x00dev, 11, 0x42); | ||
3991 | rt2800_rfcsr_write(rt2x00dev, 12, 0x1c); | ||
3992 | rt2800_rfcsr_write(rt2x00dev, 13, 0x00); | ||
3993 | rt2800_rfcsr_write(rt2x00dev, 14, 0x5a); | ||
3994 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); | ||
3995 | rt2800_rfcsr_write(rt2x00dev, 16, 0x01); | ||
3996 | rt2800_rfcsr_write(rt2x00dev, 18, 0x45); | ||
3997 | rt2800_rfcsr_write(rt2x00dev, 19, 0x02); | ||
3998 | rt2800_rfcsr_write(rt2x00dev, 20, 0x00); | ||
3999 | rt2800_rfcsr_write(rt2x00dev, 21, 0x00); | ||
4000 | rt2800_rfcsr_write(rt2x00dev, 22, 0x00); | ||
4001 | rt2800_rfcsr_write(rt2x00dev, 23, 0x00); | ||
4002 | rt2800_rfcsr_write(rt2x00dev, 24, 0x00); | ||
4003 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); | ||
4004 | rt2800_rfcsr_write(rt2x00dev, 26, 0x00); | ||
4005 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); | ||
4006 | rt2800_rfcsr_write(rt2x00dev, 28, 0x03); | ||
4007 | rt2800_rfcsr_write(rt2x00dev, 29, 0x00); | ||
4008 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); | ||
4009 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | ||
4010 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); | ||
4011 | rt2800_rfcsr_write(rt2x00dev, 33, 0x00); | ||
4012 | rt2800_rfcsr_write(rt2x00dev, 34, 0x01); | ||
4013 | rt2800_rfcsr_write(rt2x00dev, 35, 0x03); | ||
4014 | rt2800_rfcsr_write(rt2x00dev, 36, 0xbd); | ||
4015 | rt2800_rfcsr_write(rt2x00dev, 37, 0x3c); | ||
4016 | rt2800_rfcsr_write(rt2x00dev, 38, 0x5f); | ||
4017 | rt2800_rfcsr_write(rt2x00dev, 39, 0xc5); | ||
4018 | rt2800_rfcsr_write(rt2x00dev, 40, 0x33); | ||
4019 | rt2800_rfcsr_write(rt2x00dev, 41, 0x5b); | ||
4020 | rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); | ||
4021 | rt2800_rfcsr_write(rt2x00dev, 43, 0xdb); | ||
4022 | rt2800_rfcsr_write(rt2x00dev, 44, 0xdb); | ||
4023 | rt2800_rfcsr_write(rt2x00dev, 45, 0xdb); | ||
4024 | rt2800_rfcsr_write(rt2x00dev, 46, 0xdd); | ||
4025 | rt2800_rfcsr_write(rt2x00dev, 47, 0x0d); | ||
4026 | rt2800_rfcsr_write(rt2x00dev, 48, 0x14); | ||
4027 | rt2800_rfcsr_write(rt2x00dev, 49, 0x00); | ||
4028 | rt2800_rfcsr_write(rt2x00dev, 50, 0x2d); | ||
4029 | rt2800_rfcsr_write(rt2x00dev, 51, 0x7f); | ||
4030 | rt2800_rfcsr_write(rt2x00dev, 52, 0x00); | ||
4031 | rt2800_rfcsr_write(rt2x00dev, 53, 0x52); | ||
4032 | rt2800_rfcsr_write(rt2x00dev, 54, 0x1b); | ||
4033 | rt2800_rfcsr_write(rt2x00dev, 55, 0x7f); | ||
4034 | rt2800_rfcsr_write(rt2x00dev, 56, 0x00); | ||
4035 | rt2800_rfcsr_write(rt2x00dev, 57, 0x52); | ||
4036 | rt2800_rfcsr_write(rt2x00dev, 58, 0x1b); | ||
4037 | rt2800_rfcsr_write(rt2x00dev, 59, 0x00); | ||
4038 | rt2800_rfcsr_write(rt2x00dev, 60, 0x00); | ||
4039 | rt2800_rfcsr_write(rt2x00dev, 61, 0x00); | ||
4040 | rt2800_rfcsr_write(rt2x00dev, 62, 0x00); | ||
4041 | rt2800_rfcsr_write(rt2x00dev, 63, 0x00); | ||
4042 | } | ||
4043 | |||
4044 | static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev) | ||
4045 | { | ||
4046 | rt2800_rfcsr_write(rt2x00dev, 0, 0xa0); | ||
4047 | rt2800_rfcsr_write(rt2x00dev, 1, 0xe1); | ||
4048 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); | ||
4049 | rt2800_rfcsr_write(rt2x00dev, 3, 0x62); | ||
4050 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); | ||
4051 | rt2800_rfcsr_write(rt2x00dev, 5, 0x8b); | ||
4052 | rt2800_rfcsr_write(rt2x00dev, 6, 0x42); | ||
4053 | rt2800_rfcsr_write(rt2x00dev, 7, 0x34); | ||
4054 | rt2800_rfcsr_write(rt2x00dev, 8, 0x00); | ||
4055 | rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); | ||
4056 | rt2800_rfcsr_write(rt2x00dev, 10, 0x61); | ||
4057 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); | ||
4058 | rt2800_rfcsr_write(rt2x00dev, 12, 0x3b); | ||
4059 | rt2800_rfcsr_write(rt2x00dev, 13, 0xe0); | ||
4060 | rt2800_rfcsr_write(rt2x00dev, 14, 0x90); | ||
4061 | rt2800_rfcsr_write(rt2x00dev, 15, 0x53); | ||
4062 | rt2800_rfcsr_write(rt2x00dev, 16, 0xe0); | ||
4063 | rt2800_rfcsr_write(rt2x00dev, 17, 0x94); | ||
4064 | rt2800_rfcsr_write(rt2x00dev, 18, 0x5c); | ||
4065 | rt2800_rfcsr_write(rt2x00dev, 19, 0x4a); | ||
4066 | rt2800_rfcsr_write(rt2x00dev, 20, 0xb2); | ||
4067 | rt2800_rfcsr_write(rt2x00dev, 21, 0xf6); | ||
4068 | rt2800_rfcsr_write(rt2x00dev, 22, 0x00); | ||
4069 | rt2800_rfcsr_write(rt2x00dev, 23, 0x14); | ||
4070 | rt2800_rfcsr_write(rt2x00dev, 24, 0x08); | ||
4071 | rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); | ||
4072 | rt2800_rfcsr_write(rt2x00dev, 26, 0x85); | ||
4073 | rt2800_rfcsr_write(rt2x00dev, 27, 0x00); | ||
4074 | rt2800_rfcsr_write(rt2x00dev, 28, 0x41); | ||
4075 | rt2800_rfcsr_write(rt2x00dev, 29, 0x8f); | ||
4076 | rt2800_rfcsr_write(rt2x00dev, 30, 0x20); | ||
4077 | rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); | ||
4078 | } | ||
4079 | |||
4080 | static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev) | ||
4081 | { | ||
4082 | rt2800_rfcsr_write(rt2x00dev, 0, 0x70); | ||
4083 | rt2800_rfcsr_write(rt2x00dev, 1, 0x81); | ||
4084 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); | ||
4085 | rt2800_rfcsr_write(rt2x00dev, 3, 0x02); | ||
4086 | rt2800_rfcsr_write(rt2x00dev, 4, 0x4c); | ||
4087 | rt2800_rfcsr_write(rt2x00dev, 5, 0x05); | ||
4088 | rt2800_rfcsr_write(rt2x00dev, 6, 0x4a); | ||
4089 | rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); | ||
4090 | rt2800_rfcsr_write(rt2x00dev, 9, 0xc3); | ||
4091 | rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); | ||
4092 | rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); | ||
4093 | rt2800_rfcsr_write(rt2x00dev, 12, 0x70); | ||
4094 | rt2800_rfcsr_write(rt2x00dev, 13, 0x65); | ||
4095 | rt2800_rfcsr_write(rt2x00dev, 14, 0xa0); | ||
4096 | rt2800_rfcsr_write(rt2x00dev, 15, 0x53); | ||
4097 | rt2800_rfcsr_write(rt2x00dev, 16, 0x4c); | ||
4098 | rt2800_rfcsr_write(rt2x00dev, 17, 0x23); | ||
4099 | rt2800_rfcsr_write(rt2x00dev, 18, 0xac); | ||
4100 | rt2800_rfcsr_write(rt2x00dev, 19, 0x93); | ||
4101 | rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); | ||
4102 | rt2800_rfcsr_write(rt2x00dev, 21, 0xd0); | ||
4103 | rt2800_rfcsr_write(rt2x00dev, 22, 0x00); | ||
4104 | rt2800_rfcsr_write(rt2x00dev, 23, 0x3c); | ||
4105 | rt2800_rfcsr_write(rt2x00dev, 24, 0x16); | ||
4106 | rt2800_rfcsr_write(rt2x00dev, 25, 0x15); | ||
4107 | rt2800_rfcsr_write(rt2x00dev, 26, 0x85); | ||
4108 | rt2800_rfcsr_write(rt2x00dev, 27, 0x00); | ||
4109 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); | ||
4110 | rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); | ||
4111 | rt2800_rfcsr_write(rt2x00dev, 30, 0x09); | ||
4112 | rt2800_rfcsr_write(rt2x00dev, 31, 0x10); | ||
4113 | } | ||
4114 | |||
4115 | static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) | ||
4116 | { | ||
4117 | rt2800_rfcsr_write(rt2x00dev, 1, 0x0f); | ||
4118 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | ||
4119 | rt2800_rfcsr_write(rt2x00dev, 3, 0x88); | ||
4120 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); | ||
4121 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4122 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); | ||
4123 | else | ||
4124 | rt2800_rfcsr_write(rt2x00dev, 6, 0xa0); | ||
4125 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); | ||
4126 | rt2800_rfcsr_write(rt2x00dev, 10, 0x53); | ||
4127 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); | ||
4128 | rt2800_rfcsr_write(rt2x00dev, 12, 0xc6); | ||
4129 | rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); | ||
4130 | rt2800_rfcsr_write(rt2x00dev, 14, 0x00); | ||
4131 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); | ||
4132 | rt2800_rfcsr_write(rt2x00dev, 16, 0x00); | ||
4133 | rt2800_rfcsr_write(rt2x00dev, 18, 0x03); | ||
4134 | rt2800_rfcsr_write(rt2x00dev, 19, 0x00); | ||
4135 | |||
4136 | rt2800_rfcsr_write(rt2x00dev, 20, 0x00); | ||
4137 | rt2800_rfcsr_write(rt2x00dev, 21, 0x00); | ||
4138 | rt2800_rfcsr_write(rt2x00dev, 22, 0x20); | ||
4139 | rt2800_rfcsr_write(rt2x00dev, 23, 0x00); | ||
4140 | rt2800_rfcsr_write(rt2x00dev, 24, 0x00); | ||
4141 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4142 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); | ||
4143 | else | ||
4144 | rt2800_rfcsr_write(rt2x00dev, 25, 0xc0); | ||
4145 | rt2800_rfcsr_write(rt2x00dev, 26, 0x00); | ||
4146 | rt2800_rfcsr_write(rt2x00dev, 27, 0x09); | ||
4147 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); | ||
4148 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | ||
4149 | |||
4150 | rt2800_rfcsr_write(rt2x00dev, 30, 0x00); | ||
4151 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | ||
4152 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); | ||
4153 | rt2800_rfcsr_write(rt2x00dev, 33, 0x00); | ||
4154 | rt2800_rfcsr_write(rt2x00dev, 34, 0x07); | ||
4155 | rt2800_rfcsr_write(rt2x00dev, 35, 0x12); | ||
4156 | rt2800_rfcsr_write(rt2x00dev, 36, 0x00); | ||
4157 | rt2800_rfcsr_write(rt2x00dev, 37, 0x08); | ||
4158 | rt2800_rfcsr_write(rt2x00dev, 38, 0x85); | ||
4159 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); | ||
4160 | |||
4161 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4162 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); | ||
4163 | else | ||
4164 | rt2800_rfcsr_write(rt2x00dev, 40, 0x4b); | ||
4165 | rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); | ||
4166 | rt2800_rfcsr_write(rt2x00dev, 42, 0xd2); | ||
4167 | rt2800_rfcsr_write(rt2x00dev, 43, 0x9a); | ||
4168 | rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); | ||
4169 | rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); | ||
4170 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4171 | rt2800_rfcsr_write(rt2x00dev, 46, 0x73); | ||
4172 | else | ||
4173 | rt2800_rfcsr_write(rt2x00dev, 46, 0x7b); | ||
4174 | rt2800_rfcsr_write(rt2x00dev, 47, 0x00); | ||
4175 | rt2800_rfcsr_write(rt2x00dev, 48, 0x10); | ||
4176 | rt2800_rfcsr_write(rt2x00dev, 49, 0x94); | ||
4177 | |||
4178 | rt2800_rfcsr_write(rt2x00dev, 52, 0x38); | ||
4179 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4180 | rt2800_rfcsr_write(rt2x00dev, 53, 0x00); | ||
4181 | else | ||
4182 | rt2800_rfcsr_write(rt2x00dev, 53, 0x84); | ||
4183 | rt2800_rfcsr_write(rt2x00dev, 54, 0x78); | ||
4184 | rt2800_rfcsr_write(rt2x00dev, 55, 0x44); | ||
4185 | rt2800_rfcsr_write(rt2x00dev, 56, 0x22); | ||
4186 | rt2800_rfcsr_write(rt2x00dev, 57, 0x80); | ||
4187 | rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); | ||
4188 | rt2800_rfcsr_write(rt2x00dev, 59, 0x63); | ||
4189 | |||
4190 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | ||
4191 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4192 | rt2800_rfcsr_write(rt2x00dev, 61, 0xd1); | ||
4193 | else | ||
4194 | rt2800_rfcsr_write(rt2x00dev, 61, 0xdd); | ||
4195 | rt2800_rfcsr_write(rt2x00dev, 62, 0x00); | ||
4196 | rt2800_rfcsr_write(rt2x00dev, 63, 0x00); | ||
4197 | } | ||
4198 | |||
4199 | static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev) | ||
4200 | { | ||
4201 | rt2800_rfcsr_write(rt2x00dev, 1, 0x17); | ||
4202 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | ||
4203 | rt2800_rfcsr_write(rt2x00dev, 3, 0x88); | ||
4204 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); | ||
4205 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); | ||
4206 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); | ||
4207 | rt2800_rfcsr_write(rt2x00dev, 10, 0x53); | ||
4208 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); | ||
4209 | rt2800_rfcsr_write(rt2x00dev, 12, 0x46); | ||
4210 | rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); | ||
4211 | rt2800_rfcsr_write(rt2x00dev, 14, 0x00); | ||
4212 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); | ||
4213 | rt2800_rfcsr_write(rt2x00dev, 16, 0x00); | ||
4214 | rt2800_rfcsr_write(rt2x00dev, 18, 0x03); | ||
4215 | rt2800_rfcsr_write(rt2x00dev, 19, 0x4d); | ||
4216 | rt2800_rfcsr_write(rt2x00dev, 20, 0x00); | ||
4217 | rt2800_rfcsr_write(rt2x00dev, 21, 0x8d); | ||
4218 | rt2800_rfcsr_write(rt2x00dev, 22, 0x20); | ||
4219 | rt2800_rfcsr_write(rt2x00dev, 23, 0x0b); | ||
4220 | rt2800_rfcsr_write(rt2x00dev, 24, 0x44); | ||
4221 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); | ||
4222 | rt2800_rfcsr_write(rt2x00dev, 26, 0x82); | ||
4223 | rt2800_rfcsr_write(rt2x00dev, 27, 0x09); | ||
4224 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); | ||
4225 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | ||
4226 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); | ||
4227 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | ||
4228 | rt2800_rfcsr_write(rt2x00dev, 32, 0x20); | ||
4229 | rt2800_rfcsr_write(rt2x00dev, 33, 0xC0); | ||
4230 | rt2800_rfcsr_write(rt2x00dev, 34, 0x07); | ||
4231 | rt2800_rfcsr_write(rt2x00dev, 35, 0x12); | ||
4232 | rt2800_rfcsr_write(rt2x00dev, 36, 0x00); | ||
4233 | rt2800_rfcsr_write(rt2x00dev, 37, 0x08); | ||
4234 | rt2800_rfcsr_write(rt2x00dev, 38, 0x89); | ||
4235 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); | ||
4236 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0f); | ||
4237 | rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); | ||
4238 | rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); | ||
4239 | rt2800_rfcsr_write(rt2x00dev, 43, 0x9b); | ||
4240 | rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); | ||
4241 | rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); | ||
4242 | rt2800_rfcsr_write(rt2x00dev, 46, 0x73); | ||
4243 | rt2800_rfcsr_write(rt2x00dev, 47, 0x0c); | ||
4244 | rt2800_rfcsr_write(rt2x00dev, 48, 0x10); | ||
4245 | rt2800_rfcsr_write(rt2x00dev, 49, 0x94); | ||
4246 | rt2800_rfcsr_write(rt2x00dev, 50, 0x94); | ||
4247 | rt2800_rfcsr_write(rt2x00dev, 51, 0x3a); | ||
4248 | rt2800_rfcsr_write(rt2x00dev, 52, 0x48); | ||
4249 | rt2800_rfcsr_write(rt2x00dev, 53, 0x44); | ||
4250 | rt2800_rfcsr_write(rt2x00dev, 54, 0x38); | ||
4251 | rt2800_rfcsr_write(rt2x00dev, 55, 0x43); | ||
4252 | rt2800_rfcsr_write(rt2x00dev, 56, 0xa1); | ||
4253 | rt2800_rfcsr_write(rt2x00dev, 57, 0x00); | ||
4254 | rt2800_rfcsr_write(rt2x00dev, 58, 0x39); | ||
4255 | rt2800_rfcsr_write(rt2x00dev, 59, 0x07); | ||
4256 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | ||
4257 | rt2800_rfcsr_write(rt2x00dev, 61, 0x91); | ||
4258 | rt2800_rfcsr_write(rt2x00dev, 62, 0x39); | ||
4259 | rt2800_rfcsr_write(rt2x00dev, 63, 0x07); | ||
4260 | } | ||
4261 | |||
3869 | static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | 4262 | static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) |
3870 | { | 4263 | { |
3871 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | 4264 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; |
@@ -3889,6 +4282,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
3889 | /* | 4282 | /* |
3890 | * Init RF calibration. | 4283 | * Init RF calibration. |
3891 | */ | 4284 | */ |
4285 | |||
3892 | if (rt2x00_rt(rt2x00dev, RT3290) || | 4286 | if (rt2x00_rt(rt2x00dev, RT3290) || |
3893 | rt2x00_rt(rt2x00dev, RT5390) || | 4287 | rt2x00_rt(rt2x00dev, RT5390) || |
3894 | rt2x00_rt(rt2x00dev, RT5392)) { | 4288 | rt2x00_rt(rt2x00dev, RT5392)) { |
@@ -3907,379 +4301,35 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
3907 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | 4301 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); |
3908 | } | 4302 | } |
3909 | 4303 | ||
3910 | if (rt2x00_rt(rt2x00dev, RT3070) || | 4304 | if (rt2800_is_305x_soc(rt2x00dev)) { |
3911 | rt2x00_rt(rt2x00dev, RT3071) || | 4305 | rt2800_init_rfcsr_305x_soc(rt2x00dev); |
3912 | rt2x00_rt(rt2x00dev, RT3090)) { | ||
3913 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); | ||
3914 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); | ||
3915 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); | ||
3916 | rt2800_rfcsr_write(rt2x00dev, 7, 0x60); | ||
3917 | rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); | ||
3918 | rt2800_rfcsr_write(rt2x00dev, 10, 0x41); | ||
3919 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); | ||
3920 | rt2800_rfcsr_write(rt2x00dev, 12, 0x7b); | ||
3921 | rt2800_rfcsr_write(rt2x00dev, 14, 0x90); | ||
3922 | rt2800_rfcsr_write(rt2x00dev, 15, 0x58); | ||
3923 | rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); | ||
3924 | rt2800_rfcsr_write(rt2x00dev, 17, 0x92); | ||
3925 | rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); | ||
3926 | rt2800_rfcsr_write(rt2x00dev, 19, 0x02); | ||
3927 | rt2800_rfcsr_write(rt2x00dev, 20, 0xba); | ||
3928 | rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); | ||
3929 | rt2800_rfcsr_write(rt2x00dev, 24, 0x16); | ||
3930 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); | ||
3931 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); | ||
3932 | } else if (rt2x00_rt(rt2x00dev, RT3290)) { | ||
3933 | rt2800_rfcsr_write(rt2x00dev, 1, 0x0f); | ||
3934 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | ||
3935 | rt2800_rfcsr_write(rt2x00dev, 3, 0x08); | ||
3936 | rt2800_rfcsr_write(rt2x00dev, 4, 0x00); | ||
3937 | rt2800_rfcsr_write(rt2x00dev, 6, 0xa0); | ||
3938 | rt2800_rfcsr_write(rt2x00dev, 8, 0xf3); | ||
3939 | rt2800_rfcsr_write(rt2x00dev, 9, 0x02); | ||
3940 | rt2800_rfcsr_write(rt2x00dev, 10, 0x53); | ||
3941 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); | ||
3942 | rt2800_rfcsr_write(rt2x00dev, 12, 0x46); | ||
3943 | rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); | ||
3944 | rt2800_rfcsr_write(rt2x00dev, 18, 0x02); | ||
3945 | rt2800_rfcsr_write(rt2x00dev, 22, 0x20); | ||
3946 | rt2800_rfcsr_write(rt2x00dev, 25, 0x83); | ||
3947 | rt2800_rfcsr_write(rt2x00dev, 26, 0x82); | ||
3948 | rt2800_rfcsr_write(rt2x00dev, 27, 0x09); | ||
3949 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | ||
3950 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); | ||
3951 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | ||
3952 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); | ||
3953 | rt2800_rfcsr_write(rt2x00dev, 33, 0x00); | ||
3954 | rt2800_rfcsr_write(rt2x00dev, 34, 0x05); | ||
3955 | rt2800_rfcsr_write(rt2x00dev, 35, 0x12); | ||
3956 | rt2800_rfcsr_write(rt2x00dev, 36, 0x00); | ||
3957 | rt2800_rfcsr_write(rt2x00dev, 38, 0x85); | ||
3958 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); | ||
3959 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); | ||
3960 | rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); | ||
3961 | rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); | ||
3962 | rt2800_rfcsr_write(rt2x00dev, 43, 0x7b); | ||
3963 | rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); | ||
3964 | rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); | ||
3965 | rt2800_rfcsr_write(rt2x00dev, 46, 0x73); | ||
3966 | rt2800_rfcsr_write(rt2x00dev, 47, 0x00); | ||
3967 | rt2800_rfcsr_write(rt2x00dev, 48, 0x10); | ||
3968 | rt2800_rfcsr_write(rt2x00dev, 49, 0x98); | ||
3969 | rt2800_rfcsr_write(rt2x00dev, 52, 0x38); | ||
3970 | rt2800_rfcsr_write(rt2x00dev, 53, 0x00); | ||
3971 | rt2800_rfcsr_write(rt2x00dev, 54, 0x78); | ||
3972 | rt2800_rfcsr_write(rt2x00dev, 55, 0x43); | ||
3973 | rt2800_rfcsr_write(rt2x00dev, 56, 0x02); | ||
3974 | rt2800_rfcsr_write(rt2x00dev, 57, 0x80); | ||
3975 | rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); | ||
3976 | rt2800_rfcsr_write(rt2x00dev, 59, 0x09); | ||
3977 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | ||
3978 | rt2800_rfcsr_write(rt2x00dev, 61, 0xc1); | ||
3979 | } else if (rt2x00_rt(rt2x00dev, RT3390)) { | ||
3980 | rt2800_rfcsr_write(rt2x00dev, 0, 0xa0); | ||
3981 | rt2800_rfcsr_write(rt2x00dev, 1, 0xe1); | ||
3982 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); | ||
3983 | rt2800_rfcsr_write(rt2x00dev, 3, 0x62); | ||
3984 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); | ||
3985 | rt2800_rfcsr_write(rt2x00dev, 5, 0x8b); | ||
3986 | rt2800_rfcsr_write(rt2x00dev, 6, 0x42); | ||
3987 | rt2800_rfcsr_write(rt2x00dev, 7, 0x34); | ||
3988 | rt2800_rfcsr_write(rt2x00dev, 8, 0x00); | ||
3989 | rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); | ||
3990 | rt2800_rfcsr_write(rt2x00dev, 10, 0x61); | ||
3991 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); | ||
3992 | rt2800_rfcsr_write(rt2x00dev, 12, 0x3b); | ||
3993 | rt2800_rfcsr_write(rt2x00dev, 13, 0xe0); | ||
3994 | rt2800_rfcsr_write(rt2x00dev, 14, 0x90); | ||
3995 | rt2800_rfcsr_write(rt2x00dev, 15, 0x53); | ||
3996 | rt2800_rfcsr_write(rt2x00dev, 16, 0xe0); | ||
3997 | rt2800_rfcsr_write(rt2x00dev, 17, 0x94); | ||
3998 | rt2800_rfcsr_write(rt2x00dev, 18, 0x5c); | ||
3999 | rt2800_rfcsr_write(rt2x00dev, 19, 0x4a); | ||
4000 | rt2800_rfcsr_write(rt2x00dev, 20, 0xb2); | ||
4001 | rt2800_rfcsr_write(rt2x00dev, 21, 0xf6); | ||
4002 | rt2800_rfcsr_write(rt2x00dev, 22, 0x00); | ||
4003 | rt2800_rfcsr_write(rt2x00dev, 23, 0x14); | ||
4004 | rt2800_rfcsr_write(rt2x00dev, 24, 0x08); | ||
4005 | rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); | ||
4006 | rt2800_rfcsr_write(rt2x00dev, 26, 0x85); | ||
4007 | rt2800_rfcsr_write(rt2x00dev, 27, 0x00); | ||
4008 | rt2800_rfcsr_write(rt2x00dev, 28, 0x41); | ||
4009 | rt2800_rfcsr_write(rt2x00dev, 29, 0x8f); | ||
4010 | rt2800_rfcsr_write(rt2x00dev, 30, 0x20); | ||
4011 | rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); | ||
4012 | } else if (rt2x00_rt(rt2x00dev, RT3572)) { | ||
4013 | rt2800_rfcsr_write(rt2x00dev, 0, 0x70); | ||
4014 | rt2800_rfcsr_write(rt2x00dev, 1, 0x81); | ||
4015 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); | ||
4016 | rt2800_rfcsr_write(rt2x00dev, 3, 0x02); | ||
4017 | rt2800_rfcsr_write(rt2x00dev, 4, 0x4c); | ||
4018 | rt2800_rfcsr_write(rt2x00dev, 5, 0x05); | ||
4019 | rt2800_rfcsr_write(rt2x00dev, 6, 0x4a); | ||
4020 | rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); | ||
4021 | rt2800_rfcsr_write(rt2x00dev, 9, 0xc3); | ||
4022 | rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); | ||
4023 | rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); | ||
4024 | rt2800_rfcsr_write(rt2x00dev, 12, 0x70); | ||
4025 | rt2800_rfcsr_write(rt2x00dev, 13, 0x65); | ||
4026 | rt2800_rfcsr_write(rt2x00dev, 14, 0xa0); | ||
4027 | rt2800_rfcsr_write(rt2x00dev, 15, 0x53); | ||
4028 | rt2800_rfcsr_write(rt2x00dev, 16, 0x4c); | ||
4029 | rt2800_rfcsr_write(rt2x00dev, 17, 0x23); | ||
4030 | rt2800_rfcsr_write(rt2x00dev, 18, 0xac); | ||
4031 | rt2800_rfcsr_write(rt2x00dev, 19, 0x93); | ||
4032 | rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); | ||
4033 | rt2800_rfcsr_write(rt2x00dev, 21, 0xd0); | ||
4034 | rt2800_rfcsr_write(rt2x00dev, 22, 0x00); | ||
4035 | rt2800_rfcsr_write(rt2x00dev, 23, 0x3c); | ||
4036 | rt2800_rfcsr_write(rt2x00dev, 24, 0x16); | ||
4037 | rt2800_rfcsr_write(rt2x00dev, 25, 0x15); | ||
4038 | rt2800_rfcsr_write(rt2x00dev, 26, 0x85); | ||
4039 | rt2800_rfcsr_write(rt2x00dev, 27, 0x00); | ||
4040 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); | ||
4041 | rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); | ||
4042 | rt2800_rfcsr_write(rt2x00dev, 30, 0x09); | ||
4043 | rt2800_rfcsr_write(rt2x00dev, 31, 0x10); | ||
4044 | } else if (rt2800_is_305x_soc(rt2x00dev)) { | ||
4045 | rt2800_rfcsr_write(rt2x00dev, 0, 0x50); | ||
4046 | rt2800_rfcsr_write(rt2x00dev, 1, 0x01); | ||
4047 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); | ||
4048 | rt2800_rfcsr_write(rt2x00dev, 3, 0x75); | ||
4049 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); | ||
4050 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); | ||
4051 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); | ||
4052 | rt2800_rfcsr_write(rt2x00dev, 7, 0x50); | ||
4053 | rt2800_rfcsr_write(rt2x00dev, 8, 0x39); | ||
4054 | rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); | ||
4055 | rt2800_rfcsr_write(rt2x00dev, 10, 0x60); | ||
4056 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); | ||
4057 | rt2800_rfcsr_write(rt2x00dev, 12, 0x75); | ||
4058 | rt2800_rfcsr_write(rt2x00dev, 13, 0x75); | ||
4059 | rt2800_rfcsr_write(rt2x00dev, 14, 0x90); | ||
4060 | rt2800_rfcsr_write(rt2x00dev, 15, 0x58); | ||
4061 | rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); | ||
4062 | rt2800_rfcsr_write(rt2x00dev, 17, 0x92); | ||
4063 | rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); | ||
4064 | rt2800_rfcsr_write(rt2x00dev, 19, 0x02); | ||
4065 | rt2800_rfcsr_write(rt2x00dev, 20, 0xba); | ||
4066 | rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); | ||
4067 | rt2800_rfcsr_write(rt2x00dev, 22, 0x00); | ||
4068 | rt2800_rfcsr_write(rt2x00dev, 23, 0x31); | ||
4069 | rt2800_rfcsr_write(rt2x00dev, 24, 0x08); | ||
4070 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); | ||
4071 | rt2800_rfcsr_write(rt2x00dev, 26, 0x25); | ||
4072 | rt2800_rfcsr_write(rt2x00dev, 27, 0x23); | ||
4073 | rt2800_rfcsr_write(rt2x00dev, 28, 0x13); | ||
4074 | rt2800_rfcsr_write(rt2x00dev, 29, 0x83); | ||
4075 | rt2800_rfcsr_write(rt2x00dev, 30, 0x00); | ||
4076 | rt2800_rfcsr_write(rt2x00dev, 31, 0x00); | ||
4077 | return 0; | 4306 | return 0; |
4078 | } else if (rt2x00_rt(rt2x00dev, RT3352)) { | 4307 | } |
4079 | rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); | 4308 | |
4080 | rt2800_rfcsr_write(rt2x00dev, 1, 0x23); | 4309 | switch (rt2x00dev->chip.rt) { |
4081 | rt2800_rfcsr_write(rt2x00dev, 2, 0x50); | 4310 | case RT3070: |
4082 | rt2800_rfcsr_write(rt2x00dev, 3, 0x18); | 4311 | case RT3071: |
4083 | rt2800_rfcsr_write(rt2x00dev, 4, 0x00); | 4312 | case RT3090: |
4084 | rt2800_rfcsr_write(rt2x00dev, 5, 0x00); | 4313 | rt2800_init_rfcsr_30xx(rt2x00dev); |
4085 | rt2800_rfcsr_write(rt2x00dev, 6, 0x33); | 4314 | break; |
4086 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); | 4315 | case RT3290: |
4087 | rt2800_rfcsr_write(rt2x00dev, 8, 0xf1); | 4316 | rt2800_init_rfcsr_3290(rt2x00dev); |
4088 | rt2800_rfcsr_write(rt2x00dev, 9, 0x02); | 4317 | break; |
4089 | rt2800_rfcsr_write(rt2x00dev, 10, 0xd2); | 4318 | case RT3352: |
4090 | rt2800_rfcsr_write(rt2x00dev, 11, 0x42); | 4319 | rt2800_init_rfcsr_3352(rt2x00dev); |
4091 | rt2800_rfcsr_write(rt2x00dev, 12, 0x1c); | 4320 | break; |
4092 | rt2800_rfcsr_write(rt2x00dev, 13, 0x00); | 4321 | case RT3390: |
4093 | rt2800_rfcsr_write(rt2x00dev, 14, 0x5a); | 4322 | rt2800_init_rfcsr_3390(rt2x00dev); |
4094 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); | 4323 | break; |
4095 | rt2800_rfcsr_write(rt2x00dev, 16, 0x01); | 4324 | case RT3572: |
4096 | rt2800_rfcsr_write(rt2x00dev, 18, 0x45); | 4325 | rt2800_init_rfcsr_3572(rt2x00dev); |
4097 | rt2800_rfcsr_write(rt2x00dev, 19, 0x02); | 4326 | break; |
4098 | rt2800_rfcsr_write(rt2x00dev, 20, 0x00); | 4327 | case RT5390: |
4099 | rt2800_rfcsr_write(rt2x00dev, 21, 0x00); | 4328 | rt2800_init_rfcsr_5390(rt2x00dev); |
4100 | rt2800_rfcsr_write(rt2x00dev, 22, 0x00); | 4329 | break; |
4101 | rt2800_rfcsr_write(rt2x00dev, 23, 0x00); | 4330 | case RT5392: |
4102 | rt2800_rfcsr_write(rt2x00dev, 24, 0x00); | 4331 | rt2800_init_rfcsr_5392(rt2x00dev); |
4103 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); | 4332 | break; |
4104 | rt2800_rfcsr_write(rt2x00dev, 26, 0x00); | ||
4105 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); | ||
4106 | rt2800_rfcsr_write(rt2x00dev, 28, 0x03); | ||
4107 | rt2800_rfcsr_write(rt2x00dev, 29, 0x00); | ||
4108 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); | ||
4109 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | ||
4110 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); | ||
4111 | rt2800_rfcsr_write(rt2x00dev, 33, 0x00); | ||
4112 | rt2800_rfcsr_write(rt2x00dev, 34, 0x01); | ||
4113 | rt2800_rfcsr_write(rt2x00dev, 35, 0x03); | ||
4114 | rt2800_rfcsr_write(rt2x00dev, 36, 0xbd); | ||
4115 | rt2800_rfcsr_write(rt2x00dev, 37, 0x3c); | ||
4116 | rt2800_rfcsr_write(rt2x00dev, 38, 0x5f); | ||
4117 | rt2800_rfcsr_write(rt2x00dev, 39, 0xc5); | ||
4118 | rt2800_rfcsr_write(rt2x00dev, 40, 0x33); | ||
4119 | rt2800_rfcsr_write(rt2x00dev, 41, 0x5b); | ||
4120 | rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); | ||
4121 | rt2800_rfcsr_write(rt2x00dev, 43, 0xdb); | ||
4122 | rt2800_rfcsr_write(rt2x00dev, 44, 0xdb); | ||
4123 | rt2800_rfcsr_write(rt2x00dev, 45, 0xdb); | ||
4124 | rt2800_rfcsr_write(rt2x00dev, 46, 0xdd); | ||
4125 | rt2800_rfcsr_write(rt2x00dev, 47, 0x0d); | ||
4126 | rt2800_rfcsr_write(rt2x00dev, 48, 0x14); | ||
4127 | rt2800_rfcsr_write(rt2x00dev, 49, 0x00); | ||
4128 | rt2800_rfcsr_write(rt2x00dev, 50, 0x2d); | ||
4129 | rt2800_rfcsr_write(rt2x00dev, 51, 0x7f); | ||
4130 | rt2800_rfcsr_write(rt2x00dev, 52, 0x00); | ||
4131 | rt2800_rfcsr_write(rt2x00dev, 53, 0x52); | ||
4132 | rt2800_rfcsr_write(rt2x00dev, 54, 0x1b); | ||
4133 | rt2800_rfcsr_write(rt2x00dev, 55, 0x7f); | ||
4134 | rt2800_rfcsr_write(rt2x00dev, 56, 0x00); | ||
4135 | rt2800_rfcsr_write(rt2x00dev, 57, 0x52); | ||
4136 | rt2800_rfcsr_write(rt2x00dev, 58, 0x1b); | ||
4137 | rt2800_rfcsr_write(rt2x00dev, 59, 0x00); | ||
4138 | rt2800_rfcsr_write(rt2x00dev, 60, 0x00); | ||
4139 | rt2800_rfcsr_write(rt2x00dev, 61, 0x00); | ||
4140 | rt2800_rfcsr_write(rt2x00dev, 62, 0x00); | ||
4141 | rt2800_rfcsr_write(rt2x00dev, 63, 0x00); | ||
4142 | } else if (rt2x00_rt(rt2x00dev, RT5390)) { | ||
4143 | rt2800_rfcsr_write(rt2x00dev, 1, 0x0f); | ||
4144 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | ||
4145 | rt2800_rfcsr_write(rt2x00dev, 3, 0x88); | ||
4146 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); | ||
4147 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4148 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); | ||
4149 | else | ||
4150 | rt2800_rfcsr_write(rt2x00dev, 6, 0xa0); | ||
4151 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); | ||
4152 | rt2800_rfcsr_write(rt2x00dev, 10, 0x53); | ||
4153 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); | ||
4154 | rt2800_rfcsr_write(rt2x00dev, 12, 0xc6); | ||
4155 | rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); | ||
4156 | rt2800_rfcsr_write(rt2x00dev, 14, 0x00); | ||
4157 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); | ||
4158 | rt2800_rfcsr_write(rt2x00dev, 16, 0x00); | ||
4159 | rt2800_rfcsr_write(rt2x00dev, 18, 0x03); | ||
4160 | rt2800_rfcsr_write(rt2x00dev, 19, 0x00); | ||
4161 | |||
4162 | rt2800_rfcsr_write(rt2x00dev, 20, 0x00); | ||
4163 | rt2800_rfcsr_write(rt2x00dev, 21, 0x00); | ||
4164 | rt2800_rfcsr_write(rt2x00dev, 22, 0x20); | ||
4165 | rt2800_rfcsr_write(rt2x00dev, 23, 0x00); | ||
4166 | rt2800_rfcsr_write(rt2x00dev, 24, 0x00); | ||
4167 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4168 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); | ||
4169 | else | ||
4170 | rt2800_rfcsr_write(rt2x00dev, 25, 0xc0); | ||
4171 | rt2800_rfcsr_write(rt2x00dev, 26, 0x00); | ||
4172 | rt2800_rfcsr_write(rt2x00dev, 27, 0x09); | ||
4173 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); | ||
4174 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | ||
4175 | |||
4176 | rt2800_rfcsr_write(rt2x00dev, 30, 0x00); | ||
4177 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | ||
4178 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); | ||
4179 | rt2800_rfcsr_write(rt2x00dev, 33, 0x00); | ||
4180 | rt2800_rfcsr_write(rt2x00dev, 34, 0x07); | ||
4181 | rt2800_rfcsr_write(rt2x00dev, 35, 0x12); | ||
4182 | rt2800_rfcsr_write(rt2x00dev, 36, 0x00); | ||
4183 | rt2800_rfcsr_write(rt2x00dev, 37, 0x08); | ||
4184 | rt2800_rfcsr_write(rt2x00dev, 38, 0x85); | ||
4185 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); | ||
4186 | |||
4187 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4188 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); | ||
4189 | else | ||
4190 | rt2800_rfcsr_write(rt2x00dev, 40, 0x4b); | ||
4191 | rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); | ||
4192 | rt2800_rfcsr_write(rt2x00dev, 42, 0xd2); | ||
4193 | rt2800_rfcsr_write(rt2x00dev, 43, 0x9a); | ||
4194 | rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); | ||
4195 | rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); | ||
4196 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4197 | rt2800_rfcsr_write(rt2x00dev, 46, 0x73); | ||
4198 | else | ||
4199 | rt2800_rfcsr_write(rt2x00dev, 46, 0x7b); | ||
4200 | rt2800_rfcsr_write(rt2x00dev, 47, 0x00); | ||
4201 | rt2800_rfcsr_write(rt2x00dev, 48, 0x10); | ||
4202 | rt2800_rfcsr_write(rt2x00dev, 49, 0x94); | ||
4203 | |||
4204 | rt2800_rfcsr_write(rt2x00dev, 52, 0x38); | ||
4205 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4206 | rt2800_rfcsr_write(rt2x00dev, 53, 0x00); | ||
4207 | else | ||
4208 | rt2800_rfcsr_write(rt2x00dev, 53, 0x84); | ||
4209 | rt2800_rfcsr_write(rt2x00dev, 54, 0x78); | ||
4210 | rt2800_rfcsr_write(rt2x00dev, 55, 0x44); | ||
4211 | rt2800_rfcsr_write(rt2x00dev, 56, 0x22); | ||
4212 | rt2800_rfcsr_write(rt2x00dev, 57, 0x80); | ||
4213 | rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); | ||
4214 | rt2800_rfcsr_write(rt2x00dev, 59, 0x63); | ||
4215 | |||
4216 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | ||
4217 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | ||
4218 | rt2800_rfcsr_write(rt2x00dev, 61, 0xd1); | ||
4219 | else | ||
4220 | rt2800_rfcsr_write(rt2x00dev, 61, 0xdd); | ||
4221 | rt2800_rfcsr_write(rt2x00dev, 62, 0x00); | ||
4222 | rt2800_rfcsr_write(rt2x00dev, 63, 0x00); | ||
4223 | } else if (rt2x00_rt(rt2x00dev, RT5392)) { | ||
4224 | rt2800_rfcsr_write(rt2x00dev, 1, 0x17); | ||
4225 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | ||
4226 | rt2800_rfcsr_write(rt2x00dev, 3, 0x88); | ||
4227 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); | ||
4228 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); | ||
4229 | rt2800_rfcsr_write(rt2x00dev, 7, 0x00); | ||
4230 | rt2800_rfcsr_write(rt2x00dev, 10, 0x53); | ||
4231 | rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); | ||
4232 | rt2800_rfcsr_write(rt2x00dev, 12, 0x46); | ||
4233 | rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); | ||
4234 | rt2800_rfcsr_write(rt2x00dev, 14, 0x00); | ||
4235 | rt2800_rfcsr_write(rt2x00dev, 15, 0x00); | ||
4236 | rt2800_rfcsr_write(rt2x00dev, 16, 0x00); | ||
4237 | rt2800_rfcsr_write(rt2x00dev, 18, 0x03); | ||
4238 | rt2800_rfcsr_write(rt2x00dev, 19, 0x4d); | ||
4239 | rt2800_rfcsr_write(rt2x00dev, 20, 0x00); | ||
4240 | rt2800_rfcsr_write(rt2x00dev, 21, 0x8d); | ||
4241 | rt2800_rfcsr_write(rt2x00dev, 22, 0x20); | ||
4242 | rt2800_rfcsr_write(rt2x00dev, 23, 0x0b); | ||
4243 | rt2800_rfcsr_write(rt2x00dev, 24, 0x44); | ||
4244 | rt2800_rfcsr_write(rt2x00dev, 25, 0x80); | ||
4245 | rt2800_rfcsr_write(rt2x00dev, 26, 0x82); | ||
4246 | rt2800_rfcsr_write(rt2x00dev, 27, 0x09); | ||
4247 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); | ||
4248 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | ||
4249 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); | ||
4250 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | ||
4251 | rt2800_rfcsr_write(rt2x00dev, 32, 0x20); | ||
4252 | rt2800_rfcsr_write(rt2x00dev, 33, 0xC0); | ||
4253 | rt2800_rfcsr_write(rt2x00dev, 34, 0x07); | ||
4254 | rt2800_rfcsr_write(rt2x00dev, 35, 0x12); | ||
4255 | rt2800_rfcsr_write(rt2x00dev, 36, 0x00); | ||
4256 | rt2800_rfcsr_write(rt2x00dev, 37, 0x08); | ||
4257 | rt2800_rfcsr_write(rt2x00dev, 38, 0x89); | ||
4258 | rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); | ||
4259 | rt2800_rfcsr_write(rt2x00dev, 40, 0x0f); | ||
4260 | rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); | ||
4261 | rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); | ||
4262 | rt2800_rfcsr_write(rt2x00dev, 43, 0x9b); | ||
4263 | rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); | ||
4264 | rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); | ||
4265 | rt2800_rfcsr_write(rt2x00dev, 46, 0x73); | ||
4266 | rt2800_rfcsr_write(rt2x00dev, 47, 0x0c); | ||
4267 | rt2800_rfcsr_write(rt2x00dev, 48, 0x10); | ||
4268 | rt2800_rfcsr_write(rt2x00dev, 49, 0x94); | ||
4269 | rt2800_rfcsr_write(rt2x00dev, 50, 0x94); | ||
4270 | rt2800_rfcsr_write(rt2x00dev, 51, 0x3a); | ||
4271 | rt2800_rfcsr_write(rt2x00dev, 52, 0x48); | ||
4272 | rt2800_rfcsr_write(rt2x00dev, 53, 0x44); | ||
4273 | rt2800_rfcsr_write(rt2x00dev, 54, 0x38); | ||
4274 | rt2800_rfcsr_write(rt2x00dev, 55, 0x43); | ||
4275 | rt2800_rfcsr_write(rt2x00dev, 56, 0xa1); | ||
4276 | rt2800_rfcsr_write(rt2x00dev, 57, 0x00); | ||
4277 | rt2800_rfcsr_write(rt2x00dev, 58, 0x39); | ||
4278 | rt2800_rfcsr_write(rt2x00dev, 59, 0x07); | ||
4279 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | ||
4280 | rt2800_rfcsr_write(rt2x00dev, 61, 0x91); | ||
4281 | rt2800_rfcsr_write(rt2x00dev, 62, 0x39); | ||
4282 | rt2800_rfcsr_write(rt2x00dev, 63, 0x07); | ||
4283 | } | 4333 | } |
4284 | 4334 | ||
4285 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { | 4335 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { |
@@ -4620,12 +4670,14 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i) | |||
4620 | mutex_unlock(&rt2x00dev->csr_mutex); | 4670 | mutex_unlock(&rt2x00dev->csr_mutex); |
4621 | } | 4671 | } |
4622 | 4672 | ||
4623 | void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) | 4673 | int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) |
4624 | { | 4674 | { |
4625 | unsigned int i; | 4675 | unsigned int i; |
4626 | 4676 | ||
4627 | for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8) | 4677 | for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8) |
4628 | rt2800_efuse_read(rt2x00dev, i); | 4678 | rt2800_efuse_read(rt2x00dev, i); |
4679 | |||
4680 | return 0; | ||
4629 | } | 4681 | } |
4630 | EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse); | 4682 | EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse); |
4631 | 4683 | ||
@@ -4635,11 +4687,14 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
4635 | u16 word; | 4687 | u16 word; |
4636 | u8 *mac; | 4688 | u8 *mac; |
4637 | u8 default_lna_gain; | 4689 | u8 default_lna_gain; |
4690 | int retval; | ||
4638 | 4691 | ||
4639 | /* | 4692 | /* |
4640 | * Read the EEPROM. | 4693 | * Read the EEPROM. |
4641 | */ | 4694 | */ |
4642 | rt2800_read_eeprom(rt2x00dev); | 4695 | retval = rt2800_read_eeprom(rt2x00dev); |
4696 | if (retval) | ||
4697 | return retval; | ||
4643 | 4698 | ||
4644 | /* | 4699 | /* |
4645 | * Start validation of the data that has been read. | 4700 | * Start validation of the data that has been read. |
@@ -5090,8 +5145,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
5090 | IEEE80211_HW_SUPPORTS_PS | | 5145 | IEEE80211_HW_SUPPORTS_PS | |
5091 | IEEE80211_HW_PS_NULLFUNC_STACK | | 5146 | IEEE80211_HW_PS_NULLFUNC_STACK | |
5092 | IEEE80211_HW_AMPDU_AGGREGATION | | 5147 | IEEE80211_HW_AMPDU_AGGREGATION | |
5093 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | 5148 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; |
5094 | IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL; | ||
5095 | 5149 | ||
5096 | /* | 5150 | /* |
5097 | * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices | 5151 | * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices |
@@ -5484,7 +5538,9 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5484 | case IEEE80211_AMPDU_TX_START: | 5538 | case IEEE80211_AMPDU_TX_START: |
5485 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 5539 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
5486 | break; | 5540 | break; |
5487 | case IEEE80211_AMPDU_TX_STOP: | 5541 | case IEEE80211_AMPDU_TX_STOP_CONT: |
5542 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
5543 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
5488 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 5544 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
5489 | break; | 5545 | break; |
5490 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 5546 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index a128ceadcb3e..6ec739466db4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -43,7 +43,7 @@ struct rt2800_ops { | |||
43 | const unsigned int offset, | 43 | const unsigned int offset, |
44 | const struct rt2x00_field32 field, u32 *reg); | 44 | const struct rt2x00_field32 field, u32 *reg); |
45 | 45 | ||
46 | void (*read_eeprom)(struct rt2x00_dev *rt2x00dev); | 46 | int (*read_eeprom)(struct rt2x00_dev *rt2x00dev); |
47 | bool (*hwcrypt_disabled)(struct rt2x00_dev *rt2x00dev); | 47 | bool (*hwcrypt_disabled)(struct rt2x00_dev *rt2x00dev); |
48 | 48 | ||
49 | int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, | 49 | int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, |
@@ -117,11 +117,11 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev, | |||
117 | return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); | 117 | return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg); |
118 | } | 118 | } |
119 | 119 | ||
120 | static inline void rt2800_read_eeprom(struct rt2x00_dev *rt2x00dev) | 120 | static inline int rt2800_read_eeprom(struct rt2x00_dev *rt2x00dev) |
121 | { | 121 | { |
122 | const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; | 122 | const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; |
123 | 123 | ||
124 | rt2800ops->read_eeprom(rt2x00dev); | 124 | return rt2800ops->read_eeprom(rt2x00dev); |
125 | } | 125 | } |
126 | 126 | ||
127 | static inline bool rt2800_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) | 127 | static inline bool rt2800_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) |
@@ -207,7 +207,7 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev); | |||
207 | void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); | 207 | void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); |
208 | 208 | ||
209 | int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev); | 209 | int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev); |
210 | void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev); | 210 | int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev); |
211 | 211 | ||
212 | int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev); | 212 | int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev); |
213 | 213 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 9224d874bf24..0e8d1705e368 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -90,17 +90,22 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
90 | } | 90 | } |
91 | 91 | ||
92 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 92 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) |
93 | static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | 93 | static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) |
94 | { | 94 | { |
95 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); | 95 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); |
96 | 96 | ||
97 | if (!base_addr) | ||
98 | return -ENOMEM; | ||
99 | |||
97 | memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); | 100 | memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); |
98 | 101 | ||
99 | iounmap(base_addr); | 102 | iounmap(base_addr); |
103 | return 0; | ||
100 | } | 104 | } |
101 | #else | 105 | #else |
102 | static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | 106 | static inline int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) |
103 | { | 107 | { |
108 | return -ENOMEM; | ||
104 | } | 109 | } |
105 | #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ | 110 | #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ |
106 | 111 | ||
@@ -135,7 +140,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom) | |||
135 | rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); | 140 | rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); |
136 | } | 141 | } |
137 | 142 | ||
138 | static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) | 143 | static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) |
139 | { | 144 | { |
140 | struct eeprom_93cx6 eeprom; | 145 | struct eeprom_93cx6 eeprom; |
141 | u32 reg; | 146 | u32 reg; |
@@ -164,6 +169,8 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) | |||
164 | 169 | ||
165 | eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, | 170 | eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, |
166 | EEPROM_SIZE / sizeof(u16)); | 171 | EEPROM_SIZE / sizeof(u16)); |
172 | |||
173 | return 0; | ||
167 | } | 174 | } |
168 | 175 | ||
169 | static int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) | 176 | static int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) |
@@ -171,13 +178,14 @@ static int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) | |||
171 | return rt2800_efuse_detect(rt2x00dev); | 178 | return rt2800_efuse_detect(rt2x00dev); |
172 | } | 179 | } |
173 | 180 | ||
174 | static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) | 181 | static inline int rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) |
175 | { | 182 | { |
176 | rt2800_read_eeprom_efuse(rt2x00dev); | 183 | return rt2800_read_eeprom_efuse(rt2x00dev); |
177 | } | 184 | } |
178 | #else | 185 | #else |
179 | static inline void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) | 186 | static inline int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) |
180 | { | 187 | { |
188 | return -EOPNOTSUPP; | ||
181 | } | 189 | } |
182 | 190 | ||
183 | static inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) | 191 | static inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) |
@@ -185,8 +193,9 @@ static inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) | |||
185 | return 0; | 193 | return 0; |
186 | } | 194 | } |
187 | 195 | ||
188 | static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) | 196 | static inline int rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) |
189 | { | 197 | { |
198 | return -EOPNOTSUPP; | ||
190 | } | 199 | } |
191 | #endif /* CONFIG_PCI */ | 200 | #endif /* CONFIG_PCI */ |
192 | 201 | ||
@@ -970,14 +979,18 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | |||
970 | /* | 979 | /* |
971 | * Device probe functions. | 980 | * Device probe functions. |
972 | */ | 981 | */ |
973 | static void rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev) | 982 | static int rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev) |
974 | { | 983 | { |
984 | int retval; | ||
985 | |||
975 | if (rt2x00_is_soc(rt2x00dev)) | 986 | if (rt2x00_is_soc(rt2x00dev)) |
976 | rt2800pci_read_eeprom_soc(rt2x00dev); | 987 | retval = rt2800pci_read_eeprom_soc(rt2x00dev); |
977 | else if (rt2800pci_efuse_detect(rt2x00dev)) | 988 | else if (rt2800pci_efuse_detect(rt2x00dev)) |
978 | rt2800pci_read_eeprom_efuse(rt2x00dev); | 989 | retval = rt2800pci_read_eeprom_efuse(rt2x00dev); |
979 | else | 990 | else |
980 | rt2800pci_read_eeprom_pci(rt2x00dev); | 991 | retval = rt2800pci_read_eeprom_pci(rt2x00dev); |
992 | |||
993 | return retval; | ||
981 | } | 994 | } |
982 | 995 | ||
983 | static const struct ieee80211_ops rt2800pci_mac80211_ops = { | 996 | static const struct ieee80211_ops rt2800pci_mac80211_ops = { |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 5c149b58ab46..4721cada1591 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -735,13 +735,17 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
735 | /* | 735 | /* |
736 | * Device probe functions. | 736 | * Device probe functions. |
737 | */ | 737 | */ |
738 | static void rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev) | 738 | static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev) |
739 | { | 739 | { |
740 | int retval; | ||
741 | |||
740 | if (rt2800_efuse_detect(rt2x00dev)) | 742 | if (rt2800_efuse_detect(rt2x00dev)) |
741 | rt2800_read_eeprom_efuse(rt2x00dev); | 743 | retval = rt2800_read_eeprom_efuse(rt2x00dev); |
742 | else | 744 | else |
743 | rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, | 745 | retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, |
744 | EEPROM_SIZE); | 746 | EEPROM_SIZE); |
747 | |||
748 | return retval; | ||
745 | } | 749 | } |
746 | 750 | ||
747 | static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) | 751 | static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 0751b35ef6dc..b52512b8ac5f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -1016,6 +1016,26 @@ struct rt2x00_dev { | |||
1016 | * Protect the interrupt mask register. | 1016 | * Protect the interrupt mask register. |
1017 | */ | 1017 | */ |
1018 | spinlock_t irqmask_lock; | 1018 | spinlock_t irqmask_lock; |
1019 | |||
1020 | /* | ||
1021 | * List of BlockAckReq TX entries that need driver BlockAck processing. | ||
1022 | */ | ||
1023 | struct list_head bar_list; | ||
1024 | spinlock_t bar_list_lock; | ||
1025 | }; | ||
1026 | |||
1027 | struct rt2x00_bar_list_entry { | ||
1028 | struct list_head list; | ||
1029 | struct rcu_head head; | ||
1030 | |||
1031 | struct queue_entry *entry; | ||
1032 | int block_acked; | ||
1033 | |||
1034 | /* Relevant parts of the IEEE80211 BAR header */ | ||
1035 | __u8 ra[6]; | ||
1036 | __u8 ta[6]; | ||
1037 | __le16 control; | ||
1038 | __le16 start_seq_num; | ||
1019 | }; | 1039 | }; |
1020 | 1040 | ||
1021 | /* | 1041 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 44f8b3f3cbed..b40a53857498 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -271,6 +271,50 @@ void rt2x00lib_dmadone(struct queue_entry *entry) | |||
271 | } | 271 | } |
272 | EXPORT_SYMBOL_GPL(rt2x00lib_dmadone); | 272 | EXPORT_SYMBOL_GPL(rt2x00lib_dmadone); |
273 | 273 | ||
274 | static inline int rt2x00lib_txdone_bar_status(struct queue_entry *entry) | ||
275 | { | ||
276 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
277 | struct ieee80211_bar *bar = (void *) entry->skb->data; | ||
278 | struct rt2x00_bar_list_entry *bar_entry; | ||
279 | int ret; | ||
280 | |||
281 | if (likely(!ieee80211_is_back_req(bar->frame_control))) | ||
282 | return 0; | ||
283 | |||
284 | /* | ||
285 | * Unlike all other frames, the status report for BARs does | ||
286 | * not directly come from the hardware as it is incapable of | ||
287 | * matching a BA to a previously send BAR. The hardware will | ||
288 | * report all BARs as if they weren't acked at all. | ||
289 | * | ||
290 | * Instead the RX-path will scan for incoming BAs and set the | ||
291 | * block_acked flag if it sees one that was likely caused by | ||
292 | * a BAR from us. | ||
293 | * | ||
294 | * Remove remaining BARs here and return their status for | ||
295 | * TX done processing. | ||
296 | */ | ||
297 | ret = 0; | ||
298 | rcu_read_lock(); | ||
299 | list_for_each_entry_rcu(bar_entry, &rt2x00dev->bar_list, list) { | ||
300 | if (bar_entry->entry != entry) | ||
301 | continue; | ||
302 | |||
303 | spin_lock_bh(&rt2x00dev->bar_list_lock); | ||
304 | /* Return whether this BAR was blockacked or not */ | ||
305 | ret = bar_entry->block_acked; | ||
306 | /* Remove the BAR from our checklist */ | ||
307 | list_del_rcu(&bar_entry->list); | ||
308 | spin_unlock_bh(&rt2x00dev->bar_list_lock); | ||
309 | kfree_rcu(bar_entry, head); | ||
310 | |||
311 | break; | ||
312 | } | ||
313 | rcu_read_unlock(); | ||
314 | |||
315 | return ret; | ||
316 | } | ||
317 | |||
274 | void rt2x00lib_txdone(struct queue_entry *entry, | 318 | void rt2x00lib_txdone(struct queue_entry *entry, |
275 | struct txdone_entry_desc *txdesc) | 319 | struct txdone_entry_desc *txdesc) |
276 | { | 320 | { |
@@ -324,9 +368,12 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
324 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb); | 368 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb); |
325 | 369 | ||
326 | /* | 370 | /* |
327 | * Determine if the frame has been successfully transmitted. | 371 | * Determine if the frame has been successfully transmitted and |
372 | * remove BARs from our check list while checking for their | ||
373 | * TX status. | ||
328 | */ | 374 | */ |
329 | success = | 375 | success = |
376 | rt2x00lib_txdone_bar_status(entry) || | ||
330 | test_bit(TXDONE_SUCCESS, &txdesc->flags) || | 377 | test_bit(TXDONE_SUCCESS, &txdesc->flags) || |
331 | test_bit(TXDONE_UNKNOWN, &txdesc->flags); | 378 | test_bit(TXDONE_UNKNOWN, &txdesc->flags); |
332 | 379 | ||
@@ -491,6 +538,50 @@ static void rt2x00lib_sleep(struct work_struct *work) | |||
491 | IEEE80211_CONF_CHANGE_PS); | 538 | IEEE80211_CONF_CHANGE_PS); |
492 | } | 539 | } |
493 | 540 | ||
541 | static void rt2x00lib_rxdone_check_ba(struct rt2x00_dev *rt2x00dev, | ||
542 | struct sk_buff *skb, | ||
543 | struct rxdone_entry_desc *rxdesc) | ||
544 | { | ||
545 | struct rt2x00_bar_list_entry *entry; | ||
546 | struct ieee80211_bar *ba = (void *)skb->data; | ||
547 | |||
548 | if (likely(!ieee80211_is_back(ba->frame_control))) | ||
549 | return; | ||
550 | |||
551 | if (rxdesc->size < sizeof(*ba) + FCS_LEN) | ||
552 | return; | ||
553 | |||
554 | rcu_read_lock(); | ||
555 | list_for_each_entry_rcu(entry, &rt2x00dev->bar_list, list) { | ||
556 | |||
557 | if (ba->start_seq_num != entry->start_seq_num) | ||
558 | continue; | ||
559 | |||
560 | #define TID_CHECK(a, b) ( \ | ||
561 | ((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) == \ | ||
562 | ((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK))) \ | ||
563 | |||
564 | if (!TID_CHECK(ba->control, entry->control)) | ||
565 | continue; | ||
566 | |||
567 | #undef TID_CHECK | ||
568 | |||
569 | if (compare_ether_addr(ba->ra, entry->ta)) | ||
570 | continue; | ||
571 | |||
572 | if (compare_ether_addr(ba->ta, entry->ra)) | ||
573 | continue; | ||
574 | |||
575 | /* Mark BAR since we received the according BA */ | ||
576 | spin_lock_bh(&rt2x00dev->bar_list_lock); | ||
577 | entry->block_acked = 1; | ||
578 | spin_unlock_bh(&rt2x00dev->bar_list_lock); | ||
579 | break; | ||
580 | } | ||
581 | rcu_read_unlock(); | ||
582 | |||
583 | } | ||
584 | |||
494 | static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev, | 585 | static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev, |
495 | struct sk_buff *skb, | 586 | struct sk_buff *skb, |
496 | struct rxdone_entry_desc *rxdesc) | 587 | struct rxdone_entry_desc *rxdesc) |
@@ -674,6 +765,12 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp) | |||
674 | rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc); | 765 | rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc); |
675 | 766 | ||
676 | /* | 767 | /* |
768 | * Check for incoming BlockAcks to match to the BlockAckReqs | ||
769 | * we've send out. | ||
770 | */ | ||
771 | rt2x00lib_rxdone_check_ba(rt2x00dev, entry->skb, &rxdesc); | ||
772 | |||
773 | /* | ||
677 | * Update extra components | 774 | * Update extra components |
678 | */ | 775 | */ |
679 | rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); | 776 | rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); |
@@ -1183,6 +1280,8 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1183 | 1280 | ||
1184 | spin_lock_init(&rt2x00dev->irqmask_lock); | 1281 | spin_lock_init(&rt2x00dev->irqmask_lock); |
1185 | mutex_init(&rt2x00dev->csr_mutex); | 1282 | mutex_init(&rt2x00dev->csr_mutex); |
1283 | INIT_LIST_HEAD(&rt2x00dev->bar_list); | ||
1284 | spin_lock_init(&rt2x00dev->bar_list_lock); | ||
1186 | 1285 | ||
1187 | set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); | 1286 | set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); |
1188 | 1287 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index e488b944a034..f35d85a71bbc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -582,6 +582,48 @@ static void rt2x00queue_kick_tx_queue(struct data_queue *queue, | |||
582 | queue->rt2x00dev->ops->lib->kick_queue(queue); | 582 | queue->rt2x00dev->ops->lib->kick_queue(queue); |
583 | } | 583 | } |
584 | 584 | ||
585 | static void rt2x00queue_bar_check(struct queue_entry *entry) | ||
586 | { | ||
587 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
588 | struct ieee80211_bar *bar = (void *) (entry->skb->data + | ||
589 | rt2x00dev->ops->extra_tx_headroom); | ||
590 | struct rt2x00_bar_list_entry *bar_entry; | ||
591 | |||
592 | if (likely(!ieee80211_is_back_req(bar->frame_control))) | ||
593 | return; | ||
594 | |||
595 | bar_entry = kmalloc(sizeof(*bar_entry), GFP_ATOMIC); | ||
596 | |||
597 | /* | ||
598 | * If the alloc fails we still send the BAR out but just don't track | ||
599 | * it in our bar list. And as a result we will report it to mac80211 | ||
600 | * back as failed. | ||
601 | */ | ||
602 | if (!bar_entry) | ||
603 | return; | ||
604 | |||
605 | bar_entry->entry = entry; | ||
606 | bar_entry->block_acked = 0; | ||
607 | |||
608 | /* | ||
609 | * Copy the relevant parts of the 802.11 BAR into out check list | ||
610 | * such that we can use RCU for less-overhead in the RX path since | ||
611 | * sending BARs and processing the according BlockAck should be | ||
612 | * the exception. | ||
613 | */ | ||
614 | memcpy(bar_entry->ra, bar->ra, sizeof(bar->ra)); | ||
615 | memcpy(bar_entry->ta, bar->ta, sizeof(bar->ta)); | ||
616 | bar_entry->control = bar->control; | ||
617 | bar_entry->start_seq_num = bar->start_seq_num; | ||
618 | |||
619 | /* | ||
620 | * Insert BAR into our BAR check list. | ||
621 | */ | ||
622 | spin_lock_bh(&rt2x00dev->bar_list_lock); | ||
623 | list_add_tail_rcu(&bar_entry->list, &rt2x00dev->bar_list); | ||
624 | spin_unlock_bh(&rt2x00dev->bar_list_lock); | ||
625 | } | ||
626 | |||
585 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, | 627 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, |
586 | bool local) | 628 | bool local) |
587 | { | 629 | { |
@@ -680,6 +722,11 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, | |||
680 | goto out; | 722 | goto out; |
681 | } | 723 | } |
682 | 724 | ||
725 | /* | ||
726 | * Put BlockAckReqs into our check list for driver BA processing. | ||
727 | */ | ||
728 | rt2x00queue_bar_check(entry); | ||
729 | |||
683 | set_bit(ENTRY_DATA_PENDING, &entry->flags); | 730 | set_bit(ENTRY_DATA_PENDING, &entry->flags); |
684 | 731 | ||
685 | rt2x00queue_index_inc(entry, Q_INDEX); | 732 | rt2x00queue_index_inc(entry, Q_INDEX); |
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig index 21b1bbb93a7e..b80bc4612581 100644 --- a/drivers/net/wireless/rtlwifi/Kconfig +++ b/drivers/net/wireless/rtlwifi/Kconfig | |||
@@ -57,12 +57,12 @@ config RTL8192CU | |||
57 | 57 | ||
58 | config RTLWIFI | 58 | config RTLWIFI |
59 | tristate | 59 | tristate |
60 | depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE | 60 | depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE |
61 | default m | 61 | default m |
62 | 62 | ||
63 | config RTLWIFI_DEBUG | 63 | config RTLWIFI_DEBUG |
64 | bool "Additional debugging output" | 64 | bool "Additional debugging output" |
65 | depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE | 65 | depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE |
66 | default y | 66 | default y |
67 | 67 | ||
68 | config RTL8192C_COMMON | 68 | config RTL8192C_COMMON |
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index be33aa14c8af..d3ce9fbef00e 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -879,7 +879,9 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, | |||
879 | "IEEE80211_AMPDU_TX_START: TID:%d\n", tid); | 879 | "IEEE80211_AMPDU_TX_START: TID:%d\n", tid); |
880 | return rtl_tx_agg_start(hw, sta, tid, ssn); | 880 | return rtl_tx_agg_start(hw, sta, tid, ssn); |
881 | break; | 881 | break; |
882 | case IEEE80211_AMPDU_TX_STOP: | 882 | case IEEE80211_AMPDU_TX_STOP_CONT: |
883 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
884 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
883 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 885 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
884 | "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); | 886 | "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); |
885 | return rtl_tx_agg_stop(hw, sta, tid); | 887 | return rtl_tx_agg_stop(hw, sta, tid); |
diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c index c1608cddc529..d7d0d4948b01 100644 --- a/drivers/net/wireless/rtlwifi/regd.c +++ b/drivers/net/wireless/rtlwifi/regd.c | |||
@@ -158,8 +158,6 @@ static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
158 | const struct ieee80211_reg_rule *reg_rule; | 158 | const struct ieee80211_reg_rule *reg_rule; |
159 | struct ieee80211_channel *ch; | 159 | struct ieee80211_channel *ch; |
160 | unsigned int i; | 160 | unsigned int i; |
161 | u32 bandwidth = 0; | ||
162 | int r; | ||
163 | 161 | ||
164 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 162 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
165 | 163 | ||
@@ -174,9 +172,8 @@ static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy, | |||
174 | (ch->flags & IEEE80211_CHAN_RADAR)) | 172 | (ch->flags & IEEE80211_CHAN_RADAR)) |
175 | continue; | 173 | continue; |
176 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { | 174 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
177 | r = freq_reg_info(wiphy, ch->center_freq, | 175 | reg_rule = freq_reg_info(wiphy, ch->center_freq); |
178 | bandwidth, ®_rule); | 176 | if (IS_ERR(reg_rule)) |
179 | if (r) | ||
180 | continue; | 177 | continue; |
181 | 178 | ||
182 | /* | 179 | /* |
@@ -211,8 +208,6 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, | |||
211 | struct ieee80211_supported_band *sband; | 208 | struct ieee80211_supported_band *sband; |
212 | struct ieee80211_channel *ch; | 209 | struct ieee80211_channel *ch; |
213 | const struct ieee80211_reg_rule *reg_rule; | 210 | const struct ieee80211_reg_rule *reg_rule; |
214 | u32 bandwidth = 0; | ||
215 | int r; | ||
216 | 211 | ||
217 | if (!wiphy->bands[IEEE80211_BAND_2GHZ]) | 212 | if (!wiphy->bands[IEEE80211_BAND_2GHZ]) |
218 | return; | 213 | return; |
@@ -240,16 +235,16 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, | |||
240 | */ | 235 | */ |
241 | 236 | ||
242 | ch = &sband->channels[11]; /* CH 12 */ | 237 | ch = &sband->channels[11]; /* CH 12 */ |
243 | r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); | 238 | reg_rule = freq_reg_info(wiphy, ch->center_freq); |
244 | if (!r) { | 239 | if (!IS_ERR(reg_rule)) { |
245 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) | 240 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) |
246 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 241 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) |
247 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 242 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; |
248 | } | 243 | } |
249 | 244 | ||
250 | ch = &sband->channels[12]; /* CH 13 */ | 245 | ch = &sband->channels[12]; /* CH 13 */ |
251 | r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); | 246 | reg_rule = freq_reg_info(wiphy, ch->center_freq); |
252 | if (!r) { | 247 | if (!IS_ERR(reg_rule)) { |
253 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) | 248 | if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) |
254 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 249 | if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) |
255 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 250 | ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; |
@@ -303,9 +298,9 @@ static void _rtl_reg_apply_world_flags(struct wiphy *wiphy, | |||
303 | return; | 298 | return; |
304 | } | 299 | } |
305 | 300 | ||
306 | static int _rtl_reg_notifier_apply(struct wiphy *wiphy, | 301 | static void _rtl_reg_notifier_apply(struct wiphy *wiphy, |
307 | struct regulatory_request *request, | 302 | struct regulatory_request *request, |
308 | struct rtl_regulatory *reg) | 303 | struct rtl_regulatory *reg) |
309 | { | 304 | { |
310 | /* We always apply this */ | 305 | /* We always apply this */ |
311 | _rtl_reg_apply_radar_flags(wiphy); | 306 | _rtl_reg_apply_radar_flags(wiphy); |
@@ -319,8 +314,6 @@ static int _rtl_reg_notifier_apply(struct wiphy *wiphy, | |||
319 | _rtl_reg_apply_world_flags(wiphy, request->initiator, reg); | 314 | _rtl_reg_apply_world_flags(wiphy, request->initiator, reg); |
320 | break; | 315 | break; |
321 | } | 316 | } |
322 | |||
323 | return 0; | ||
324 | } | 317 | } |
325 | 318 | ||
326 | static const struct ieee80211_regdomain *_rtl_regdomain_select( | 319 | static const struct ieee80211_regdomain *_rtl_regdomain_select( |
@@ -353,9 +346,9 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select( | |||
353 | 346 | ||
354 | static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg, | 347 | static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg, |
355 | struct wiphy *wiphy, | 348 | struct wiphy *wiphy, |
356 | int (*reg_notifier) (struct wiphy *wiphy, | 349 | void (*reg_notifier) (struct wiphy *wiphy, |
357 | struct regulatory_request * | 350 | struct regulatory_request * |
358 | request)) | 351 | request)) |
359 | { | 352 | { |
360 | const struct ieee80211_regdomain *regd; | 353 | const struct ieee80211_regdomain *regd; |
361 | 354 | ||
@@ -384,7 +377,7 @@ static struct country_code_to_enum_rd *_rtl_regd_find_country(u16 countrycode) | |||
384 | } | 377 | } |
385 | 378 | ||
386 | int rtl_regd_init(struct ieee80211_hw *hw, | 379 | int rtl_regd_init(struct ieee80211_hw *hw, |
387 | int (*reg_notifier) (struct wiphy *wiphy, | 380 | void (*reg_notifier) (struct wiphy *wiphy, |
388 | struct regulatory_request *request)) | 381 | struct regulatory_request *request)) |
389 | { | 382 | { |
390 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 383 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -426,12 +419,12 @@ int rtl_regd_init(struct ieee80211_hw *hw, | |||
426 | return 0; | 419 | return 0; |
427 | } | 420 | } |
428 | 421 | ||
429 | int rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) | 422 | void rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) |
430 | { | 423 | { |
431 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 424 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
432 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 425 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
433 | 426 | ||
434 | RT_TRACE(rtlpriv, COMP_REGD, DBG_LOUD, "\n"); | 427 | RT_TRACE(rtlpriv, COMP_REGD, DBG_LOUD, "\n"); |
435 | 428 | ||
436 | return _rtl_reg_notifier_apply(wiphy, request, &rtlpriv->regd); | 429 | _rtl_reg_notifier_apply(wiphy, request, &rtlpriv->regd); |
437 | } | 430 | } |
diff --git a/drivers/net/wireless/rtlwifi/regd.h b/drivers/net/wireless/rtlwifi/regd.h index 70ef2f418a44..4e1f4f00e6e9 100644 --- a/drivers/net/wireless/rtlwifi/regd.h +++ b/drivers/net/wireless/rtlwifi/regd.h | |||
@@ -55,7 +55,7 @@ enum country_code_type_t { | |||
55 | }; | 55 | }; |
56 | 56 | ||
57 | int rtl_regd_init(struct ieee80211_hw *hw, | 57 | int rtl_regd_init(struct ieee80211_hw *hw, |
58 | int (*reg_notifier) (struct wiphy *wiphy, | 58 | void (*reg_notifier) (struct wiphy *wiphy, |
59 | struct regulatory_request *request)); | 59 | struct regulatory_request *request)); |
60 | int rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); | 60 | void rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); |
61 | #endif | 61 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c index a0fbf284420e..cdb570ffb4b5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c | |||
@@ -452,7 +452,7 @@ static void _rtl92de_translate_rx_signal_stuff(struct ieee80211_hw *hw, | |||
452 | u8 *praddr; | 452 | u8 *praddr; |
453 | u16 type, cfc; | 453 | u16 type, cfc; |
454 | __le16 fc; | 454 | __le16 fc; |
455 | bool packet_matchbssid, packet_toself, packet_beacon; | 455 | bool packet_matchbssid, packet_toself, packet_beacon = false; |
456 | 456 | ||
457 | tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; | 457 | tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; |
458 | hdr = (struct ieee80211_hdr *)tmp_buf; | 458 | hdr = (struct ieee80211_hdr *)tmp_buf; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index 206561d7282f..f8431a3c2c9d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c | |||
@@ -480,7 +480,7 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, | |||
480 | u8 *praddr; | 480 | u8 *praddr; |
481 | __le16 fc; | 481 | __le16 fc; |
482 | u16 type, cfc; | 482 | u16 type, cfc; |
483 | bool packet_matchbssid, packet_toself, packet_beacon; | 483 | bool packet_matchbssid, packet_toself, packet_beacon = false; |
484 | 484 | ||
485 | tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; | 485 | tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; |
486 | 486 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c index a313be8c21d2..ce8ad12bce5b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c | |||
@@ -247,7 +247,7 @@ static void _rtl8723ae_translate_rx_signal_stuff(struct ieee80211_hw *hw, | |||
247 | u8 *psaddr; | 247 | u8 *psaddr; |
248 | __le16 fc; | 248 | __le16 fc; |
249 | u16 type; | 249 | u16 type; |
250 | bool packet_matchbssid, packet_toself, packet_beacon; | 250 | bool packet_matchbssid, packet_toself, packet_beacon = false; |
251 | 251 | ||
252 | tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; | 252 | tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; |
253 | 253 | ||
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index ea9d8e011bc9..ce6e62a37e14 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -89,8 +89,8 @@ static int wl12xx_set_authorized(struct wl1271 *wl, | |||
89 | return 0; | 89 | return 0; |
90 | } | 90 | } |
91 | 91 | ||
92 | static int wl1271_reg_notify(struct wiphy *wiphy, | 92 | static void wl1271_reg_notify(struct wiphy *wiphy, |
93 | struct regulatory_request *request) | 93 | struct regulatory_request *request) |
94 | { | 94 | { |
95 | struct ieee80211_supported_band *band; | 95 | struct ieee80211_supported_band *band; |
96 | struct ieee80211_channel *ch; | 96 | struct ieee80211_channel *ch; |
@@ -107,8 +107,6 @@ static int wl1271_reg_notify(struct wiphy *wiphy, | |||
107 | IEEE80211_CHAN_PASSIVE_SCAN; | 107 | IEEE80211_CHAN_PASSIVE_SCAN; |
108 | 108 | ||
109 | } | 109 | } |
110 | |||
111 | return 0; | ||
112 | } | 110 | } |
113 | 111 | ||
114 | static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 112 | static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
@@ -4575,7 +4573,9 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, | |||
4575 | * Falling break here on purpose for all TX APDU commands. | 4573 | * Falling break here on purpose for all TX APDU commands. |
4576 | */ | 4574 | */ |
4577 | case IEEE80211_AMPDU_TX_START: | 4575 | case IEEE80211_AMPDU_TX_START: |
4578 | case IEEE80211_AMPDU_TX_STOP: | 4576 | case IEEE80211_AMPDU_TX_STOP_CONT: |
4577 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
4578 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
4579 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 4579 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
4580 | ret = -EINVAL; | 4580 | ret = -EINVAL; |
4581 | break; | 4581 | break; |
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index ec857676c39f..80c728b28828 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig | |||
@@ -5,19 +5,6 @@ | |||
5 | menu "Near Field Communication (NFC) devices" | 5 | menu "Near Field Communication (NFC) devices" |
6 | depends on NFC | 6 | depends on NFC |
7 | 7 | ||
8 | config PN544_HCI_NFC | ||
9 | tristate "HCI PN544 NFC driver" | ||
10 | depends on I2C && NFC_HCI && NFC_SHDLC | ||
11 | select CRC_CCITT | ||
12 | default n | ||
13 | ---help--- | ||
14 | NXP PN544 i2c driver. | ||
15 | This is a driver based on the SHDLC and HCI NFC kernel layers and | ||
16 | will thus not work with NXP libnfc library. | ||
17 | |||
18 | To compile this driver as a module, choose m here. The module will | ||
19 | be called pn544_hci. | ||
20 | |||
21 | config NFC_PN533 | 8 | config NFC_PN533 |
22 | tristate "NXP PN533 USB driver" | 9 | tristate "NXP PN533 USB driver" |
23 | depends on USB | 10 | depends on USB |
@@ -39,4 +26,6 @@ config NFC_WILINK | |||
39 | Say Y here to compile support for Texas Instrument's NFC WiLink driver | 26 | Say Y here to compile support for Texas Instrument's NFC WiLink driver |
40 | into the kernel or say M to compile it as module. | 27 | into the kernel or say M to compile it as module. |
41 | 28 | ||
29 | source "drivers/nfc/pn544/Kconfig" | ||
30 | |||
42 | endmenu | 31 | endmenu |
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index 36c359043f54..574bbc04d97a 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for nfc devices | 2 | # Makefile for nfc devices |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PN544_HCI_NFC) += pn544/ | 5 | obj-$(CONFIG_NFC_PN544) += pn544/ |
6 | obj-$(CONFIG_NFC_PN533) += pn533.o | 6 | obj-$(CONFIG_NFC_PN533) += pn533.o |
7 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o | 7 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o |
8 | 8 | ||
diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c index 50b1ee41afc6..3b731acbc408 100644 --- a/drivers/nfc/nfcwilink.c +++ b/drivers/nfc/nfcwilink.c | |||
@@ -526,7 +526,7 @@ static int nfcwilink_probe(struct platform_device *pdev) | |||
526 | 526 | ||
527 | nfc_dev_dbg(&pdev->dev, "probe entry"); | 527 | nfc_dev_dbg(&pdev->dev, "probe entry"); |
528 | 528 | ||
529 | drv = kzalloc(sizeof(struct nfcwilink), GFP_KERNEL); | 529 | drv = devm_kzalloc(&pdev->dev, sizeof(struct nfcwilink), GFP_KERNEL); |
530 | if (!drv) { | 530 | if (!drv) { |
531 | rc = -ENOMEM; | 531 | rc = -ENOMEM; |
532 | goto exit; | 532 | goto exit; |
@@ -542,12 +542,13 @@ static int nfcwilink_probe(struct platform_device *pdev) | |||
542 | 542 | ||
543 | drv->ndev = nci_allocate_device(&nfcwilink_ops, | 543 | drv->ndev = nci_allocate_device(&nfcwilink_ops, |
544 | protocols, | 544 | protocols, |
545 | NFC_SE_NONE, | ||
545 | NFCWILINK_HDR_LEN, | 546 | NFCWILINK_HDR_LEN, |
546 | 0); | 547 | 0); |
547 | if (!drv->ndev) { | 548 | if (!drv->ndev) { |
548 | nfc_dev_err(&pdev->dev, "nci_allocate_device failed"); | 549 | nfc_dev_err(&pdev->dev, "nci_allocate_device failed"); |
549 | rc = -ENOMEM; | 550 | rc = -ENOMEM; |
550 | goto free_exit; | 551 | goto exit; |
551 | } | 552 | } |
552 | 553 | ||
553 | nci_set_parent_dev(drv->ndev, &pdev->dev); | 554 | nci_set_parent_dev(drv->ndev, &pdev->dev); |
@@ -566,9 +567,6 @@ static int nfcwilink_probe(struct platform_device *pdev) | |||
566 | free_dev_exit: | 567 | free_dev_exit: |
567 | nci_free_device(drv->ndev); | 568 | nci_free_device(drv->ndev); |
568 | 569 | ||
569 | free_exit: | ||
570 | kfree(drv); | ||
571 | |||
572 | exit: | 570 | exit: |
573 | return rc; | 571 | return rc; |
574 | } | 572 | } |
@@ -588,8 +586,6 @@ static int nfcwilink_remove(struct platform_device *pdev) | |||
588 | nci_unregister_device(ndev); | 586 | nci_unregister_device(ndev); |
589 | nci_free_device(ndev); | 587 | nci_free_device(ndev); |
590 | 588 | ||
591 | kfree(drv); | ||
592 | |||
593 | dev_set_drvdata(&pdev->dev, NULL); | 589 | dev_set_drvdata(&pdev->dev, NULL); |
594 | 590 | ||
595 | return 0; | 591 | return 0; |
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index ada681b01a17..f696318cfb51 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -41,11 +41,6 @@ | |||
41 | #define SONY_VENDOR_ID 0x054c | 41 | #define SONY_VENDOR_ID 0x054c |
42 | #define PASORI_PRODUCT_ID 0x02e1 | 42 | #define PASORI_PRODUCT_ID 0x02e1 |
43 | 43 | ||
44 | #define PN533_QUIRKS_TYPE_A BIT(0) | ||
45 | #define PN533_QUIRKS_TYPE_F BIT(1) | ||
46 | #define PN533_QUIRKS_DEP BIT(2) | ||
47 | #define PN533_QUIRKS_RAW_EXCHANGE BIT(3) | ||
48 | |||
49 | #define PN533_DEVICE_STD 0x1 | 44 | #define PN533_DEVICE_STD 0x1 |
50 | #define PN533_DEVICE_PASORI 0x2 | 45 | #define PN533_DEVICE_PASORI 0x2 |
51 | 46 | ||
@@ -84,14 +79,18 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
84 | #define PN533_LISTEN_TIME 2 | 79 | #define PN533_LISTEN_TIME 2 |
85 | 80 | ||
86 | /* frame definitions */ | 81 | /* frame definitions */ |
87 | #define PN533_NORMAL_FRAME_MAX_LEN 262 /* 6 (PREAMBLE, SOF, LEN, LCS, TFI) | 82 | #define PN533_FRAME_HEADER_LEN (sizeof(struct pn533_frame) \ |
88 | 254 (DATA) | 83 | + 2) /* data[0] TFI, data[1] CC */ |
89 | 2 (DCS, postamble) */ | 84 | #define PN533_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/ |
90 | 85 | ||
91 | #define PN533_FRAME_TAIL_SIZE 2 | 86 | /* |
92 | #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ | 87 | * Max extended frame payload len, excluding TFI and CC |
93 | PN533_FRAME_TAIL_SIZE) | 88 | * which are already in PN533_FRAME_HEADER_LEN. |
94 | #define PN533_FRAME_ACK_SIZE (sizeof(struct pn533_frame) + 1) | 89 | */ |
90 | #define PN533_FRAME_MAX_PAYLOAD_LEN 263 | ||
91 | |||
92 | #define PN533_FRAME_ACK_SIZE 6 /* Preamble (1), SoPC (2), ACK Code (2), | ||
93 | Postamble (1) */ | ||
95 | #define PN533_FRAME_CHECKSUM(f) (f->data[f->datalen]) | 94 | #define PN533_FRAME_CHECKSUM(f) (f->data[f->datalen]) |
96 | #define PN533_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1]) | 95 | #define PN533_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1]) |
97 | 96 | ||
@@ -105,8 +104,6 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
105 | 104 | ||
106 | /* PN533 Commands */ | 105 | /* PN533 Commands */ |
107 | #define PN533_FRAME_CMD(f) (f->data[1]) | 106 | #define PN533_FRAME_CMD(f) (f->data[1]) |
108 | #define PN533_FRAME_CMD_PARAMS_PTR(f) (&f->data[2]) | ||
109 | #define PN533_FRAME_CMD_PARAMS_LEN(f) (f->datalen - 2) | ||
110 | 107 | ||
111 | #define PN533_CMD_GET_FIRMWARE_VERSION 0x02 | 108 | #define PN533_CMD_GET_FIRMWARE_VERSION 0x02 |
112 | #define PN533_CMD_RF_CONFIGURATION 0x32 | 109 | #define PN533_CMD_RF_CONFIGURATION 0x32 |
@@ -120,6 +117,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
120 | #define PN533_CMD_TG_INIT_AS_TARGET 0x8c | 117 | #define PN533_CMD_TG_INIT_AS_TARGET 0x8c |
121 | #define PN533_CMD_TG_GET_DATA 0x86 | 118 | #define PN533_CMD_TG_GET_DATA 0x86 |
122 | #define PN533_CMD_TG_SET_DATA 0x8e | 119 | #define PN533_CMD_TG_SET_DATA 0x8e |
120 | #define PN533_CMD_UNDEF 0xff | ||
123 | 121 | ||
124 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) | 122 | #define PN533_CMD_RESPONSE(cmd) (cmd + 1) |
125 | 123 | ||
@@ -128,13 +126,12 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
128 | #define PN533_CMD_MI_MASK 0x40 | 126 | #define PN533_CMD_MI_MASK 0x40 |
129 | #define PN533_CMD_RET_SUCCESS 0x00 | 127 | #define PN533_CMD_RET_SUCCESS 0x00 |
130 | 128 | ||
131 | /* PN533 status codes */ | ||
132 | #define PN533_STATUS_TARGET_RELEASED 0x29 | ||
133 | |||
134 | struct pn533; | 129 | struct pn533; |
135 | 130 | ||
136 | typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, | 131 | typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, int status); |
137 | u8 *params, int params_len); | 132 | |
133 | typedef int (*pn533_send_async_complete_t) (struct pn533 *dev, void *arg, | ||
134 | struct sk_buff *resp); | ||
138 | 135 | ||
139 | /* structs for pn533 commands */ | 136 | /* structs for pn533 commands */ |
140 | 137 | ||
@@ -282,11 +279,6 @@ const struct pn533_poll_modulations poll_mod[] = { | |||
282 | 279 | ||
283 | /* PN533_CMD_IN_ATR */ | 280 | /* PN533_CMD_IN_ATR */ |
284 | 281 | ||
285 | struct pn533_cmd_activate_param { | ||
286 | u8 tg; | ||
287 | u8 next; | ||
288 | } __packed; | ||
289 | |||
290 | struct pn533_cmd_activate_response { | 282 | struct pn533_cmd_activate_response { |
291 | u8 status; | 283 | u8 status; |
292 | u8 nfcid3t[10]; | 284 | u8 nfcid3t[10]; |
@@ -299,14 +291,6 @@ struct pn533_cmd_activate_response { | |||
299 | u8 gt[]; | 291 | u8 gt[]; |
300 | } __packed; | 292 | } __packed; |
301 | 293 | ||
302 | /* PN533_CMD_IN_JUMP_FOR_DEP */ | ||
303 | struct pn533_cmd_jump_dep { | ||
304 | u8 active; | ||
305 | u8 baud; | ||
306 | u8 next; | ||
307 | u8 data[]; | ||
308 | } __packed; | ||
309 | |||
310 | struct pn533_cmd_jump_dep_response { | 294 | struct pn533_cmd_jump_dep_response { |
311 | u8 status; | 295 | u8 status; |
312 | u8 tg; | 296 | u8 tg; |
@@ -329,32 +313,13 @@ struct pn533_cmd_jump_dep_response { | |||
329 | #define PN533_INIT_TARGET_RESP_ACTIVE 0x1 | 313 | #define PN533_INIT_TARGET_RESP_ACTIVE 0x1 |
330 | #define PN533_INIT_TARGET_RESP_DEP 0x4 | 314 | #define PN533_INIT_TARGET_RESP_DEP 0x4 |
331 | 315 | ||
332 | struct pn533_cmd_init_target { | ||
333 | u8 mode; | ||
334 | u8 mifare[6]; | ||
335 | u8 felica[18]; | ||
336 | u8 nfcid3[10]; | ||
337 | u8 gb_len; | ||
338 | u8 gb[]; | ||
339 | } __packed; | ||
340 | |||
341 | struct pn533_cmd_init_target_response { | ||
342 | u8 mode; | ||
343 | u8 cmd[]; | ||
344 | } __packed; | ||
345 | |||
346 | struct pn533 { | 316 | struct pn533 { |
347 | struct usb_device *udev; | 317 | struct usb_device *udev; |
348 | struct usb_interface *interface; | 318 | struct usb_interface *interface; |
349 | struct nfc_dev *nfc_dev; | 319 | struct nfc_dev *nfc_dev; |
350 | 320 | ||
351 | struct urb *out_urb; | 321 | struct urb *out_urb; |
352 | int out_maxlen; | ||
353 | struct pn533_frame *out_frame; | ||
354 | |||
355 | struct urb *in_urb; | 322 | struct urb *in_urb; |
356 | int in_maxlen; | ||
357 | struct pn533_frame *in_frame; | ||
358 | 323 | ||
359 | struct sk_buff_head resp_q; | 324 | struct sk_buff_head resp_q; |
360 | 325 | ||
@@ -365,12 +330,12 @@ struct pn533 { | |||
365 | struct work_struct mi_work; | 330 | struct work_struct mi_work; |
366 | struct work_struct tg_work; | 331 | struct work_struct tg_work; |
367 | struct timer_list listen_timer; | 332 | struct timer_list listen_timer; |
368 | struct pn533_frame *wq_in_frame; | ||
369 | int wq_in_error; | 333 | int wq_in_error; |
370 | int cancel_listen; | 334 | int cancel_listen; |
371 | 335 | ||
372 | pn533_cmd_complete_t cmd_complete; | 336 | pn533_cmd_complete_t cmd_complete; |
373 | void *cmd_complete_arg; | 337 | void *cmd_complete_arg; |
338 | void *cmd_complete_mi_arg; | ||
374 | struct mutex cmd_lock; | 339 | struct mutex cmd_lock; |
375 | u8 cmd; | 340 | u8 cmd; |
376 | 341 | ||
@@ -391,16 +356,17 @@ struct pn533 { | |||
391 | 356 | ||
392 | struct list_head cmd_queue; | 357 | struct list_head cmd_queue; |
393 | u8 cmd_pending; | 358 | u8 cmd_pending; |
359 | |||
360 | struct pn533_frame_ops *ops; | ||
394 | }; | 361 | }; |
395 | 362 | ||
396 | struct pn533_cmd { | 363 | struct pn533_cmd { |
397 | struct list_head queue; | 364 | struct list_head queue; |
398 | struct pn533_frame *out_frame; | 365 | u8 cmd_code; |
399 | struct pn533_frame *in_frame; | 366 | struct sk_buff *req; |
400 | int in_frame_len; | 367 | struct sk_buff *resp; |
401 | pn533_cmd_complete_t cmd_complete; | 368 | int resp_len; |
402 | void *arg; | 369 | void *arg; |
403 | gfp_t flags; | ||
404 | }; | 370 | }; |
405 | 371 | ||
406 | struct pn533_frame { | 372 | struct pn533_frame { |
@@ -411,6 +377,22 @@ struct pn533_frame { | |||
411 | u8 data[]; | 377 | u8 data[]; |
412 | } __packed; | 378 | } __packed; |
413 | 379 | ||
380 | struct pn533_frame_ops { | ||
381 | void (*tx_frame_init)(void *frame, u8 cmd_code); | ||
382 | void (*tx_frame_finish)(void *frame); | ||
383 | void (*tx_update_payload_len)(void *frame, int len); | ||
384 | int tx_header_len; | ||
385 | int tx_tail_len; | ||
386 | |||
387 | bool (*rx_is_frame_valid)(void *frame); | ||
388 | int (*rx_frame_size)(void *frame); | ||
389 | int rx_header_len; | ||
390 | int rx_tail_len; | ||
391 | |||
392 | int max_payload_len; | ||
393 | u8 (*get_cmd_code)(void *frame); | ||
394 | }; | ||
395 | |||
414 | /* The rule: value + checksum = 0 */ | 396 | /* The rule: value + checksum = 0 */ |
415 | static inline u8 pn533_checksum(u8 value) | 397 | static inline u8 pn533_checksum(u8 value) |
416 | { | 398 | { |
@@ -429,37 +411,21 @@ static u8 pn533_data_checksum(u8 *data, int datalen) | |||
429 | return pn533_checksum(sum); | 411 | return pn533_checksum(sum); |
430 | } | 412 | } |
431 | 413 | ||
432 | /** | 414 | static void pn533_tx_frame_init(void *_frame, u8 cmd_code) |
433 | * pn533_tx_frame_ack - create a ack frame | ||
434 | * @frame: The frame to be set as ack | ||
435 | * | ||
436 | * Ack is different type of standard frame. As a standard frame, it has | ||
437 | * preamble and start_frame. However the checksum of this frame must fail, | ||
438 | * i.e. datalen + datalen_checksum must NOT be zero. When the checksum test | ||
439 | * fails and datalen = 0 and datalen_checksum = 0xFF, the frame is a ack. | ||
440 | * After datalen_checksum field, the postamble is placed. | ||
441 | */ | ||
442 | static void pn533_tx_frame_ack(struct pn533_frame *frame) | ||
443 | { | 415 | { |
444 | frame->preamble = 0; | 416 | struct pn533_frame *frame = _frame; |
445 | frame->start_frame = cpu_to_be16(PN533_SOF); | ||
446 | frame->datalen = 0; | ||
447 | frame->datalen_checksum = 0xFF; | ||
448 | /* data[0] is used as postamble */ | ||
449 | frame->data[0] = 0; | ||
450 | } | ||
451 | 417 | ||
452 | static void pn533_tx_frame_init(struct pn533_frame *frame, u8 cmd) | ||
453 | { | ||
454 | frame->preamble = 0; | 418 | frame->preamble = 0; |
455 | frame->start_frame = cpu_to_be16(PN533_SOF); | 419 | frame->start_frame = cpu_to_be16(PN533_SOF); |
456 | PN533_FRAME_IDENTIFIER(frame) = PN533_DIR_OUT; | 420 | PN533_FRAME_IDENTIFIER(frame) = PN533_DIR_OUT; |
457 | PN533_FRAME_CMD(frame) = cmd; | 421 | PN533_FRAME_CMD(frame) = cmd_code; |
458 | frame->datalen = 2; | 422 | frame->datalen = 2; |
459 | } | 423 | } |
460 | 424 | ||
461 | static void pn533_tx_frame_finish(struct pn533_frame *frame) | 425 | static void pn533_tx_frame_finish(void *_frame) |
462 | { | 426 | { |
427 | struct pn533_frame *frame = _frame; | ||
428 | |||
463 | frame->datalen_checksum = pn533_checksum(frame->datalen); | 429 | frame->datalen_checksum = pn533_checksum(frame->datalen); |
464 | 430 | ||
465 | PN533_FRAME_CHECKSUM(frame) = | 431 | PN533_FRAME_CHECKSUM(frame) = |
@@ -468,9 +434,17 @@ static void pn533_tx_frame_finish(struct pn533_frame *frame) | |||
468 | PN533_FRAME_POSTAMBLE(frame) = 0; | 434 | PN533_FRAME_POSTAMBLE(frame) = 0; |
469 | } | 435 | } |
470 | 436 | ||
471 | static bool pn533_rx_frame_is_valid(struct pn533_frame *frame) | 437 | static void pn533_tx_update_payload_len(void *_frame, int len) |
438 | { | ||
439 | struct pn533_frame *frame = _frame; | ||
440 | |||
441 | frame->datalen += len; | ||
442 | } | ||
443 | |||
444 | static bool pn533_rx_frame_is_valid(void *_frame) | ||
472 | { | 445 | { |
473 | u8 checksum; | 446 | u8 checksum; |
447 | struct pn533_frame *frame = _frame; | ||
474 | 448 | ||
475 | if (frame->start_frame != cpu_to_be16(PN533_SOF)) | 449 | if (frame->start_frame != cpu_to_be16(PN533_SOF)) |
476 | return false; | 450 | return false; |
@@ -497,28 +471,48 @@ static bool pn533_rx_frame_is_ack(struct pn533_frame *frame) | |||
497 | return true; | 471 | return true; |
498 | } | 472 | } |
499 | 473 | ||
500 | static bool pn533_rx_frame_is_cmd_response(struct pn533_frame *frame, u8 cmd) | 474 | static inline int pn533_rx_frame_size(void *frame) |
475 | { | ||
476 | struct pn533_frame *f = frame; | ||
477 | |||
478 | return sizeof(struct pn533_frame) + f->datalen + PN533_FRAME_TAIL_LEN; | ||
479 | } | ||
480 | |||
481 | static u8 pn533_get_cmd_code(void *frame) | ||
482 | { | ||
483 | struct pn533_frame *f = frame; | ||
484 | |||
485 | return PN533_FRAME_CMD(f); | ||
486 | } | ||
487 | |||
488 | struct pn533_frame_ops pn533_std_frame_ops = { | ||
489 | .tx_frame_init = pn533_tx_frame_init, | ||
490 | .tx_frame_finish = pn533_tx_frame_finish, | ||
491 | .tx_update_payload_len = pn533_tx_update_payload_len, | ||
492 | .tx_header_len = PN533_FRAME_HEADER_LEN, | ||
493 | .tx_tail_len = PN533_FRAME_TAIL_LEN, | ||
494 | |||
495 | .rx_is_frame_valid = pn533_rx_frame_is_valid, | ||
496 | .rx_frame_size = pn533_rx_frame_size, | ||
497 | .rx_header_len = PN533_FRAME_HEADER_LEN, | ||
498 | .rx_tail_len = PN533_FRAME_TAIL_LEN, | ||
499 | |||
500 | .max_payload_len = PN533_FRAME_MAX_PAYLOAD_LEN, | ||
501 | .get_cmd_code = pn533_get_cmd_code, | ||
502 | }; | ||
503 | |||
504 | static bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame) | ||
501 | { | 505 | { |
502 | return (PN533_FRAME_CMD(frame) == PN533_CMD_RESPONSE(cmd)); | 506 | return (dev->ops->get_cmd_code(frame) == PN533_CMD_RESPONSE(dev->cmd)); |
503 | } | 507 | } |
504 | 508 | ||
505 | 509 | ||
506 | static void pn533_wq_cmd_complete(struct work_struct *work) | 510 | static void pn533_wq_cmd_complete(struct work_struct *work) |
507 | { | 511 | { |
508 | struct pn533 *dev = container_of(work, struct pn533, cmd_complete_work); | 512 | struct pn533 *dev = container_of(work, struct pn533, cmd_complete_work); |
509 | struct pn533_frame *in_frame; | ||
510 | int rc; | 513 | int rc; |
511 | 514 | ||
512 | in_frame = dev->wq_in_frame; | 515 | rc = dev->cmd_complete(dev, dev->cmd_complete_arg, dev->wq_in_error); |
513 | |||
514 | if (dev->wq_in_error) | ||
515 | rc = dev->cmd_complete(dev, dev->cmd_complete_arg, NULL, | ||
516 | dev->wq_in_error); | ||
517 | else | ||
518 | rc = dev->cmd_complete(dev, dev->cmd_complete_arg, | ||
519 | PN533_FRAME_CMD_PARAMS_PTR(in_frame), | ||
520 | PN533_FRAME_CMD_PARAMS_LEN(in_frame)); | ||
521 | |||
522 | if (rc != -EINPROGRESS) | 516 | if (rc != -EINPROGRESS) |
523 | queue_work(dev->wq, &dev->cmd_work); | 517 | queue_work(dev->wq, &dev->cmd_work); |
524 | } | 518 | } |
@@ -526,46 +520,47 @@ static void pn533_wq_cmd_complete(struct work_struct *work) | |||
526 | static void pn533_recv_response(struct urb *urb) | 520 | static void pn533_recv_response(struct urb *urb) |
527 | { | 521 | { |
528 | struct pn533 *dev = urb->context; | 522 | struct pn533 *dev = urb->context; |
529 | struct pn533_frame *in_frame; | 523 | u8 *in_frame; |
530 | |||
531 | dev->wq_in_frame = NULL; | ||
532 | 524 | ||
533 | switch (urb->status) { | 525 | switch (urb->status) { |
534 | case 0: | 526 | case 0: |
535 | /* success */ | 527 | break; /* success */ |
536 | break; | ||
537 | case -ECONNRESET: | 528 | case -ECONNRESET: |
538 | case -ENOENT: | 529 | case -ENOENT: |
539 | case -ESHUTDOWN: | 530 | nfc_dev_dbg(&dev->interface->dev, |
540 | nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with" | 531 | "The urb has been canceled (status %d)", |
541 | " status: %d", urb->status); | 532 | urb->status); |
542 | dev->wq_in_error = urb->status; | 533 | dev->wq_in_error = urb->status; |
543 | goto sched_wq; | 534 | goto sched_wq; |
535 | break; | ||
536 | case -ESHUTDOWN: | ||
544 | default: | 537 | default: |
545 | nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:" | 538 | nfc_dev_err(&dev->interface->dev, |
546 | " %d", urb->status); | 539 | "Urb failure (status %d)", urb->status); |
547 | dev->wq_in_error = urb->status; | 540 | dev->wq_in_error = urb->status; |
548 | goto sched_wq; | 541 | goto sched_wq; |
549 | } | 542 | } |
550 | 543 | ||
551 | in_frame = dev->in_urb->transfer_buffer; | 544 | in_frame = dev->in_urb->transfer_buffer; |
552 | 545 | ||
553 | if (!pn533_rx_frame_is_valid(in_frame)) { | 546 | nfc_dev_dbg(&dev->interface->dev, "Received a frame."); |
547 | print_hex_dump(KERN_DEBUG, "PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, | ||
548 | in_frame, dev->ops->rx_frame_size(in_frame), false); | ||
549 | |||
550 | if (!dev->ops->rx_is_frame_valid(in_frame)) { | ||
554 | nfc_dev_err(&dev->interface->dev, "Received an invalid frame"); | 551 | nfc_dev_err(&dev->interface->dev, "Received an invalid frame"); |
555 | dev->wq_in_error = -EIO; | 552 | dev->wq_in_error = -EIO; |
556 | goto sched_wq; | 553 | goto sched_wq; |
557 | } | 554 | } |
558 | 555 | ||
559 | if (!pn533_rx_frame_is_cmd_response(in_frame, dev->cmd)) { | 556 | if (!pn533_rx_frame_is_cmd_response(dev, in_frame)) { |
560 | nfc_dev_err(&dev->interface->dev, "The received frame is not " | 557 | nfc_dev_err(&dev->interface->dev, |
561 | "response to the last command"); | 558 | "It it not the response to the last command"); |
562 | dev->wq_in_error = -EIO; | 559 | dev->wq_in_error = -EIO; |
563 | goto sched_wq; | 560 | goto sched_wq; |
564 | } | 561 | } |
565 | 562 | ||
566 | nfc_dev_dbg(&dev->interface->dev, "Received a valid frame"); | ||
567 | dev->wq_in_error = 0; | 563 | dev->wq_in_error = 0; |
568 | dev->wq_in_frame = in_frame; | ||
569 | 564 | ||
570 | sched_wq: | 565 | sched_wq: |
571 | queue_work(dev->wq, &dev->cmd_complete_work); | 566 | queue_work(dev->wq, &dev->cmd_complete_work); |
@@ -586,18 +581,19 @@ static void pn533_recv_ack(struct urb *urb) | |||
586 | 581 | ||
587 | switch (urb->status) { | 582 | switch (urb->status) { |
588 | case 0: | 583 | case 0: |
589 | /* success */ | 584 | break; /* success */ |
590 | break; | ||
591 | case -ECONNRESET: | 585 | case -ECONNRESET: |
592 | case -ENOENT: | 586 | case -ENOENT: |
593 | case -ESHUTDOWN: | 587 | nfc_dev_dbg(&dev->interface->dev, |
594 | nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with" | 588 | "The urb has been stopped (status %d)", |
595 | " status: %d", urb->status); | 589 | urb->status); |
596 | dev->wq_in_error = urb->status; | 590 | dev->wq_in_error = urb->status; |
597 | goto sched_wq; | 591 | goto sched_wq; |
592 | break; | ||
593 | case -ESHUTDOWN: | ||
598 | default: | 594 | default: |
599 | nfc_dev_err(&dev->interface->dev, "Nonzero urb status received:" | 595 | nfc_dev_err(&dev->interface->dev, |
600 | " %d", urb->status); | 596 | "Urb failure (status %d)", urb->status); |
601 | dev->wq_in_error = urb->status; | 597 | dev->wq_in_error = urb->status; |
602 | goto sched_wq; | 598 | goto sched_wq; |
603 | } | 599 | } |
@@ -610,12 +606,10 @@ static void pn533_recv_ack(struct urb *urb) | |||
610 | goto sched_wq; | 606 | goto sched_wq; |
611 | } | 607 | } |
612 | 608 | ||
613 | nfc_dev_dbg(&dev->interface->dev, "Received a valid ack"); | ||
614 | |||
615 | rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); | 609 | rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC); |
616 | if (rc) { | 610 | if (rc) { |
617 | nfc_dev_err(&dev->interface->dev, "usb_submit_urb failed with" | 611 | nfc_dev_err(&dev->interface->dev, |
618 | " result %d", rc); | 612 | "usb_submit_urb failed with result %d", rc); |
619 | dev->wq_in_error = rc; | 613 | dev->wq_in_error = rc; |
620 | goto sched_wq; | 614 | goto sched_wq; |
621 | } | 615 | } |
@@ -623,7 +617,6 @@ static void pn533_recv_ack(struct urb *urb) | |||
623 | return; | 617 | return; |
624 | 618 | ||
625 | sched_wq: | 619 | sched_wq: |
626 | dev->wq_in_frame = NULL; | ||
627 | queue_work(dev->wq, &dev->cmd_complete_work); | 620 | queue_work(dev->wq, &dev->cmd_complete_work); |
628 | } | 621 | } |
629 | 622 | ||
@@ -636,47 +629,46 @@ static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags) | |||
636 | 629 | ||
637 | static int pn533_send_ack(struct pn533 *dev, gfp_t flags) | 630 | static int pn533_send_ack(struct pn533 *dev, gfp_t flags) |
638 | { | 631 | { |
632 | u8 ack[PN533_FRAME_ACK_SIZE] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; | ||
633 | /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ | ||
639 | int rc; | 634 | int rc; |
640 | 635 | ||
641 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 636 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
642 | 637 | ||
643 | pn533_tx_frame_ack(dev->out_frame); | 638 | dev->out_urb->transfer_buffer = ack; |
644 | 639 | dev->out_urb->transfer_buffer_length = sizeof(ack); | |
645 | dev->out_urb->transfer_buffer = dev->out_frame; | ||
646 | dev->out_urb->transfer_buffer_length = PN533_FRAME_ACK_SIZE; | ||
647 | rc = usb_submit_urb(dev->out_urb, flags); | 640 | rc = usb_submit_urb(dev->out_urb, flags); |
648 | 641 | ||
649 | return rc; | 642 | return rc; |
650 | } | 643 | } |
651 | 644 | ||
652 | static int __pn533_send_cmd_frame_async(struct pn533 *dev, | 645 | static int __pn533_send_frame_async(struct pn533 *dev, |
653 | struct pn533_frame *out_frame, | 646 | struct sk_buff *out, |
654 | struct pn533_frame *in_frame, | 647 | struct sk_buff *in, |
655 | int in_frame_len, | 648 | int in_len, |
656 | pn533_cmd_complete_t cmd_complete, | 649 | pn533_cmd_complete_t cmd_complete, |
657 | void *arg, gfp_t flags) | 650 | void *arg) |
658 | { | 651 | { |
659 | int rc; | 652 | int rc; |
660 | 653 | ||
661 | nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x", | 654 | dev->cmd = dev->ops->get_cmd_code(out->data); |
662 | PN533_FRAME_CMD(out_frame)); | ||
663 | |||
664 | dev->cmd = PN533_FRAME_CMD(out_frame); | ||
665 | dev->cmd_complete = cmd_complete; | 655 | dev->cmd_complete = cmd_complete; |
666 | dev->cmd_complete_arg = arg; | 656 | dev->cmd_complete_arg = arg; |
667 | 657 | ||
668 | dev->out_urb->transfer_buffer = out_frame; | 658 | dev->out_urb->transfer_buffer = out->data; |
669 | dev->out_urb->transfer_buffer_length = | 659 | dev->out_urb->transfer_buffer_length = out->len; |
670 | PN533_FRAME_SIZE(out_frame); | ||
671 | 660 | ||
672 | dev->in_urb->transfer_buffer = in_frame; | 661 | dev->in_urb->transfer_buffer = in->data; |
673 | dev->in_urb->transfer_buffer_length = in_frame_len; | 662 | dev->in_urb->transfer_buffer_length = in_len; |
674 | 663 | ||
675 | rc = usb_submit_urb(dev->out_urb, flags); | 664 | print_hex_dump(KERN_DEBUG, "PN533 TX: ", DUMP_PREFIX_NONE, 16, 1, |
665 | out->data, out->len, false); | ||
666 | |||
667 | rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); | ||
676 | if (rc) | 668 | if (rc) |
677 | return rc; | 669 | return rc; |
678 | 670 | ||
679 | rc = pn533_submit_urb_for_ack(dev, flags); | 671 | rc = pn533_submit_urb_for_ack(dev, GFP_KERNEL); |
680 | if (rc) | 672 | if (rc) |
681 | goto error; | 673 | goto error; |
682 | 674 | ||
@@ -687,146 +679,325 @@ error: | |||
687 | return rc; | 679 | return rc; |
688 | } | 680 | } |
689 | 681 | ||
690 | static void pn533_wq_cmd(struct work_struct *work) | 682 | static void pn533_build_cmd_frame(struct pn533 *dev, u8 cmd_code, |
683 | struct sk_buff *skb) | ||
691 | { | 684 | { |
692 | struct pn533 *dev = container_of(work, struct pn533, cmd_work); | 685 | /* payload is already there, just update datalen */ |
693 | struct pn533_cmd *cmd; | 686 | int payload_len = skb->len; |
687 | struct pn533_frame_ops *ops = dev->ops; | ||
694 | 688 | ||
695 | mutex_lock(&dev->cmd_lock); | ||
696 | 689 | ||
697 | if (list_empty(&dev->cmd_queue)) { | 690 | skb_push(skb, ops->tx_header_len); |
698 | dev->cmd_pending = 0; | 691 | skb_put(skb, ops->tx_tail_len); |
699 | mutex_unlock(&dev->cmd_lock); | ||
700 | return; | ||
701 | } | ||
702 | 692 | ||
703 | cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue); | 693 | ops->tx_frame_init(skb->data, cmd_code); |
694 | ops->tx_update_payload_len(skb->data, payload_len); | ||
695 | ops->tx_frame_finish(skb->data); | ||
696 | } | ||
704 | 697 | ||
705 | list_del(&cmd->queue); | 698 | struct pn533_send_async_complete_arg { |
699 | pn533_send_async_complete_t complete_cb; | ||
700 | void *complete_cb_context; | ||
701 | struct sk_buff *resp; | ||
702 | struct sk_buff *req; | ||
703 | }; | ||
706 | 704 | ||
707 | mutex_unlock(&dev->cmd_lock); | 705 | static int pn533_send_async_complete(struct pn533 *dev, void *_arg, int status) |
706 | { | ||
707 | struct pn533_send_async_complete_arg *arg = _arg; | ||
708 | 708 | ||
709 | __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame, | 709 | struct sk_buff *req = arg->req; |
710 | cmd->in_frame_len, cmd->cmd_complete, | 710 | struct sk_buff *resp = arg->resp; |
711 | cmd->arg, cmd->flags); | ||
712 | 711 | ||
713 | kfree(cmd); | 712 | int rc; |
713 | |||
714 | dev_kfree_skb(req); | ||
715 | |||
716 | if (status < 0) { | ||
717 | arg->complete_cb(dev, arg->complete_cb_context, | ||
718 | ERR_PTR(status)); | ||
719 | dev_kfree_skb(resp); | ||
720 | kfree(arg); | ||
721 | return status; | ||
722 | } | ||
723 | |||
724 | skb_put(resp, dev->ops->rx_frame_size(resp->data)); | ||
725 | skb_pull(resp, dev->ops->rx_header_len); | ||
726 | skb_trim(resp, resp->len - dev->ops->rx_tail_len); | ||
727 | |||
728 | rc = arg->complete_cb(dev, arg->complete_cb_context, resp); | ||
729 | |||
730 | kfree(arg); | ||
731 | return rc; | ||
714 | } | 732 | } |
715 | 733 | ||
716 | static int pn533_send_cmd_frame_async(struct pn533 *dev, | 734 | static int __pn533_send_async(struct pn533 *dev, u8 cmd_code, |
717 | struct pn533_frame *out_frame, | 735 | struct sk_buff *req, struct sk_buff *resp, |
718 | struct pn533_frame *in_frame, | 736 | int resp_len, |
719 | int in_frame_len, | 737 | pn533_send_async_complete_t complete_cb, |
720 | pn533_cmd_complete_t cmd_complete, | 738 | void *complete_cb_context) |
721 | void *arg, gfp_t flags) | ||
722 | { | 739 | { |
723 | struct pn533_cmd *cmd; | 740 | struct pn533_cmd *cmd; |
741 | struct pn533_send_async_complete_arg *arg; | ||
724 | int rc = 0; | 742 | int rc = 0; |
725 | 743 | ||
726 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 744 | nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x", cmd_code); |
745 | |||
746 | arg = kzalloc(sizeof(*arg), GFP_KERNEL); | ||
747 | if (!arg) | ||
748 | return -ENOMEM; | ||
749 | |||
750 | arg->complete_cb = complete_cb; | ||
751 | arg->complete_cb_context = complete_cb_context; | ||
752 | arg->resp = resp; | ||
753 | arg->req = req; | ||
754 | |||
755 | pn533_build_cmd_frame(dev, cmd_code, req); | ||
727 | 756 | ||
728 | mutex_lock(&dev->cmd_lock); | 757 | mutex_lock(&dev->cmd_lock); |
729 | 758 | ||
730 | if (!dev->cmd_pending) { | 759 | if (!dev->cmd_pending) { |
731 | rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, | 760 | rc = __pn533_send_frame_async(dev, req, resp, resp_len, |
732 | in_frame_len, cmd_complete, | 761 | pn533_send_async_complete, arg); |
733 | arg, flags); | 762 | if (rc) |
734 | if (!rc) | 763 | goto error; |
735 | dev->cmd_pending = 1; | ||
736 | 764 | ||
765 | dev->cmd_pending = 1; | ||
737 | goto unlock; | 766 | goto unlock; |
738 | } | 767 | } |
739 | 768 | ||
740 | nfc_dev_dbg(&dev->interface->dev, "%s Queueing command", __func__); | 769 | nfc_dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x", __func__, |
770 | cmd_code); | ||
741 | 771 | ||
742 | cmd = kzalloc(sizeof(struct pn533_cmd), flags); | 772 | cmd = kzalloc(sizeof(struct pn533_cmd), GFP_KERNEL); |
743 | if (!cmd) { | 773 | if (!cmd) { |
744 | rc = -ENOMEM; | 774 | rc = -ENOMEM; |
745 | goto unlock; | 775 | goto error; |
746 | } | 776 | } |
747 | 777 | ||
748 | INIT_LIST_HEAD(&cmd->queue); | 778 | INIT_LIST_HEAD(&cmd->queue); |
749 | cmd->out_frame = out_frame; | 779 | cmd->cmd_code = cmd_code; |
750 | cmd->in_frame = in_frame; | 780 | cmd->req = req; |
751 | cmd->in_frame_len = in_frame_len; | 781 | cmd->resp = resp; |
752 | cmd->cmd_complete = cmd_complete; | 782 | cmd->resp_len = resp_len; |
753 | cmd->arg = arg; | 783 | cmd->arg = arg; |
754 | cmd->flags = flags; | ||
755 | 784 | ||
756 | list_add_tail(&cmd->queue, &dev->cmd_queue); | 785 | list_add_tail(&cmd->queue, &dev->cmd_queue); |
757 | 786 | ||
787 | goto unlock; | ||
788 | |||
789 | error: | ||
790 | kfree(arg); | ||
758 | unlock: | 791 | unlock: |
759 | mutex_unlock(&dev->cmd_lock); | 792 | mutex_unlock(&dev->cmd_lock); |
793 | return rc; | ||
794 | } | ||
795 | |||
796 | static int pn533_send_data_async(struct pn533 *dev, u8 cmd_code, | ||
797 | struct sk_buff *req, | ||
798 | pn533_send_async_complete_t complete_cb, | ||
799 | void *complete_cb_context) | ||
800 | { | ||
801 | struct sk_buff *resp; | ||
802 | int rc; | ||
803 | int resp_len = dev->ops->rx_header_len + | ||
804 | dev->ops->max_payload_len + | ||
805 | dev->ops->rx_tail_len; | ||
806 | |||
807 | resp = nfc_alloc_recv_skb(resp_len, GFP_KERNEL); | ||
808 | if (!resp) | ||
809 | return -ENOMEM; | ||
810 | |||
811 | rc = __pn533_send_async(dev, cmd_code, req, resp, resp_len, complete_cb, | ||
812 | complete_cb_context); | ||
813 | if (rc) | ||
814 | dev_kfree_skb(resp); | ||
760 | 815 | ||
761 | return rc; | 816 | return rc; |
762 | } | 817 | } |
763 | 818 | ||
764 | struct pn533_sync_cmd_response { | 819 | static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code, |
820 | struct sk_buff *req, | ||
821 | pn533_send_async_complete_t complete_cb, | ||
822 | void *complete_cb_context) | ||
823 | { | ||
824 | struct sk_buff *resp; | ||
765 | int rc; | 825 | int rc; |
766 | struct completion done; | 826 | int resp_len = dev->ops->rx_header_len + |
767 | }; | 827 | dev->ops->max_payload_len + |
828 | dev->ops->rx_tail_len; | ||
829 | |||
830 | resp = alloc_skb(resp_len, GFP_KERNEL); | ||
831 | if (!resp) | ||
832 | return -ENOMEM; | ||
833 | |||
834 | rc = __pn533_send_async(dev, cmd_code, req, resp, resp_len, complete_cb, | ||
835 | complete_cb_context); | ||
836 | if (rc) | ||
837 | dev_kfree_skb(resp); | ||
768 | 838 | ||
769 | static int pn533_sync_cmd_complete(struct pn533 *dev, void *_arg, | 839 | return rc; |
770 | u8 *params, int params_len) | 840 | } |
841 | |||
842 | /* | ||
843 | * pn533_send_cmd_direct_async | ||
844 | * | ||
845 | * The function sends a piority cmd directly to the chip omiting the cmd | ||
846 | * queue. It's intended to be used by chaining mechanism of received responses | ||
847 | * where the host has to request every single chunk of data before scheduling | ||
848 | * next cmd from the queue. | ||
849 | */ | ||
850 | static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code, | ||
851 | struct sk_buff *req, | ||
852 | pn533_send_async_complete_t complete_cb, | ||
853 | void *complete_cb_context) | ||
771 | { | 854 | { |
772 | struct pn533_sync_cmd_response *arg = _arg; | 855 | struct pn533_send_async_complete_arg *arg; |
856 | struct sk_buff *resp; | ||
857 | int rc; | ||
858 | int resp_len = dev->ops->rx_header_len + | ||
859 | dev->ops->max_payload_len + | ||
860 | dev->ops->rx_tail_len; | ||
773 | 861 | ||
774 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 862 | resp = alloc_skb(resp_len, GFP_KERNEL); |
863 | if (!resp) | ||
864 | return -ENOMEM; | ||
865 | |||
866 | arg = kzalloc(sizeof(*arg), GFP_KERNEL); | ||
867 | if (!arg) { | ||
868 | dev_kfree_skb(resp); | ||
869 | return -ENOMEM; | ||
870 | } | ||
775 | 871 | ||
776 | arg->rc = 0; | 872 | arg->complete_cb = complete_cb; |
873 | arg->complete_cb_context = complete_cb_context; | ||
874 | arg->resp = resp; | ||
875 | arg->req = req; | ||
777 | 876 | ||
778 | if (params_len < 0) /* error */ | 877 | pn533_build_cmd_frame(dev, cmd_code, req); |
779 | arg->rc = params_len; | ||
780 | 878 | ||
879 | rc = __pn533_send_frame_async(dev, req, resp, resp_len, | ||
880 | pn533_send_async_complete, arg); | ||
881 | if (rc < 0) { | ||
882 | dev_kfree_skb(resp); | ||
883 | kfree(arg); | ||
884 | } | ||
885 | |||
886 | return rc; | ||
887 | } | ||
888 | |||
889 | static void pn533_wq_cmd(struct work_struct *work) | ||
890 | { | ||
891 | struct pn533 *dev = container_of(work, struct pn533, cmd_work); | ||
892 | struct pn533_cmd *cmd; | ||
893 | |||
894 | mutex_lock(&dev->cmd_lock); | ||
895 | |||
896 | if (list_empty(&dev->cmd_queue)) { | ||
897 | dev->cmd_pending = 0; | ||
898 | mutex_unlock(&dev->cmd_lock); | ||
899 | return; | ||
900 | } | ||
901 | |||
902 | cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue); | ||
903 | |||
904 | list_del(&cmd->queue); | ||
905 | |||
906 | mutex_unlock(&dev->cmd_lock); | ||
907 | |||
908 | __pn533_send_frame_async(dev, cmd->req, cmd->resp, cmd->resp_len, | ||
909 | pn533_send_async_complete, cmd->arg); | ||
910 | |||
911 | kfree(cmd); | ||
912 | } | ||
913 | |||
914 | struct pn533_sync_cmd_response { | ||
915 | struct sk_buff *resp; | ||
916 | struct completion done; | ||
917 | }; | ||
918 | |||
919 | static int pn533_send_sync_complete(struct pn533 *dev, void *_arg, | ||
920 | struct sk_buff *resp) | ||
921 | { | ||
922 | struct pn533_sync_cmd_response *arg = _arg; | ||
923 | |||
924 | arg->resp = resp; | ||
781 | complete(&arg->done); | 925 | complete(&arg->done); |
782 | 926 | ||
783 | return 0; | 927 | return 0; |
784 | } | 928 | } |
785 | 929 | ||
786 | static int pn533_send_cmd_frame_sync(struct pn533 *dev, | 930 | /* pn533_send_cmd_sync |
787 | struct pn533_frame *out_frame, | 931 | * |
788 | struct pn533_frame *in_frame, | 932 | * Please note the req parameter is freed inside the function to |
789 | int in_frame_len) | 933 | * limit a number of return value interpretations by the caller. |
934 | * | ||
935 | * 1. negative in case of error during TX path -> req should be freed | ||
936 | * | ||
937 | * 2. negative in case of error during RX path -> req should not be freed | ||
938 | * as it's been already freed at the begining of RX path by | ||
939 | * async_complete_cb. | ||
940 | * | ||
941 | * 3. valid pointer in case of succesfult RX path | ||
942 | * | ||
943 | * A caller has to check a return value with IS_ERR macro. If the test pass, | ||
944 | * the returned pointer is valid. | ||
945 | * | ||
946 | * */ | ||
947 | static struct sk_buff *pn533_send_cmd_sync(struct pn533 *dev, u8 cmd_code, | ||
948 | struct sk_buff *req) | ||
790 | { | 949 | { |
791 | int rc; | 950 | int rc; |
792 | struct pn533_sync_cmd_response arg; | 951 | struct pn533_sync_cmd_response arg; |
793 | 952 | ||
794 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
795 | |||
796 | init_completion(&arg.done); | 953 | init_completion(&arg.done); |
797 | 954 | ||
798 | rc = pn533_send_cmd_frame_async(dev, out_frame, in_frame, in_frame_len, | 955 | rc = pn533_send_cmd_async(dev, cmd_code, req, |
799 | pn533_sync_cmd_complete, &arg, GFP_KERNEL); | 956 | pn533_send_sync_complete, &arg); |
800 | if (rc) | 957 | if (rc) { |
801 | return rc; | 958 | dev_kfree_skb(req); |
959 | return ERR_PTR(rc); | ||
960 | } | ||
802 | 961 | ||
803 | wait_for_completion(&arg.done); | 962 | wait_for_completion(&arg.done); |
804 | 963 | ||
805 | return arg.rc; | 964 | return arg.resp; |
806 | } | 965 | } |
807 | 966 | ||
808 | static void pn533_send_complete(struct urb *urb) | 967 | static void pn533_send_complete(struct urb *urb) |
809 | { | 968 | { |
810 | struct pn533 *dev = urb->context; | 969 | struct pn533 *dev = urb->context; |
811 | 970 | ||
812 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
813 | |||
814 | switch (urb->status) { | 971 | switch (urb->status) { |
815 | case 0: | 972 | case 0: |
816 | /* success */ | 973 | break; /* success */ |
817 | break; | ||
818 | case -ECONNRESET: | 974 | case -ECONNRESET: |
819 | case -ENOENT: | 975 | case -ENOENT: |
820 | case -ESHUTDOWN: | 976 | nfc_dev_dbg(&dev->interface->dev, |
821 | nfc_dev_dbg(&dev->interface->dev, "Urb shutting down with" | 977 | "The urb has been stopped (status %d)", |
822 | " status: %d", urb->status); | 978 | urb->status); |
823 | break; | 979 | break; |
980 | case -ESHUTDOWN: | ||
824 | default: | 981 | default: |
825 | nfc_dev_dbg(&dev->interface->dev, "Nonzero urb status received:" | 982 | nfc_dev_err(&dev->interface->dev, |
826 | " %d", urb->status); | 983 | "Urb failure (status %d)", urb->status); |
827 | } | 984 | } |
828 | } | 985 | } |
829 | 986 | ||
987 | static struct sk_buff *pn533_alloc_skb(struct pn533 *dev, unsigned int size) | ||
988 | { | ||
989 | struct sk_buff *skb; | ||
990 | |||
991 | skb = alloc_skb(dev->ops->tx_header_len + | ||
992 | size + | ||
993 | dev->ops->tx_tail_len, GFP_KERNEL); | ||
994 | |||
995 | if (skb) | ||
996 | skb_reserve(skb, dev->ops->tx_header_len); | ||
997 | |||
998 | return skb; | ||
999 | } | ||
1000 | |||
830 | struct pn533_target_type_a { | 1001 | struct pn533_target_type_a { |
831 | __be16 sens_res; | 1002 | __be16 sens_res; |
832 | u8 sel_res; | 1003 | u8 sel_res; |
@@ -867,9 +1038,9 @@ static bool pn533_target_type_a_is_valid(struct pn533_target_type_a *type_a, | |||
867 | platconf = PN533_TYPE_A_SENS_RES_PLATCONF(type_a->sens_res); | 1038 | platconf = PN533_TYPE_A_SENS_RES_PLATCONF(type_a->sens_res); |
868 | 1039 | ||
869 | if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL && | 1040 | if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL && |
870 | platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) || | 1041 | platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) || |
871 | (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL && | 1042 | (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL && |
872 | platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL)) | 1043 | platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL)) |
873 | return false; | 1044 | return false; |
874 | 1045 | ||
875 | /* Requirements 4.8.2.1, 4.8.2.3, 4.8.2.5 and 4.8.2.7 from NFC Forum */ | 1046 | /* Requirements 4.8.2.1, 4.8.2.3, 4.8.2.5 and 4.8.2.7 from NFC Forum */ |
@@ -884,7 +1055,7 @@ static int pn533_target_found_type_a(struct nfc_target *nfc_tgt, u8 *tgt_data, | |||
884 | { | 1055 | { |
885 | struct pn533_target_type_a *tgt_type_a; | 1056 | struct pn533_target_type_a *tgt_type_a; |
886 | 1057 | ||
887 | tgt_type_a = (struct pn533_target_type_a *) tgt_data; | 1058 | tgt_type_a = (struct pn533_target_type_a *)tgt_data; |
888 | 1059 | ||
889 | if (!pn533_target_type_a_is_valid(tgt_type_a, tgt_data_len)) | 1060 | if (!pn533_target_type_a_is_valid(tgt_type_a, tgt_data_len)) |
890 | return -EPROTO; | 1061 | return -EPROTO; |
@@ -942,14 +1113,13 @@ static int pn533_target_found_felica(struct nfc_target *nfc_tgt, u8 *tgt_data, | |||
942 | { | 1113 | { |
943 | struct pn533_target_felica *tgt_felica; | 1114 | struct pn533_target_felica *tgt_felica; |
944 | 1115 | ||
945 | tgt_felica = (struct pn533_target_felica *) tgt_data; | 1116 | tgt_felica = (struct pn533_target_felica *)tgt_data; |
946 | 1117 | ||
947 | if (!pn533_target_felica_is_valid(tgt_felica, tgt_data_len)) | 1118 | if (!pn533_target_felica_is_valid(tgt_felica, tgt_data_len)) |
948 | return -EPROTO; | 1119 | return -EPROTO; |
949 | 1120 | ||
950 | if (tgt_felica->nfcid2[0] == PN533_FELICA_SENSF_NFCID2_DEP_B1 && | 1121 | if ((tgt_felica->nfcid2[0] == PN533_FELICA_SENSF_NFCID2_DEP_B1) && |
951 | tgt_felica->nfcid2[1] == | 1122 | (tgt_felica->nfcid2[1] == PN533_FELICA_SENSF_NFCID2_DEP_B2)) |
952 | PN533_FELICA_SENSF_NFCID2_DEP_B2) | ||
953 | nfc_tgt->supported_protocols = NFC_PROTO_NFC_DEP_MASK; | 1123 | nfc_tgt->supported_protocols = NFC_PROTO_NFC_DEP_MASK; |
954 | else | 1124 | else |
955 | nfc_tgt->supported_protocols = NFC_PROTO_FELICA_MASK; | 1125 | nfc_tgt->supported_protocols = NFC_PROTO_FELICA_MASK; |
@@ -979,9 +1149,9 @@ static bool pn533_target_jewel_is_valid(struct pn533_target_jewel *jewel, | |||
979 | platconf = PN533_TYPE_A_SENS_RES_PLATCONF(jewel->sens_res); | 1149 | platconf = PN533_TYPE_A_SENS_RES_PLATCONF(jewel->sens_res); |
980 | 1150 | ||
981 | if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL && | 1151 | if ((ssd == PN533_TYPE_A_SENS_RES_SSD_JEWEL && |
982 | platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) || | 1152 | platconf != PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL) || |
983 | (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL && | 1153 | (ssd != PN533_TYPE_A_SENS_RES_SSD_JEWEL && |
984 | platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL)) | 1154 | platconf == PN533_TYPE_A_SENS_RES_PLATCONF_JEWEL)) |
985 | return false; | 1155 | return false; |
986 | 1156 | ||
987 | return true; | 1157 | return true; |
@@ -992,7 +1162,7 @@ static int pn533_target_found_jewel(struct nfc_target *nfc_tgt, u8 *tgt_data, | |||
992 | { | 1162 | { |
993 | struct pn533_target_jewel *tgt_jewel; | 1163 | struct pn533_target_jewel *tgt_jewel; |
994 | 1164 | ||
995 | tgt_jewel = (struct pn533_target_jewel *) tgt_data; | 1165 | tgt_jewel = (struct pn533_target_jewel *)tgt_data; |
996 | 1166 | ||
997 | if (!pn533_target_jewel_is_valid(tgt_jewel, tgt_data_len)) | 1167 | if (!pn533_target_jewel_is_valid(tgt_jewel, tgt_data_len)) |
998 | return -EPROTO; | 1168 | return -EPROTO; |
@@ -1051,7 +1221,7 @@ static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data, | |||
1051 | { | 1221 | { |
1052 | struct pn533_target_type_b *tgt_type_b; | 1222 | struct pn533_target_type_b *tgt_type_b; |
1053 | 1223 | ||
1054 | tgt_type_b = (struct pn533_target_type_b *) tgt_data; | 1224 | tgt_type_b = (struct pn533_target_type_b *)tgt_data; |
1055 | 1225 | ||
1056 | if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len)) | 1226 | if (!pn533_target_type_b_is_valid(tgt_type_b, tgt_data_len)) |
1057 | return -EPROTO; | 1227 | return -EPROTO; |
@@ -1061,50 +1231,37 @@ static int pn533_target_found_type_b(struct nfc_target *nfc_tgt, u8 *tgt_data, | |||
1061 | return 0; | 1231 | return 0; |
1062 | } | 1232 | } |
1063 | 1233 | ||
1064 | struct pn533_poll_response { | 1234 | static int pn533_target_found(struct pn533 *dev, u8 tg, u8 *tgdata, |
1065 | u8 nbtg; | 1235 | int tgdata_len) |
1066 | u8 tg; | ||
1067 | u8 target_data[]; | ||
1068 | } __packed; | ||
1069 | |||
1070 | static int pn533_target_found(struct pn533 *dev, | ||
1071 | struct pn533_poll_response *resp, int resp_len) | ||
1072 | { | 1236 | { |
1073 | int target_data_len; | ||
1074 | struct nfc_target nfc_tgt; | 1237 | struct nfc_target nfc_tgt; |
1075 | int rc; | 1238 | int rc; |
1076 | 1239 | ||
1077 | nfc_dev_dbg(&dev->interface->dev, "%s - modulation=%d", __func__, | 1240 | nfc_dev_dbg(&dev->interface->dev, "%s - modulation=%d", __func__, |
1078 | dev->poll_mod_curr); | 1241 | dev->poll_mod_curr); |
1079 | 1242 | ||
1080 | if (resp->tg != 1) | 1243 | if (tg != 1) |
1081 | return -EPROTO; | 1244 | return -EPROTO; |
1082 | 1245 | ||
1083 | memset(&nfc_tgt, 0, sizeof(struct nfc_target)); | 1246 | memset(&nfc_tgt, 0, sizeof(struct nfc_target)); |
1084 | 1247 | ||
1085 | target_data_len = resp_len - sizeof(struct pn533_poll_response); | ||
1086 | |||
1087 | switch (dev->poll_mod_curr) { | 1248 | switch (dev->poll_mod_curr) { |
1088 | case PN533_POLL_MOD_106KBPS_A: | 1249 | case PN533_POLL_MOD_106KBPS_A: |
1089 | rc = pn533_target_found_type_a(&nfc_tgt, resp->target_data, | 1250 | rc = pn533_target_found_type_a(&nfc_tgt, tgdata, tgdata_len); |
1090 | target_data_len); | ||
1091 | break; | 1251 | break; |
1092 | case PN533_POLL_MOD_212KBPS_FELICA: | 1252 | case PN533_POLL_MOD_212KBPS_FELICA: |
1093 | case PN533_POLL_MOD_424KBPS_FELICA: | 1253 | case PN533_POLL_MOD_424KBPS_FELICA: |
1094 | rc = pn533_target_found_felica(&nfc_tgt, resp->target_data, | 1254 | rc = pn533_target_found_felica(&nfc_tgt, tgdata, tgdata_len); |
1095 | target_data_len); | ||
1096 | break; | 1255 | break; |
1097 | case PN533_POLL_MOD_106KBPS_JEWEL: | 1256 | case PN533_POLL_MOD_106KBPS_JEWEL: |
1098 | rc = pn533_target_found_jewel(&nfc_tgt, resp->target_data, | 1257 | rc = pn533_target_found_jewel(&nfc_tgt, tgdata, tgdata_len); |
1099 | target_data_len); | ||
1100 | break; | 1258 | break; |
1101 | case PN533_POLL_MOD_847KBPS_B: | 1259 | case PN533_POLL_MOD_847KBPS_B: |
1102 | rc = pn533_target_found_type_b(&nfc_tgt, resp->target_data, | 1260 | rc = pn533_target_found_type_b(&nfc_tgt, tgdata, tgdata_len); |
1103 | target_data_len); | ||
1104 | break; | 1261 | break; |
1105 | default: | 1262 | default: |
1106 | nfc_dev_err(&dev->interface->dev, "Unknown current poll" | 1263 | nfc_dev_err(&dev->interface->dev, |
1107 | " modulation"); | 1264 | "Unknown current poll modulation"); |
1108 | return -EPROTO; | 1265 | return -EPROTO; |
1109 | } | 1266 | } |
1110 | 1267 | ||
@@ -1112,13 +1269,14 @@ static int pn533_target_found(struct pn533 *dev, | |||
1112 | return rc; | 1269 | return rc; |
1113 | 1270 | ||
1114 | if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { | 1271 | if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { |
1115 | nfc_dev_dbg(&dev->interface->dev, "The target found does not" | 1272 | nfc_dev_dbg(&dev->interface->dev, |
1116 | " have the desired protocol"); | 1273 | "The Tg found doesn't have the desired protocol"); |
1117 | return -EAGAIN; | 1274 | return -EAGAIN; |
1118 | } | 1275 | } |
1119 | 1276 | ||
1120 | nfc_dev_dbg(&dev->interface->dev, "Target found - supported protocols: " | 1277 | nfc_dev_dbg(&dev->interface->dev, |
1121 | "0x%x", nfc_tgt.supported_protocols); | 1278 | "Target found - supported protocols: 0x%x", |
1279 | nfc_tgt.supported_protocols); | ||
1122 | 1280 | ||
1123 | dev->tgt_available_prots = nfc_tgt.supported_protocols; | 1281 | dev->tgt_available_prots = nfc_tgt.supported_protocols; |
1124 | 1282 | ||
@@ -1140,7 +1298,7 @@ static void pn533_poll_reset_mod_list(struct pn533 *dev) | |||
1140 | static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index) | 1298 | static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index) |
1141 | { | 1299 | { |
1142 | dev->poll_mod_active[dev->poll_mod_count] = | 1300 | dev->poll_mod_active[dev->poll_mod_count] = |
1143 | (struct pn533_poll_modulations *) &poll_mod[mod_index]; | 1301 | (struct pn533_poll_modulations *)&poll_mod[mod_index]; |
1144 | dev->poll_mod_count++; | 1302 | dev->poll_mod_count++; |
1145 | } | 1303 | } |
1146 | 1304 | ||
@@ -1149,13 +1307,13 @@ static void pn533_poll_create_mod_list(struct pn533 *dev, | |||
1149 | { | 1307 | { |
1150 | pn533_poll_reset_mod_list(dev); | 1308 | pn533_poll_reset_mod_list(dev); |
1151 | 1309 | ||
1152 | if (im_protocols & NFC_PROTO_MIFARE_MASK | 1310 | if ((im_protocols & NFC_PROTO_MIFARE_MASK) || |
1153 | || im_protocols & NFC_PROTO_ISO14443_MASK | 1311 | (im_protocols & NFC_PROTO_ISO14443_MASK) || |
1154 | || im_protocols & NFC_PROTO_NFC_DEP_MASK) | 1312 | (im_protocols & NFC_PROTO_NFC_DEP_MASK)) |
1155 | pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A); | 1313 | pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A); |
1156 | 1314 | ||
1157 | if (im_protocols & NFC_PROTO_FELICA_MASK | 1315 | if (im_protocols & NFC_PROTO_FELICA_MASK || |
1158 | || im_protocols & NFC_PROTO_NFC_DEP_MASK) { | 1316 | im_protocols & NFC_PROTO_NFC_DEP_MASK) { |
1159 | pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA); | 1317 | pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA); |
1160 | pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA); | 1318 | pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA); |
1161 | } | 1319 | } |
@@ -1170,16 +1328,20 @@ static void pn533_poll_create_mod_list(struct pn533 *dev, | |||
1170 | pn533_poll_add_mod(dev, PN533_LISTEN_MOD); | 1328 | pn533_poll_add_mod(dev, PN533_LISTEN_MOD); |
1171 | } | 1329 | } |
1172 | 1330 | ||
1173 | static int pn533_start_poll_complete(struct pn533 *dev, u8 *params, int params_len) | 1331 | static int pn533_start_poll_complete(struct pn533 *dev, struct sk_buff *resp) |
1174 | { | 1332 | { |
1175 | struct pn533_poll_response *resp; | 1333 | u8 nbtg, tg, *tgdata; |
1176 | int rc; | 1334 | int rc, tgdata_len; |
1177 | 1335 | ||
1178 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1336 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1179 | 1337 | ||
1180 | resp = (struct pn533_poll_response *) params; | 1338 | nbtg = resp->data[0]; |
1181 | if (resp->nbtg) { | 1339 | tg = resp->data[1]; |
1182 | rc = pn533_target_found(dev, resp, params_len); | 1340 | tgdata = &resp->data[2]; |
1341 | tgdata_len = resp->len - 2; /* nbtg + tg */ | ||
1342 | |||
1343 | if (nbtg) { | ||
1344 | rc = pn533_target_found(dev, tg, tgdata, tgdata_len); | ||
1183 | 1345 | ||
1184 | /* We must stop the poll after a valid target found */ | 1346 | /* We must stop the poll after a valid target found */ |
1185 | if (rc == 0) { | 1347 | if (rc == 0) { |
@@ -1191,158 +1353,134 @@ static int pn533_start_poll_complete(struct pn533 *dev, u8 *params, int params_l | |||
1191 | return -EAGAIN; | 1353 | return -EAGAIN; |
1192 | } | 1354 | } |
1193 | 1355 | ||
1194 | static int pn533_init_target_frame(struct pn533_frame *frame, | 1356 | static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev) |
1195 | u8 *gb, size_t gb_len) | ||
1196 | { | 1357 | { |
1197 | struct pn533_cmd_init_target *cmd; | 1358 | struct sk_buff *skb; |
1198 | size_t cmd_len; | 1359 | u8 *felica, *nfcid3, *gb; |
1360 | |||
1361 | u8 *gbytes = dev->gb; | ||
1362 | size_t gbytes_len = dev->gb_len; | ||
1363 | |||
1199 | u8 felica_params[18] = {0x1, 0xfe, /* DEP */ | 1364 | u8 felica_params[18] = {0x1, 0xfe, /* DEP */ |
1200 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* random */ | 1365 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* random */ |
1201 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | 1366 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
1202 | 0xff, 0xff}; /* System code */ | 1367 | 0xff, 0xff}; /* System code */ |
1368 | |||
1203 | u8 mifare_params[6] = {0x1, 0x1, /* SENS_RES */ | 1369 | u8 mifare_params[6] = {0x1, 0x1, /* SENS_RES */ |
1204 | 0x0, 0x0, 0x0, | 1370 | 0x0, 0x0, 0x0, |
1205 | 0x40}; /* SEL_RES for DEP */ | 1371 | 0x40}; /* SEL_RES for DEP */ |
1206 | 1372 | ||
1207 | cmd_len = sizeof(struct pn533_cmd_init_target) + gb_len + 1; | 1373 | unsigned int skb_len = 36 + /* mode (1), mifare (6), |
1208 | cmd = kzalloc(cmd_len, GFP_KERNEL); | 1374 | felica (18), nfcid3 (10), gb_len (1) */ |
1209 | if (cmd == NULL) | 1375 | gbytes_len + |
1210 | return -ENOMEM; | 1376 | 1; /* len Tk*/ |
1211 | 1377 | ||
1212 | pn533_tx_frame_init(frame, PN533_CMD_TG_INIT_AS_TARGET); | 1378 | skb = pn533_alloc_skb(dev, skb_len); |
1379 | if (!skb) | ||
1380 | return NULL; | ||
1213 | 1381 | ||
1214 | /* DEP support only */ | 1382 | /* DEP support only */ |
1215 | cmd->mode |= PN533_INIT_TARGET_DEP; | 1383 | *skb_put(skb, 1) |= PN533_INIT_TARGET_DEP; |
1384 | |||
1385 | /* MIFARE params */ | ||
1386 | memcpy(skb_put(skb, 6), mifare_params, 6); | ||
1216 | 1387 | ||
1217 | /* Felica params */ | 1388 | /* Felica params */ |
1218 | memcpy(cmd->felica, felica_params, 18); | 1389 | felica = skb_put(skb, 18); |
1219 | get_random_bytes(cmd->felica + 2, 6); | 1390 | memcpy(felica, felica_params, 18); |
1391 | get_random_bytes(felica + 2, 6); | ||
1220 | 1392 | ||
1221 | /* NFCID3 */ | 1393 | /* NFCID3 */ |
1222 | memset(cmd->nfcid3, 0, 10); | 1394 | nfcid3 = skb_put(skb, 10); |
1223 | memcpy(cmd->nfcid3, cmd->felica, 8); | 1395 | memset(nfcid3, 0, 10); |
1224 | 1396 | memcpy(nfcid3, felica, 8); | |
1225 | /* MIFARE params */ | ||
1226 | memcpy(cmd->mifare, mifare_params, 6); | ||
1227 | 1397 | ||
1228 | /* General bytes */ | 1398 | /* General bytes */ |
1229 | cmd->gb_len = gb_len; | 1399 | *skb_put(skb, 1) = gbytes_len; |
1230 | memcpy(cmd->gb, gb, gb_len); | ||
1231 | |||
1232 | /* Len Tk */ | ||
1233 | cmd->gb[gb_len] = 0; | ||
1234 | |||
1235 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), cmd, cmd_len); | ||
1236 | 1400 | ||
1237 | frame->datalen += cmd_len; | 1401 | gb = skb_put(skb, gbytes_len); |
1402 | memcpy(gb, gbytes, gbytes_len); | ||
1238 | 1403 | ||
1239 | pn533_tx_frame_finish(frame); | 1404 | /* Len Tk */ |
1240 | 1405 | *skb_put(skb, 1) = 0; | |
1241 | kfree(cmd); | ||
1242 | 1406 | ||
1243 | return 0; | 1407 | return skb; |
1244 | } | 1408 | } |
1245 | 1409 | ||
1246 | #define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3) | 1410 | #define PN533_CMD_DATAEXCH_HEAD_LEN 1 |
1247 | #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 | 1411 | #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 |
1248 | static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, | 1412 | static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, |
1249 | u8 *params, int params_len) | 1413 | struct sk_buff *resp) |
1250 | { | 1414 | { |
1251 | struct sk_buff *skb_resp = arg; | 1415 | u8 status; |
1252 | struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data; | ||
1253 | 1416 | ||
1254 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1417 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1255 | 1418 | ||
1256 | if (params_len < 0) { | 1419 | if (IS_ERR(resp)) |
1257 | nfc_dev_err(&dev->interface->dev, | 1420 | return PTR_ERR(resp); |
1258 | "Error %d when starting as a target", | ||
1259 | params_len); | ||
1260 | 1421 | ||
1261 | return params_len; | 1422 | status = resp->data[0]; |
1262 | } | 1423 | skb_pull(resp, sizeof(status)); |
1263 | 1424 | ||
1264 | if (params_len > 0 && params[0] != 0) { | 1425 | if (status != 0) { |
1265 | nfc_tm_deactivated(dev->nfc_dev); | 1426 | nfc_tm_deactivated(dev->nfc_dev); |
1266 | |||
1267 | dev->tgt_mode = 0; | 1427 | dev->tgt_mode = 0; |
1268 | 1428 | dev_kfree_skb(resp); | |
1269 | kfree_skb(skb_resp); | ||
1270 | return 0; | 1429 | return 0; |
1271 | } | 1430 | } |
1272 | 1431 | ||
1273 | skb_put(skb_resp, PN533_FRAME_SIZE(in_frame)); | 1432 | return nfc_tm_data_received(dev->nfc_dev, resp); |
1274 | skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN); | ||
1275 | skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_SIZE); | ||
1276 | |||
1277 | return nfc_tm_data_received(dev->nfc_dev, skb_resp); | ||
1278 | } | 1433 | } |
1279 | 1434 | ||
1280 | static void pn533_wq_tg_get_data(struct work_struct *work) | 1435 | static void pn533_wq_tg_get_data(struct work_struct *work) |
1281 | { | 1436 | { |
1282 | struct pn533 *dev = container_of(work, struct pn533, tg_work); | 1437 | struct pn533 *dev = container_of(work, struct pn533, tg_work); |
1283 | struct pn533_frame *in_frame; | ||
1284 | struct sk_buff *skb_resp; | ||
1285 | size_t skb_resp_len; | ||
1286 | 1438 | ||
1287 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1439 | struct sk_buff *skb; |
1440 | int rc; | ||
1288 | 1441 | ||
1289 | skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN + | 1442 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1290 | PN533_CMD_DATAEXCH_DATA_MAXLEN + | ||
1291 | PN533_FRAME_TAIL_SIZE; | ||
1292 | 1443 | ||
1293 | skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL); | 1444 | skb = pn533_alloc_skb(dev, 0); |
1294 | if (!skb_resp) | 1445 | if (!skb) |
1295 | return; | 1446 | return; |
1296 | 1447 | ||
1297 | in_frame = (struct pn533_frame *)skb_resp->data; | 1448 | rc = pn533_send_data_async(dev, PN533_CMD_TG_GET_DATA, skb, |
1449 | pn533_tm_get_data_complete, NULL); | ||
1298 | 1450 | ||
1299 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_TG_GET_DATA); | 1451 | if (rc < 0) |
1300 | pn533_tx_frame_finish(dev->out_frame); | 1452 | dev_kfree_skb(skb); |
1301 | |||
1302 | pn533_send_cmd_frame_async(dev, dev->out_frame, in_frame, | ||
1303 | skb_resp_len, | ||
1304 | pn533_tm_get_data_complete, | ||
1305 | skb_resp, GFP_KERNEL); | ||
1306 | 1453 | ||
1307 | return; | 1454 | return; |
1308 | } | 1455 | } |
1309 | 1456 | ||
1310 | #define ATR_REQ_GB_OFFSET 17 | 1457 | #define ATR_REQ_GB_OFFSET 17 |
1311 | static int pn533_init_target_complete(struct pn533 *dev, u8 *params, int params_len) | 1458 | static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) |
1312 | { | 1459 | { |
1313 | struct pn533_cmd_init_target_response *resp; | 1460 | u8 mode, *cmd, comm_mode = NFC_COMM_PASSIVE, *gb; |
1314 | u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb; | ||
1315 | size_t gb_len; | 1461 | size_t gb_len; |
1316 | int rc; | 1462 | int rc; |
1317 | 1463 | ||
1318 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1464 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1319 | 1465 | ||
1320 | if (params_len < 0) { | 1466 | if (resp->len < ATR_REQ_GB_OFFSET + 1) |
1321 | nfc_dev_err(&dev->interface->dev, | ||
1322 | "Error %d when starting as a target", | ||
1323 | params_len); | ||
1324 | |||
1325 | return params_len; | ||
1326 | } | ||
1327 | |||
1328 | if (params_len < ATR_REQ_GB_OFFSET + 1) | ||
1329 | return -EINVAL; | 1467 | return -EINVAL; |
1330 | 1468 | ||
1331 | resp = (struct pn533_cmd_init_target_response *) params; | 1469 | mode = resp->data[0]; |
1470 | cmd = &resp->data[1]; | ||
1332 | 1471 | ||
1333 | nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x param len %d\n", | 1472 | nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x len %d\n", |
1334 | resp->mode, params_len); | 1473 | mode, resp->len); |
1335 | 1474 | ||
1336 | frame = resp->mode & PN533_INIT_TARGET_RESP_FRAME_MASK; | 1475 | if ((mode & PN533_INIT_TARGET_RESP_FRAME_MASK) == |
1337 | if (frame == PN533_INIT_TARGET_RESP_ACTIVE) | 1476 | PN533_INIT_TARGET_RESP_ACTIVE) |
1338 | comm_mode = NFC_COMM_ACTIVE; | 1477 | comm_mode = NFC_COMM_ACTIVE; |
1339 | 1478 | ||
1340 | /* Again, only DEP */ | 1479 | if ((mode & PN533_INIT_TARGET_RESP_DEP) == 0) /* Only DEP supported */ |
1341 | if ((resp->mode & PN533_INIT_TARGET_RESP_DEP) == 0) | ||
1342 | return -EOPNOTSUPP; | 1480 | return -EOPNOTSUPP; |
1343 | 1481 | ||
1344 | gb = resp->cmd + ATR_REQ_GB_OFFSET; | 1482 | gb = cmd + ATR_REQ_GB_OFFSET; |
1345 | gb_len = params_len - (ATR_REQ_GB_OFFSET + 1); | 1483 | gb_len = resp->len - (ATR_REQ_GB_OFFSET + 1); |
1346 | 1484 | ||
1347 | rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, | 1485 | rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, |
1348 | comm_mode, gb, gb_len); | 1486 | comm_mode, gb, gb_len); |
@@ -1353,7 +1491,6 @@ static int pn533_init_target_complete(struct pn533 *dev, u8 *params, int params_ | |||
1353 | } | 1491 | } |
1354 | 1492 | ||
1355 | dev->tgt_mode = 1; | 1493 | dev->tgt_mode = 1; |
1356 | |||
1357 | queue_work(dev->wq, &dev->tg_work); | 1494 | queue_work(dev->wq, &dev->tg_work); |
1358 | 1495 | ||
1359 | return 0; | 1496 | return 0; |
@@ -1361,7 +1498,7 @@ static int pn533_init_target_complete(struct pn533 *dev, u8 *params, int params_ | |||
1361 | 1498 | ||
1362 | static void pn533_listen_mode_timer(unsigned long data) | 1499 | static void pn533_listen_mode_timer(unsigned long data) |
1363 | { | 1500 | { |
1364 | struct pn533 *dev = (struct pn533 *) data; | 1501 | struct pn533 *dev = (struct pn533 *)data; |
1365 | 1502 | ||
1366 | nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout"); | 1503 | nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout"); |
1367 | 1504 | ||
@@ -1376,88 +1513,104 @@ static void pn533_listen_mode_timer(unsigned long data) | |||
1376 | } | 1513 | } |
1377 | 1514 | ||
1378 | static int pn533_poll_complete(struct pn533 *dev, void *arg, | 1515 | static int pn533_poll_complete(struct pn533 *dev, void *arg, |
1379 | u8 *params, int params_len) | 1516 | struct sk_buff *resp) |
1380 | { | 1517 | { |
1381 | struct pn533_poll_modulations *cur_mod; | 1518 | struct pn533_poll_modulations *cur_mod; |
1382 | int rc; | 1519 | int rc; |
1383 | 1520 | ||
1384 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1521 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1385 | 1522 | ||
1386 | if (params_len == -ENOENT) { | 1523 | if (IS_ERR(resp)) { |
1387 | if (dev->poll_mod_count != 0) | 1524 | rc = PTR_ERR(resp); |
1388 | return 0; | ||
1389 | |||
1390 | nfc_dev_err(&dev->interface->dev, | ||
1391 | "Polling operation has been stopped"); | ||
1392 | |||
1393 | goto stop_poll; | ||
1394 | } | ||
1395 | 1525 | ||
1396 | if (params_len < 0) { | 1526 | nfc_dev_err(&dev->interface->dev, "%s Poll complete error %d", |
1397 | nfc_dev_err(&dev->interface->dev, | 1527 | __func__, rc); |
1398 | "Error %d when running poll", params_len); | ||
1399 | 1528 | ||
1400 | goto stop_poll; | 1529 | if (rc == -ENOENT) { |
1530 | if (dev->poll_mod_count != 0) | ||
1531 | return rc; | ||
1532 | else | ||
1533 | goto stop_poll; | ||
1534 | } else if (rc < 0) { | ||
1535 | nfc_dev_err(&dev->interface->dev, | ||
1536 | "Error %d when running poll", rc); | ||
1537 | goto stop_poll; | ||
1538 | } | ||
1401 | } | 1539 | } |
1402 | 1540 | ||
1403 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; | 1541 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; |
1404 | 1542 | ||
1405 | if (cur_mod->len == 0) { | 1543 | if (cur_mod->len == 0) { /* Target mode */ |
1406 | del_timer(&dev->listen_timer); | 1544 | del_timer(&dev->listen_timer); |
1407 | 1545 | rc = pn533_init_target_complete(dev, resp); | |
1408 | return pn533_init_target_complete(dev, params, params_len); | 1546 | goto done; |
1409 | } else { | ||
1410 | rc = pn533_start_poll_complete(dev, params, params_len); | ||
1411 | if (!rc) | ||
1412 | return rc; | ||
1413 | } | 1547 | } |
1414 | 1548 | ||
1415 | pn533_poll_next_mod(dev); | 1549 | /* Initiator mode */ |
1550 | rc = pn533_start_poll_complete(dev, resp); | ||
1551 | if (!rc) | ||
1552 | goto done; | ||
1416 | 1553 | ||
1554 | pn533_poll_next_mod(dev); | ||
1417 | queue_work(dev->wq, &dev->poll_work); | 1555 | queue_work(dev->wq, &dev->poll_work); |
1418 | 1556 | ||
1419 | return 0; | 1557 | done: |
1558 | dev_kfree_skb(resp); | ||
1559 | return rc; | ||
1420 | 1560 | ||
1421 | stop_poll: | 1561 | stop_poll: |
1562 | nfc_dev_err(&dev->interface->dev, "Polling operation has been stopped"); | ||
1563 | |||
1422 | pn533_poll_reset_mod_list(dev); | 1564 | pn533_poll_reset_mod_list(dev); |
1423 | dev->poll_protocols = 0; | 1565 | dev->poll_protocols = 0; |
1424 | return 0; | 1566 | return rc; |
1425 | } | 1567 | } |
1426 | 1568 | ||
1427 | static void pn533_build_poll_frame(struct pn533 *dev, | 1569 | static struct sk_buff *pn533_alloc_poll_in_frame(struct pn533 *dev, |
1428 | struct pn533_frame *frame, | 1570 | struct pn533_poll_modulations *mod) |
1429 | struct pn533_poll_modulations *mod) | ||
1430 | { | 1571 | { |
1431 | nfc_dev_dbg(&dev->interface->dev, "mod len %d\n", mod->len); | 1572 | struct sk_buff *skb; |
1432 | 1573 | ||
1433 | if (mod->len == 0) { | 1574 | skb = pn533_alloc_skb(dev, mod->len); |
1434 | /* Listen mode */ | 1575 | if (!skb) |
1435 | pn533_init_target_frame(frame, dev->gb, dev->gb_len); | 1576 | return NULL; |
1436 | } else { | ||
1437 | /* Polling mode */ | ||
1438 | pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET); | ||
1439 | 1577 | ||
1440 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len); | 1578 | memcpy(skb_put(skb, mod->len), &mod->data, mod->len); |
1441 | frame->datalen += mod->len; | ||
1442 | 1579 | ||
1443 | pn533_tx_frame_finish(frame); | 1580 | return skb; |
1444 | } | ||
1445 | } | 1581 | } |
1446 | 1582 | ||
1447 | static int pn533_send_poll_frame(struct pn533 *dev) | 1583 | static int pn533_send_poll_frame(struct pn533 *dev) |
1448 | { | 1584 | { |
1449 | struct pn533_poll_modulations *cur_mod; | 1585 | struct pn533_poll_modulations *mod; |
1586 | struct sk_buff *skb; | ||
1450 | int rc; | 1587 | int rc; |
1588 | u8 cmd_code; | ||
1451 | 1589 | ||
1452 | cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; | 1590 | mod = dev->poll_mod_active[dev->poll_mod_curr]; |
1453 | 1591 | ||
1454 | pn533_build_poll_frame(dev, dev->out_frame, cur_mod); | 1592 | nfc_dev_dbg(&dev->interface->dev, "%s mod len %d\n", |
1593 | __func__, mod->len); | ||
1455 | 1594 | ||
1456 | rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, | 1595 | if (mod->len == 0) { /* Listen mode */ |
1457 | dev->in_maxlen, pn533_poll_complete, | 1596 | cmd_code = PN533_CMD_TG_INIT_AS_TARGET; |
1458 | NULL, GFP_KERNEL); | 1597 | skb = pn533_alloc_poll_tg_frame(dev); |
1459 | if (rc) | 1598 | } else { /* Polling mode */ |
1599 | cmd_code = PN533_CMD_IN_LIST_PASSIVE_TARGET; | ||
1600 | skb = pn533_alloc_poll_in_frame(dev, mod); | ||
1601 | } | ||
1602 | |||
1603 | if (!skb) { | ||
1604 | nfc_dev_err(&dev->interface->dev, "Failed to allocate skb."); | ||
1605 | return -ENOMEM; | ||
1606 | } | ||
1607 | |||
1608 | rc = pn533_send_cmd_async(dev, cmd_code, skb, pn533_poll_complete, | ||
1609 | NULL); | ||
1610 | if (rc < 0) { | ||
1611 | dev_kfree_skb(skb); | ||
1460 | nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc); | 1612 | nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc); |
1613 | } | ||
1461 | 1614 | ||
1462 | return rc; | 1615 | return rc; |
1463 | } | 1616 | } |
@@ -1533,8 +1686,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) | |||
1533 | del_timer(&dev->listen_timer); | 1686 | del_timer(&dev->listen_timer); |
1534 | 1687 | ||
1535 | if (!dev->poll_mod_count) { | 1688 | if (!dev->poll_mod_count) { |
1536 | nfc_dev_dbg(&dev->interface->dev, "Polling operation was not" | 1689 | nfc_dev_dbg(&dev->interface->dev, |
1537 | " running"); | 1690 | "Polling operation was not running"); |
1538 | return; | 1691 | return; |
1539 | } | 1692 | } |
1540 | 1693 | ||
@@ -1549,38 +1702,38 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) | |||
1549 | 1702 | ||
1550 | static int pn533_activate_target_nfcdep(struct pn533 *dev) | 1703 | static int pn533_activate_target_nfcdep(struct pn533 *dev) |
1551 | { | 1704 | { |
1552 | struct pn533_cmd_activate_param param; | 1705 | struct pn533_cmd_activate_response *rsp; |
1553 | struct pn533_cmd_activate_response *resp; | ||
1554 | u16 gt_len; | 1706 | u16 gt_len; |
1555 | int rc; | 1707 | int rc; |
1556 | 1708 | ||
1557 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1709 | struct sk_buff *skb; |
1710 | struct sk_buff *resp; | ||
1558 | 1711 | ||
1559 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_ATR); | 1712 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1560 | 1713 | ||
1561 | param.tg = 1; | 1714 | skb = pn533_alloc_skb(dev, sizeof(u8) * 2); /*TG + Next*/ |
1562 | param.next = 0; | 1715 | if (!skb) |
1563 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), ¶m, | 1716 | return -ENOMEM; |
1564 | sizeof(struct pn533_cmd_activate_param)); | ||
1565 | dev->out_frame->datalen += sizeof(struct pn533_cmd_activate_param); | ||
1566 | 1717 | ||
1567 | pn533_tx_frame_finish(dev->out_frame); | 1718 | *skb_put(skb, sizeof(u8)) = 1; /* TG */ |
1719 | *skb_put(skb, sizeof(u8)) = 0; /* Next */ | ||
1568 | 1720 | ||
1569 | rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, | 1721 | resp = pn533_send_cmd_sync(dev, PN533_CMD_IN_ATR, skb); |
1570 | dev->in_maxlen); | 1722 | if (IS_ERR(resp)) |
1571 | if (rc) | 1723 | return PTR_ERR(resp); |
1572 | return rc; | ||
1573 | 1724 | ||
1574 | resp = (struct pn533_cmd_activate_response *) | 1725 | rsp = (struct pn533_cmd_activate_response *)resp->data; |
1575 | PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame); | 1726 | rc = rsp->status & PN533_CMD_RET_MASK; |
1576 | rc = resp->status & PN533_CMD_RET_MASK; | 1727 | if (rc != PN533_CMD_RET_SUCCESS) { |
1577 | if (rc != PN533_CMD_RET_SUCCESS) | 1728 | dev_kfree_skb(resp); |
1578 | return -EIO; | 1729 | return -EIO; |
1730 | } | ||
1579 | 1731 | ||
1580 | /* ATR_RES general bytes are located at offset 16 */ | 1732 | /* ATR_RES general bytes are located at offset 16 */ |
1581 | gt_len = PN533_FRAME_CMD_PARAMS_LEN(dev->in_frame) - 16; | 1733 | gt_len = resp->len - 16; |
1582 | rc = nfc_set_remote_general_bytes(dev->nfc_dev, resp->gt, gt_len); | 1734 | rc = nfc_set_remote_general_bytes(dev->nfc_dev, rsp->gt, gt_len); |
1583 | 1735 | ||
1736 | dev_kfree_skb(resp); | ||
1584 | return rc; | 1737 | return rc; |
1585 | } | 1738 | } |
1586 | 1739 | ||
@@ -1591,38 +1744,38 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, | |||
1591 | int rc; | 1744 | int rc; |
1592 | 1745 | ||
1593 | nfc_dev_dbg(&dev->interface->dev, "%s - protocol=%u", __func__, | 1746 | nfc_dev_dbg(&dev->interface->dev, "%s - protocol=%u", __func__, |
1594 | protocol); | 1747 | protocol); |
1595 | 1748 | ||
1596 | if (dev->poll_mod_count) { | 1749 | if (dev->poll_mod_count) { |
1597 | nfc_dev_err(&dev->interface->dev, "Cannot activate while" | 1750 | nfc_dev_err(&dev->interface->dev, |
1598 | " polling"); | 1751 | "Cannot activate while polling"); |
1599 | return -EBUSY; | 1752 | return -EBUSY; |
1600 | } | 1753 | } |
1601 | 1754 | ||
1602 | if (dev->tgt_active_prot) { | 1755 | if (dev->tgt_active_prot) { |
1603 | nfc_dev_err(&dev->interface->dev, "There is already an active" | 1756 | nfc_dev_err(&dev->interface->dev, |
1604 | " target"); | 1757 | "There is already an active target"); |
1605 | return -EBUSY; | 1758 | return -EBUSY; |
1606 | } | 1759 | } |
1607 | 1760 | ||
1608 | if (!dev->tgt_available_prots) { | 1761 | if (!dev->tgt_available_prots) { |
1609 | nfc_dev_err(&dev->interface->dev, "There is no available target" | 1762 | nfc_dev_err(&dev->interface->dev, |
1610 | " to activate"); | 1763 | "There is no available target to activate"); |
1611 | return -EINVAL; | 1764 | return -EINVAL; |
1612 | } | 1765 | } |
1613 | 1766 | ||
1614 | if (!(dev->tgt_available_prots & (1 << protocol))) { | 1767 | if (!(dev->tgt_available_prots & (1 << protocol))) { |
1615 | nfc_dev_err(&dev->interface->dev, "The target does not support" | 1768 | nfc_dev_err(&dev->interface->dev, |
1616 | " the requested protocol %u", protocol); | 1769 | "Target doesn't support requested proto %u", |
1770 | protocol); | ||
1617 | return -EINVAL; | 1771 | return -EINVAL; |
1618 | } | 1772 | } |
1619 | 1773 | ||
1620 | if (protocol == NFC_PROTO_NFC_DEP) { | 1774 | if (protocol == NFC_PROTO_NFC_DEP) { |
1621 | rc = pn533_activate_target_nfcdep(dev); | 1775 | rc = pn533_activate_target_nfcdep(dev); |
1622 | if (rc) { | 1776 | if (rc) { |
1623 | nfc_dev_err(&dev->interface->dev, "Error %d when" | 1777 | nfc_dev_err(&dev->interface->dev, |
1624 | " activating target with" | 1778 | "Activating target with DEP failed %d", rc); |
1625 | " NFC_DEP protocol", rc); | ||
1626 | return rc; | 1779 | return rc; |
1627 | } | 1780 | } |
1628 | } | 1781 | } |
@@ -1637,8 +1790,10 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, | |||
1637 | struct nfc_target *target) | 1790 | struct nfc_target *target) |
1638 | { | 1791 | { |
1639 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1792 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1640 | u8 tg; | 1793 | |
1641 | u8 status; | 1794 | struct sk_buff *skb; |
1795 | struct sk_buff *resp; | ||
1796 | |||
1642 | int rc; | 1797 | int rc; |
1643 | 1798 | ||
1644 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1799 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
@@ -1649,83 +1804,69 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, | |||
1649 | } | 1804 | } |
1650 | 1805 | ||
1651 | dev->tgt_active_prot = 0; | 1806 | dev->tgt_active_prot = 0; |
1652 | |||
1653 | skb_queue_purge(&dev->resp_q); | 1807 | skb_queue_purge(&dev->resp_q); |
1654 | 1808 | ||
1655 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_RELEASE); | 1809 | skb = pn533_alloc_skb(dev, sizeof(u8)); |
1656 | 1810 | if (!skb) | |
1657 | tg = 1; | 1811 | return; |
1658 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), &tg, sizeof(u8)); | ||
1659 | dev->out_frame->datalen += sizeof(u8); | ||
1660 | 1812 | ||
1661 | pn533_tx_frame_finish(dev->out_frame); | 1813 | *skb_put(skb, 1) = 1; /* TG*/ |
1662 | 1814 | ||
1663 | rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, | 1815 | resp = pn533_send_cmd_sync(dev, PN533_CMD_IN_RELEASE, skb); |
1664 | dev->in_maxlen); | 1816 | if (IS_ERR(resp)) |
1665 | if (rc) { | ||
1666 | nfc_dev_err(&dev->interface->dev, "Error when sending release" | ||
1667 | " command to the controller"); | ||
1668 | return; | 1817 | return; |
1669 | } | ||
1670 | 1818 | ||
1671 | status = PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame)[0]; | 1819 | rc = resp->data[0] & PN533_CMD_RET_MASK; |
1672 | rc = status & PN533_CMD_RET_MASK; | ||
1673 | if (rc != PN533_CMD_RET_SUCCESS) | 1820 | if (rc != PN533_CMD_RET_SUCCESS) |
1674 | nfc_dev_err(&dev->interface->dev, "Error 0x%x when releasing" | 1821 | nfc_dev_err(&dev->interface->dev, |
1675 | " the target", rc); | 1822 | "Error 0x%x when releasing the target", rc); |
1676 | 1823 | ||
1824 | dev_kfree_skb(resp); | ||
1677 | return; | 1825 | return; |
1678 | } | 1826 | } |
1679 | 1827 | ||
1680 | 1828 | ||
1681 | static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, | 1829 | static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, |
1682 | u8 *params, int params_len) | 1830 | struct sk_buff *resp) |
1683 | { | 1831 | { |
1684 | struct pn533_cmd_jump_dep_response *resp; | 1832 | struct pn533_cmd_jump_dep_response *rsp; |
1685 | struct nfc_target nfc_target; | ||
1686 | u8 target_gt_len; | 1833 | u8 target_gt_len; |
1687 | int rc; | 1834 | int rc; |
1688 | struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg; | 1835 | u8 active = *(u8 *)arg; |
1689 | u8 active = cmd->active; | ||
1690 | 1836 | ||
1691 | kfree(arg); | 1837 | kfree(arg); |
1692 | 1838 | ||
1693 | if (params_len == -ENOENT) { | 1839 | if (IS_ERR(resp)) |
1694 | nfc_dev_dbg(&dev->interface->dev, ""); | 1840 | return PTR_ERR(resp); |
1695 | return 0; | ||
1696 | } | ||
1697 | |||
1698 | if (params_len < 0) { | ||
1699 | nfc_dev_err(&dev->interface->dev, | ||
1700 | "Error %d when bringing DEP link up", | ||
1701 | params_len); | ||
1702 | return 0; | ||
1703 | } | ||
1704 | 1841 | ||
1705 | if (dev->tgt_available_prots && | 1842 | if (dev->tgt_available_prots && |
1706 | !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) { | 1843 | !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) { |
1707 | nfc_dev_err(&dev->interface->dev, | 1844 | nfc_dev_err(&dev->interface->dev, |
1708 | "The target does not support DEP"); | 1845 | "The target does not support DEP"); |
1709 | return -EINVAL; | 1846 | rc = -EINVAL; |
1847 | goto error; | ||
1710 | } | 1848 | } |
1711 | 1849 | ||
1712 | resp = (struct pn533_cmd_jump_dep_response *) params; | 1850 | rsp = (struct pn533_cmd_jump_dep_response *)resp->data; |
1713 | rc = resp->status & PN533_CMD_RET_MASK; | 1851 | |
1852 | rc = rsp->status & PN533_CMD_RET_MASK; | ||
1714 | if (rc != PN533_CMD_RET_SUCCESS) { | 1853 | if (rc != PN533_CMD_RET_SUCCESS) { |
1715 | nfc_dev_err(&dev->interface->dev, | 1854 | nfc_dev_err(&dev->interface->dev, |
1716 | "Bringing DEP link up failed %d", rc); | 1855 | "Bringing DEP link up failed %d", rc); |
1717 | return 0; | 1856 | goto error; |
1718 | } | 1857 | } |
1719 | 1858 | ||
1720 | if (!dev->tgt_available_prots) { | 1859 | if (!dev->tgt_available_prots) { |
1860 | struct nfc_target nfc_target; | ||
1861 | |||
1721 | nfc_dev_dbg(&dev->interface->dev, "Creating new target"); | 1862 | nfc_dev_dbg(&dev->interface->dev, "Creating new target"); |
1722 | 1863 | ||
1723 | nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; | 1864 | nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; |
1724 | nfc_target.nfcid1_len = 10; | 1865 | nfc_target.nfcid1_len = 10; |
1725 | memcpy(nfc_target.nfcid1, resp->nfcid3t, nfc_target.nfcid1_len); | 1866 | memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len); |
1726 | rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1); | 1867 | rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1); |
1727 | if (rc) | 1868 | if (rc) |
1728 | return 0; | 1869 | goto error; |
1729 | 1870 | ||
1730 | dev->tgt_available_prots = 0; | 1871 | dev->tgt_available_prots = 0; |
1731 | } | 1872 | } |
@@ -1733,15 +1874,17 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, | |||
1733 | dev->tgt_active_prot = NFC_PROTO_NFC_DEP; | 1874 | dev->tgt_active_prot = NFC_PROTO_NFC_DEP; |
1734 | 1875 | ||
1735 | /* ATR_RES general bytes are located at offset 17 */ | 1876 | /* ATR_RES general bytes are located at offset 17 */ |
1736 | target_gt_len = PN533_FRAME_CMD_PARAMS_LEN(dev->in_frame) - 17; | 1877 | target_gt_len = resp->len - 17; |
1737 | rc = nfc_set_remote_general_bytes(dev->nfc_dev, | 1878 | rc = nfc_set_remote_general_bytes(dev->nfc_dev, |
1738 | resp->gt, target_gt_len); | 1879 | rsp->gt, target_gt_len); |
1739 | if (rc == 0) | 1880 | if (rc == 0) |
1740 | rc = nfc_dep_link_is_up(dev->nfc_dev, | 1881 | rc = nfc_dep_link_is_up(dev->nfc_dev, |
1741 | dev->nfc_dev->targets[0].idx, | 1882 | dev->nfc_dev->targets[0].idx, |
1742 | !active, NFC_RF_INITIATOR); | 1883 | !active, NFC_RF_INITIATOR); |
1743 | 1884 | ||
1744 | return 0; | 1885 | error: |
1886 | dev_kfree_skb(resp); | ||
1887 | return rc; | ||
1745 | } | 1888 | } |
1746 | 1889 | ||
1747 | static int pn533_mod_to_baud(struct pn533 *dev) | 1890 | static int pn533_mod_to_baud(struct pn533 *dev) |
@@ -1760,25 +1903,26 @@ static int pn533_mod_to_baud(struct pn533 *dev) | |||
1760 | 1903 | ||
1761 | #define PASSIVE_DATA_LEN 5 | 1904 | #define PASSIVE_DATA_LEN 5 |
1762 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | 1905 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, |
1763 | u8 comm_mode, u8* gb, size_t gb_len) | 1906 | u8 comm_mode, u8 *gb, size_t gb_len) |
1764 | { | 1907 | { |
1765 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1908 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1766 | struct pn533_cmd_jump_dep *cmd; | 1909 | struct sk_buff *skb; |
1767 | u8 cmd_len, *data_ptr; | 1910 | int rc, baud, skb_len; |
1911 | u8 *next, *arg; | ||
1912 | |||
1768 | u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; | 1913 | u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; |
1769 | int rc, baud; | ||
1770 | 1914 | ||
1771 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 1915 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1772 | 1916 | ||
1773 | if (dev->poll_mod_count) { | 1917 | if (dev->poll_mod_count) { |
1774 | nfc_dev_err(&dev->interface->dev, | 1918 | nfc_dev_err(&dev->interface->dev, |
1775 | "Cannot bring the DEP link up while polling"); | 1919 | "Cannot bring the DEP link up while polling"); |
1776 | return -EBUSY; | 1920 | return -EBUSY; |
1777 | } | 1921 | } |
1778 | 1922 | ||
1779 | if (dev->tgt_active_prot) { | 1923 | if (dev->tgt_active_prot) { |
1780 | nfc_dev_err(&dev->interface->dev, | 1924 | nfc_dev_err(&dev->interface->dev, |
1781 | "There is already an active target"); | 1925 | "There is already an active target"); |
1782 | return -EBUSY; | 1926 | return -EBUSY; |
1783 | } | 1927 | } |
1784 | 1928 | ||
@@ -1789,43 +1933,48 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
1789 | return baud; | 1933 | return baud; |
1790 | } | 1934 | } |
1791 | 1935 | ||
1792 | cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len; | 1936 | skb_len = 3 + gb_len; /* ActPass + BR + Next */ |
1793 | if (comm_mode == NFC_COMM_PASSIVE) | 1937 | if (comm_mode == NFC_COMM_PASSIVE) |
1794 | cmd_len += PASSIVE_DATA_LEN; | 1938 | skb_len += PASSIVE_DATA_LEN; |
1795 | 1939 | ||
1796 | cmd = kzalloc(cmd_len, GFP_KERNEL); | 1940 | skb = pn533_alloc_skb(dev, skb_len); |
1797 | if (cmd == NULL) | 1941 | if (!skb) |
1798 | return -ENOMEM; | 1942 | return -ENOMEM; |
1799 | 1943 | ||
1800 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP); | 1944 | *skb_put(skb, 1) = !comm_mode; /* ActPass */ |
1945 | *skb_put(skb, 1) = baud; /* Baud rate */ | ||
1801 | 1946 | ||
1802 | cmd->active = !comm_mode; | 1947 | next = skb_put(skb, 1); /* Next */ |
1803 | cmd->next = 0; | 1948 | *next = 0; |
1804 | cmd->baud = baud; | 1949 | |
1805 | data_ptr = cmd->data; | 1950 | if (comm_mode == NFC_COMM_PASSIVE && baud > 0) { |
1806 | if (comm_mode == NFC_COMM_PASSIVE && cmd->baud > 0) { | 1951 | memcpy(skb_put(skb, PASSIVE_DATA_LEN), passive_data, |
1807 | memcpy(data_ptr, passive_data, PASSIVE_DATA_LEN); | 1952 | PASSIVE_DATA_LEN); |
1808 | cmd->next |= 1; | 1953 | *next |= 1; |
1809 | data_ptr += PASSIVE_DATA_LEN; | ||
1810 | } | 1954 | } |
1811 | 1955 | ||
1812 | if (gb != NULL && gb_len > 0) { | 1956 | if (gb != NULL && gb_len > 0) { |
1813 | cmd->next |= 4; /* We have some Gi */ | 1957 | memcpy(skb_put(skb, gb_len), gb, gb_len); |
1814 | memcpy(data_ptr, gb, gb_len); | 1958 | *next |= 4; /* We have some Gi */ |
1815 | } else { | 1959 | } else { |
1816 | cmd->next = 0; | 1960 | *next = 0; |
1817 | } | 1961 | } |
1818 | 1962 | ||
1819 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), cmd, cmd_len); | 1963 | arg = kmalloc(sizeof(*arg), GFP_KERNEL); |
1820 | dev->out_frame->datalen += cmd_len; | 1964 | if (!arg) { |
1965 | dev_kfree_skb(skb); | ||
1966 | return -ENOMEM; | ||
1967 | } | ||
1821 | 1968 | ||
1822 | pn533_tx_frame_finish(dev->out_frame); | 1969 | *arg = !comm_mode; |
1823 | 1970 | ||
1824 | rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, | 1971 | rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb, |
1825 | dev->in_maxlen, pn533_in_dep_link_up_complete, | 1972 | pn533_in_dep_link_up_complete, arg); |
1826 | cmd, GFP_KERNEL); | 1973 | |
1827 | if (rc < 0) | 1974 | if (rc < 0) { |
1828 | kfree(cmd); | 1975 | dev_kfree_skb(skb); |
1976 | kfree(arg); | ||
1977 | } | ||
1829 | 1978 | ||
1830 | return rc; | 1979 | return rc; |
1831 | } | 1980 | } |
@@ -1834,6 +1983,8 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev) | |||
1834 | { | 1983 | { |
1835 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1984 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1836 | 1985 | ||
1986 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | ||
1987 | |||
1837 | pn533_poll_reset_mod_list(dev); | 1988 | pn533_poll_reset_mod_list(dev); |
1838 | 1989 | ||
1839 | if (dev->tgt_mode || dev->tgt_active_prot) { | 1990 | if (dev->tgt_mode || dev->tgt_active_prot) { |
@@ -1849,68 +2000,7 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev) | |||
1849 | return 0; | 2000 | return 0; |
1850 | } | 2001 | } |
1851 | 2002 | ||
1852 | static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb, | ||
1853 | bool target) | ||
1854 | { | ||
1855 | int payload_len = skb->len; | ||
1856 | struct pn533_frame *out_frame; | ||
1857 | u8 tg; | ||
1858 | |||
1859 | nfc_dev_dbg(&dev->interface->dev, "%s - Sending %d bytes", __func__, | ||
1860 | payload_len); | ||
1861 | |||
1862 | if (payload_len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { | ||
1863 | /* TODO: Implement support to multi-part data exchange */ | ||
1864 | nfc_dev_err(&dev->interface->dev, "Data length greater than the" | ||
1865 | " max allowed: %d", | ||
1866 | PN533_CMD_DATAEXCH_DATA_MAXLEN); | ||
1867 | return -ENOSYS; | ||
1868 | } | ||
1869 | |||
1870 | if (target == true) { | ||
1871 | switch (dev->device_type) { | ||
1872 | case PN533_DEVICE_PASORI: | ||
1873 | if (dev->tgt_active_prot == NFC_PROTO_FELICA) { | ||
1874 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); | ||
1875 | out_frame = (struct pn533_frame *) skb->data; | ||
1876 | pn533_tx_frame_init(out_frame, | ||
1877 | PN533_CMD_IN_COMM_THRU); | ||
1878 | |||
1879 | break; | ||
1880 | } | ||
1881 | |||
1882 | default: | ||
1883 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); | ||
1884 | out_frame = (struct pn533_frame *) skb->data; | ||
1885 | pn533_tx_frame_init(out_frame, | ||
1886 | PN533_CMD_IN_DATA_EXCHANGE); | ||
1887 | tg = 1; | ||
1888 | memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), | ||
1889 | &tg, sizeof(u8)); | ||
1890 | out_frame->datalen += sizeof(u8); | ||
1891 | |||
1892 | break; | ||
1893 | } | ||
1894 | |||
1895 | } else { | ||
1896 | skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); | ||
1897 | out_frame = (struct pn533_frame *) skb->data; | ||
1898 | pn533_tx_frame_init(out_frame, PN533_CMD_TG_SET_DATA); | ||
1899 | } | ||
1900 | |||
1901 | |||
1902 | /* The data is already in the out_frame, just update the datalen */ | ||
1903 | out_frame->datalen += payload_len; | ||
1904 | |||
1905 | pn533_tx_frame_finish(out_frame); | ||
1906 | skb_put(skb, PN533_FRAME_TAIL_SIZE); | ||
1907 | |||
1908 | return 0; | ||
1909 | } | ||
1910 | |||
1911 | struct pn533_data_exchange_arg { | 2003 | struct pn533_data_exchange_arg { |
1912 | struct sk_buff *skb_resp; | ||
1913 | struct sk_buff *skb_out; | ||
1914 | data_exchange_cb_t cb; | 2004 | data_exchange_cb_t cb; |
1915 | void *cb_context; | 2005 | void *cb_context; |
1916 | }; | 2006 | }; |
@@ -1920,7 +2010,7 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) | |||
1920 | struct sk_buff *skb, *tmp, *t; | 2010 | struct sk_buff *skb, *tmp, *t; |
1921 | unsigned int skb_len = 0, tmp_len = 0; | 2011 | unsigned int skb_len = 0, tmp_len = 0; |
1922 | 2012 | ||
1923 | nfc_dev_dbg(&dev->interface->dev, "%s\n", __func__); | 2013 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1924 | 2014 | ||
1925 | if (skb_queue_empty(&dev->resp_q)) | 2015 | if (skb_queue_empty(&dev->resp_q)) |
1926 | return NULL; | 2016 | return NULL; |
@@ -1954,46 +2044,44 @@ out: | |||
1954 | } | 2044 | } |
1955 | 2045 | ||
1956 | static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, | 2046 | static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, |
1957 | u8 *params, int params_len) | 2047 | struct sk_buff *resp) |
1958 | { | 2048 | { |
1959 | struct pn533_data_exchange_arg *arg = _arg; | 2049 | struct pn533_data_exchange_arg *arg = _arg; |
1960 | struct sk_buff *skb = NULL, *skb_resp = arg->skb_resp; | 2050 | struct sk_buff *skb; |
1961 | struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data; | 2051 | int rc = 0; |
1962 | int err = 0; | 2052 | u8 status, ret, mi; |
1963 | u8 status; | ||
1964 | u8 cmd_ret; | ||
1965 | 2053 | ||
1966 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2054 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
1967 | 2055 | ||
1968 | dev_kfree_skb(arg->skb_out); | 2056 | if (IS_ERR(resp)) { |
1969 | 2057 | rc = PTR_ERR(resp); | |
1970 | if (params_len < 0) { /* error */ | 2058 | goto _error; |
1971 | err = params_len; | ||
1972 | goto error; | ||
1973 | } | 2059 | } |
1974 | 2060 | ||
1975 | status = params[0]; | 2061 | status = resp->data[0]; |
2062 | ret = status & PN533_CMD_RET_MASK; | ||
2063 | mi = status & PN533_CMD_MI_MASK; | ||
2064 | |||
2065 | skb_pull(resp, sizeof(status)); | ||
1976 | 2066 | ||
1977 | cmd_ret = status & PN533_CMD_RET_MASK; | 2067 | if (ret != PN533_CMD_RET_SUCCESS) { |
1978 | if (cmd_ret != PN533_CMD_RET_SUCCESS) { | 2068 | nfc_dev_err(&dev->interface->dev, |
1979 | nfc_dev_err(&dev->interface->dev, "PN533 reported error %d when" | 2069 | "PN533 reported error %d when exchanging data", |
1980 | " exchanging data", cmd_ret); | 2070 | ret); |
1981 | err = -EIO; | 2071 | rc = -EIO; |
1982 | goto error; | 2072 | goto error; |
1983 | } | 2073 | } |
1984 | 2074 | ||
1985 | skb_put(skb_resp, PN533_FRAME_SIZE(in_frame)); | 2075 | skb_queue_tail(&dev->resp_q, resp); |
1986 | skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN); | ||
1987 | skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_SIZE); | ||
1988 | skb_queue_tail(&dev->resp_q, skb_resp); | ||
1989 | 2076 | ||
1990 | if (status & PN533_CMD_MI_MASK) { | 2077 | if (mi) { |
2078 | dev->cmd_complete_mi_arg = arg; | ||
1991 | queue_work(dev->wq, &dev->mi_work); | 2079 | queue_work(dev->wq, &dev->mi_work); |
1992 | return -EINPROGRESS; | 2080 | return -EINPROGRESS; |
1993 | } | 2081 | } |
1994 | 2082 | ||
1995 | skb = pn533_build_response(dev); | 2083 | skb = pn533_build_response(dev); |
1996 | if (skb == NULL) | 2084 | if (!skb) |
1997 | goto error; | 2085 | goto error; |
1998 | 2086 | ||
1999 | arg->cb(arg->cb_context, skb, 0); | 2087 | arg->cb(arg->cb_context, skb, 0); |
@@ -2001,11 +2089,12 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, | |||
2001 | return 0; | 2089 | return 0; |
2002 | 2090 | ||
2003 | error: | 2091 | error: |
2092 | dev_kfree_skb(resp); | ||
2093 | _error: | ||
2004 | skb_queue_purge(&dev->resp_q); | 2094 | skb_queue_purge(&dev->resp_q); |
2005 | dev_kfree_skb(skb_resp); | 2095 | arg->cb(arg->cb_context, NULL, rc); |
2006 | arg->cb(arg->cb_context, NULL, err); | ||
2007 | kfree(arg); | 2096 | kfree(arg); |
2008 | return 0; | 2097 | return rc; |
2009 | } | 2098 | } |
2010 | 2099 | ||
2011 | static int pn533_transceive(struct nfc_dev *nfc_dev, | 2100 | static int pn533_transceive(struct nfc_dev *nfc_dev, |
@@ -2013,87 +2102,82 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, | |||
2013 | data_exchange_cb_t cb, void *cb_context) | 2102 | data_exchange_cb_t cb, void *cb_context) |
2014 | { | 2103 | { |
2015 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 2104 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
2016 | struct pn533_frame *out_frame, *in_frame; | 2105 | struct pn533_data_exchange_arg *arg = NULL; |
2017 | struct pn533_data_exchange_arg *arg; | ||
2018 | struct sk_buff *skb_resp; | ||
2019 | int skb_resp_len; | ||
2020 | int rc; | 2106 | int rc; |
2021 | 2107 | ||
2022 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2108 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
2023 | 2109 | ||
2024 | if (!dev->tgt_active_prot) { | 2110 | if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { |
2025 | nfc_dev_err(&dev->interface->dev, "Cannot exchange data if" | 2111 | /* TODO: Implement support to multi-part data exchange */ |
2026 | " there is no active target"); | 2112 | nfc_dev_err(&dev->interface->dev, |
2027 | rc = -EINVAL; | 2113 | "Data length greater than the max allowed: %d", |
2114 | PN533_CMD_DATAEXCH_DATA_MAXLEN); | ||
2115 | rc = -ENOSYS; | ||
2028 | goto error; | 2116 | goto error; |
2029 | } | 2117 | } |
2030 | 2118 | ||
2031 | rc = pn533_build_tx_frame(dev, skb, true); | 2119 | if (!dev->tgt_active_prot) { |
2032 | if (rc) | 2120 | nfc_dev_err(&dev->interface->dev, |
2033 | goto error; | 2121 | "Can't exchange data if there is no active target"); |
2034 | 2122 | rc = -EINVAL; | |
2035 | skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN + | ||
2036 | PN533_CMD_DATAEXCH_DATA_MAXLEN + | ||
2037 | PN533_FRAME_TAIL_SIZE; | ||
2038 | |||
2039 | skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL); | ||
2040 | if (!skb_resp) { | ||
2041 | rc = -ENOMEM; | ||
2042 | goto error; | 2123 | goto error; |
2043 | } | 2124 | } |
2044 | 2125 | ||
2045 | in_frame = (struct pn533_frame *) skb_resp->data; | 2126 | arg = kmalloc(sizeof(*arg), GFP_KERNEL); |
2046 | out_frame = (struct pn533_frame *) skb->data; | ||
2047 | |||
2048 | arg = kmalloc(sizeof(struct pn533_data_exchange_arg), GFP_KERNEL); | ||
2049 | if (!arg) { | 2127 | if (!arg) { |
2050 | rc = -ENOMEM; | 2128 | rc = -ENOMEM; |
2051 | goto free_skb_resp; | 2129 | goto error; |
2052 | } | 2130 | } |
2053 | 2131 | ||
2054 | arg->skb_resp = skb_resp; | ||
2055 | arg->skb_out = skb; | ||
2056 | arg->cb = cb; | 2132 | arg->cb = cb; |
2057 | arg->cb_context = cb_context; | 2133 | arg->cb_context = cb_context; |
2058 | 2134 | ||
2059 | rc = pn533_send_cmd_frame_async(dev, out_frame, in_frame, skb_resp_len, | 2135 | switch (dev->device_type) { |
2060 | pn533_data_exchange_complete, arg, | 2136 | case PN533_DEVICE_PASORI: |
2061 | GFP_KERNEL); | 2137 | if (dev->tgt_active_prot == NFC_PROTO_FELICA) { |
2062 | if (rc) { | 2138 | rc = pn533_send_data_async(dev, PN533_CMD_IN_COMM_THRU, |
2063 | nfc_dev_err(&dev->interface->dev, "Error %d when trying to" | 2139 | skb, |
2064 | " perform data_exchange", rc); | 2140 | pn533_data_exchange_complete, |
2065 | goto free_arg; | 2141 | arg); |
2142 | |||
2143 | break; | ||
2144 | } | ||
2145 | default: | ||
2146 | *skb_push(skb, sizeof(u8)) = 1; /*TG*/ | ||
2147 | |||
2148 | rc = pn533_send_data_async(dev, PN533_CMD_IN_DATA_EXCHANGE, | ||
2149 | skb, pn533_data_exchange_complete, | ||
2150 | arg); | ||
2151 | |||
2152 | break; | ||
2066 | } | 2153 | } |
2067 | 2154 | ||
2155 | if (rc < 0) /* rc from send_async */ | ||
2156 | goto error; | ||
2157 | |||
2068 | return 0; | 2158 | return 0; |
2069 | 2159 | ||
2070 | free_arg: | ||
2071 | kfree(arg); | ||
2072 | free_skb_resp: | ||
2073 | kfree_skb(skb_resp); | ||
2074 | error: | 2160 | error: |
2075 | kfree_skb(skb); | 2161 | kfree(arg); |
2162 | dev_kfree_skb(skb); | ||
2076 | return rc; | 2163 | return rc; |
2077 | } | 2164 | } |
2078 | 2165 | ||
2079 | static int pn533_tm_send_complete(struct pn533 *dev, void *arg, | 2166 | static int pn533_tm_send_complete(struct pn533 *dev, void *arg, |
2080 | u8 *params, int params_len) | 2167 | struct sk_buff *resp) |
2081 | { | 2168 | { |
2082 | struct sk_buff *skb_out = arg; | 2169 | u8 status; |
2083 | 2170 | ||
2084 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2171 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
2085 | 2172 | ||
2086 | dev_kfree_skb(skb_out); | 2173 | if (IS_ERR(resp)) |
2174 | return PTR_ERR(resp); | ||
2087 | 2175 | ||
2088 | if (params_len < 0) { | 2176 | status = resp->data[0]; |
2089 | nfc_dev_err(&dev->interface->dev, | ||
2090 | "Error %d when sending data", | ||
2091 | params_len); | ||
2092 | 2177 | ||
2093 | return params_len; | 2178 | dev_kfree_skb(resp); |
2094 | } | ||
2095 | 2179 | ||
2096 | if (params_len > 0 && params[0] != 0) { | 2180 | if (status != 0) { |
2097 | nfc_tm_deactivated(dev->nfc_dev); | 2181 | nfc_tm_deactivated(dev->nfc_dev); |
2098 | 2182 | ||
2099 | dev->tgt_mode = 0; | 2183 | dev->tgt_mode = 0; |
@@ -2109,30 +2193,21 @@ static int pn533_tm_send_complete(struct pn533 *dev, void *arg, | |||
2109 | static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | 2193 | static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) |
2110 | { | 2194 | { |
2111 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 2195 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
2112 | struct pn533_frame *out_frame; | ||
2113 | int rc; | 2196 | int rc; |
2114 | 2197 | ||
2115 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2198 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
2116 | 2199 | ||
2117 | rc = pn533_build_tx_frame(dev, skb, false); | 2200 | if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { |
2118 | if (rc) | ||
2119 | goto error; | ||
2120 | |||
2121 | out_frame = (struct pn533_frame *) skb->data; | ||
2122 | |||
2123 | rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame, | ||
2124 | dev->in_maxlen, pn533_tm_send_complete, | ||
2125 | skb, GFP_KERNEL); | ||
2126 | if (rc) { | ||
2127 | nfc_dev_err(&dev->interface->dev, | 2201 | nfc_dev_err(&dev->interface->dev, |
2128 | "Error %d when trying to send data", rc); | 2202 | "Data length greater than the max allowed: %d", |
2129 | goto error; | 2203 | PN533_CMD_DATAEXCH_DATA_MAXLEN); |
2204 | return -ENOSYS; | ||
2130 | } | 2205 | } |
2131 | 2206 | ||
2132 | return 0; | 2207 | rc = pn533_send_data_async(dev, PN533_CMD_TG_SET_DATA, skb, |
2133 | 2208 | pn533_tm_send_complete, NULL); | |
2134 | error: | 2209 | if (rc < 0) |
2135 | kfree_skb(skb); | 2210 | dev_kfree_skb(skb); |
2136 | 2211 | ||
2137 | return rc; | 2212 | return rc; |
2138 | } | 2213 | } |
@@ -2140,107 +2215,123 @@ error: | |||
2140 | static void pn533_wq_mi_recv(struct work_struct *work) | 2215 | static void pn533_wq_mi_recv(struct work_struct *work) |
2141 | { | 2216 | { |
2142 | struct pn533 *dev = container_of(work, struct pn533, mi_work); | 2217 | struct pn533 *dev = container_of(work, struct pn533, mi_work); |
2143 | struct sk_buff *skb_cmd; | 2218 | |
2144 | struct pn533_data_exchange_arg *arg = dev->cmd_complete_arg; | 2219 | struct sk_buff *skb; |
2145 | struct pn533_frame *out_frame, *in_frame; | ||
2146 | struct sk_buff *skb_resp; | ||
2147 | int skb_resp_len; | ||
2148 | int rc; | 2220 | int rc; |
2149 | 2221 | ||
2150 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2222 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
2151 | 2223 | ||
2152 | /* This is a zero payload size skb */ | 2224 | skb = pn533_alloc_skb(dev, PN533_CMD_DATAEXCH_HEAD_LEN); |
2153 | skb_cmd = alloc_skb(PN533_CMD_DATAEXCH_HEAD_LEN + PN533_FRAME_TAIL_SIZE, | 2225 | if (!skb) |
2154 | GFP_KERNEL); | 2226 | goto error; |
2155 | if (skb_cmd == NULL) | ||
2156 | goto error_cmd; | ||
2157 | |||
2158 | skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); | ||
2159 | 2227 | ||
2160 | rc = pn533_build_tx_frame(dev, skb_cmd, true); | 2228 | switch (dev->device_type) { |
2161 | if (rc) | 2229 | case PN533_DEVICE_PASORI: |
2162 | goto error_frame; | 2230 | if (dev->tgt_active_prot == NFC_PROTO_FELICA) { |
2231 | rc = pn533_send_cmd_direct_async(dev, | ||
2232 | PN533_CMD_IN_COMM_THRU, | ||
2233 | skb, | ||
2234 | pn533_data_exchange_complete, | ||
2235 | dev->cmd_complete_mi_arg); | ||
2163 | 2236 | ||
2164 | skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN + | 2237 | break; |
2165 | PN533_CMD_DATAEXCH_DATA_MAXLEN + | 2238 | } |
2166 | PN533_FRAME_TAIL_SIZE; | 2239 | default: |
2167 | skb_resp = alloc_skb(skb_resp_len, GFP_KERNEL); | 2240 | *skb_put(skb, sizeof(u8)) = 1; /*TG*/ |
2168 | if (!skb_resp) { | ||
2169 | rc = -ENOMEM; | ||
2170 | goto error_frame; | ||
2171 | } | ||
2172 | 2241 | ||
2173 | in_frame = (struct pn533_frame *) skb_resp->data; | 2242 | rc = pn533_send_cmd_direct_async(dev, |
2174 | out_frame = (struct pn533_frame *) skb_cmd->data; | 2243 | PN533_CMD_IN_DATA_EXCHANGE, |
2244 | skb, | ||
2245 | pn533_data_exchange_complete, | ||
2246 | dev->cmd_complete_mi_arg); | ||
2175 | 2247 | ||
2176 | arg->skb_resp = skb_resp; | 2248 | break; |
2177 | arg->skb_out = skb_cmd; | 2249 | } |
2178 | 2250 | ||
2179 | rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, | 2251 | if (rc == 0) /* success */ |
2180 | skb_resp_len, | ||
2181 | pn533_data_exchange_complete, | ||
2182 | dev->cmd_complete_arg, GFP_KERNEL); | ||
2183 | if (!rc) | ||
2184 | return; | 2252 | return; |
2185 | 2253 | ||
2186 | nfc_dev_err(&dev->interface->dev, "Error %d when trying to" | 2254 | nfc_dev_err(&dev->interface->dev, |
2187 | " perform data_exchange", rc); | 2255 | "Error %d when trying to perform data_exchange", rc); |
2188 | |||
2189 | kfree_skb(skb_resp); | ||
2190 | 2256 | ||
2191 | error_frame: | 2257 | dev_kfree_skb(skb); |
2192 | kfree_skb(skb_cmd); | 2258 | kfree(dev->cmd_complete_arg); |
2193 | 2259 | ||
2194 | error_cmd: | 2260 | error: |
2195 | pn533_send_ack(dev, GFP_KERNEL); | 2261 | pn533_send_ack(dev, GFP_KERNEL); |
2196 | |||
2197 | kfree(arg); | ||
2198 | |||
2199 | queue_work(dev->wq, &dev->cmd_work); | 2262 | queue_work(dev->wq, &dev->cmd_work); |
2200 | } | 2263 | } |
2201 | 2264 | ||
2202 | static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, | 2265 | static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, |
2203 | u8 cfgdata_len) | 2266 | u8 cfgdata_len) |
2204 | { | 2267 | { |
2205 | int rc; | 2268 | struct sk_buff *skb; |
2206 | u8 *params; | 2269 | struct sk_buff *resp; |
2270 | |||
2271 | int skb_len; | ||
2207 | 2272 | ||
2208 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2273 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
2209 | 2274 | ||
2210 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_RF_CONFIGURATION); | 2275 | skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */ |
2211 | 2276 | ||
2212 | params = PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame); | 2277 | skb = pn533_alloc_skb(dev, skb_len); |
2213 | params[0] = cfgitem; | 2278 | if (!skb) |
2214 | memcpy(¶ms[1], cfgdata, cfgdata_len); | 2279 | return -ENOMEM; |
2215 | dev->out_frame->datalen += (1 + cfgdata_len); | ||
2216 | 2280 | ||
2217 | pn533_tx_frame_finish(dev->out_frame); | 2281 | *skb_put(skb, sizeof(cfgitem)) = cfgitem; |
2282 | memcpy(skb_put(skb, cfgdata_len), cfgdata, cfgdata_len); | ||
2218 | 2283 | ||
2219 | rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, | 2284 | resp = pn533_send_cmd_sync(dev, PN533_CMD_RF_CONFIGURATION, skb); |
2220 | dev->in_maxlen); | 2285 | if (IS_ERR(resp)) |
2286 | return PTR_ERR(resp); | ||
2221 | 2287 | ||
2222 | return rc; | 2288 | dev_kfree_skb(resp); |
2289 | return 0; | ||
2290 | } | ||
2291 | |||
2292 | static int pn533_get_firmware_version(struct pn533 *dev, | ||
2293 | struct pn533_fw_version *fv) | ||
2294 | { | ||
2295 | struct sk_buff *skb; | ||
2296 | struct sk_buff *resp; | ||
2297 | |||
2298 | skb = pn533_alloc_skb(dev, 0); | ||
2299 | if (!skb) | ||
2300 | return -ENOMEM; | ||
2301 | |||
2302 | resp = pn533_send_cmd_sync(dev, PN533_CMD_GET_FIRMWARE_VERSION, skb); | ||
2303 | if (IS_ERR(resp)) | ||
2304 | return PTR_ERR(resp); | ||
2305 | |||
2306 | fv->ic = resp->data[0]; | ||
2307 | fv->ver = resp->data[1]; | ||
2308 | fv->rev = resp->data[2]; | ||
2309 | fv->support = resp->data[3]; | ||
2310 | |||
2311 | dev_kfree_skb(resp); | ||
2312 | return 0; | ||
2223 | } | 2313 | } |
2224 | 2314 | ||
2225 | static int pn533_fw_reset(struct pn533 *dev) | 2315 | static int pn533_fw_reset(struct pn533 *dev) |
2226 | { | 2316 | { |
2227 | int rc; | 2317 | struct sk_buff *skb; |
2228 | u8 *params; | 2318 | struct sk_buff *resp; |
2229 | 2319 | ||
2230 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | 2320 | nfc_dev_dbg(&dev->interface->dev, "%s", __func__); |
2231 | 2321 | ||
2232 | pn533_tx_frame_init(dev->out_frame, 0x18); | 2322 | skb = pn533_alloc_skb(dev, sizeof(u8)); |
2323 | if (!skb) | ||
2324 | return -ENOMEM; | ||
2233 | 2325 | ||
2234 | params = PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame); | 2326 | *skb_put(skb, sizeof(u8)) = 0x1; |
2235 | params[0] = 0x1; | ||
2236 | dev->out_frame->datalen += 1; | ||
2237 | 2327 | ||
2238 | pn533_tx_frame_finish(dev->out_frame); | 2328 | resp = pn533_send_cmd_sync(dev, 0x18, skb); |
2329 | if (IS_ERR(resp)) | ||
2330 | return PTR_ERR(resp); | ||
2239 | 2331 | ||
2240 | rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, | 2332 | dev_kfree_skb(resp); |
2241 | dev->in_maxlen); | ||
2242 | 2333 | ||
2243 | return rc; | 2334 | return 0; |
2244 | } | 2335 | } |
2245 | 2336 | ||
2246 | static struct nfc_ops pn533_nfc_ops = { | 2337 | static struct nfc_ops pn533_nfc_ops = { |
@@ -2337,7 +2428,7 @@ static int pn533_setup(struct pn533 *dev) | |||
2337 | static int pn533_probe(struct usb_interface *interface, | 2428 | static int pn533_probe(struct usb_interface *interface, |
2338 | const struct usb_device_id *id) | 2429 | const struct usb_device_id *id) |
2339 | { | 2430 | { |
2340 | struct pn533_fw_version *fw_ver; | 2431 | struct pn533_fw_version fw_ver; |
2341 | struct pn533 *dev; | 2432 | struct pn533 *dev; |
2342 | struct usb_host_interface *iface_desc; | 2433 | struct usb_host_interface *iface_desc; |
2343 | struct usb_endpoint_descriptor *endpoint; | 2434 | struct usb_endpoint_descriptor *endpoint; |
@@ -2359,41 +2450,32 @@ static int pn533_probe(struct usb_interface *interface, | |||
2359 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 2450 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { |
2360 | endpoint = &iface_desc->endpoint[i].desc; | 2451 | endpoint = &iface_desc->endpoint[i].desc; |
2361 | 2452 | ||
2362 | if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) { | 2453 | if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) |
2363 | dev->in_maxlen = le16_to_cpu(endpoint->wMaxPacketSize); | ||
2364 | in_endpoint = endpoint->bEndpointAddress; | 2454 | in_endpoint = endpoint->bEndpointAddress; |
2365 | } | ||
2366 | 2455 | ||
2367 | if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) { | 2456 | if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) |
2368 | dev->out_maxlen = | ||
2369 | le16_to_cpu(endpoint->wMaxPacketSize); | ||
2370 | out_endpoint = endpoint->bEndpointAddress; | 2457 | out_endpoint = endpoint->bEndpointAddress; |
2371 | } | ||
2372 | } | 2458 | } |
2373 | 2459 | ||
2374 | if (!in_endpoint || !out_endpoint) { | 2460 | if (!in_endpoint || !out_endpoint) { |
2375 | nfc_dev_err(&interface->dev, "Could not find bulk-in or" | 2461 | nfc_dev_err(&interface->dev, |
2376 | " bulk-out endpoint"); | 2462 | "Could not find bulk-in or bulk-out endpoint"); |
2377 | rc = -ENODEV; | 2463 | rc = -ENODEV; |
2378 | goto error; | 2464 | goto error; |
2379 | } | 2465 | } |
2380 | 2466 | ||
2381 | dev->in_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); | ||
2382 | dev->in_urb = usb_alloc_urb(0, GFP_KERNEL); | 2467 | dev->in_urb = usb_alloc_urb(0, GFP_KERNEL); |
2383 | dev->out_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); | ||
2384 | dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); | 2468 | dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); |
2385 | 2469 | ||
2386 | if (!dev->in_frame || !dev->out_frame || | 2470 | if (!dev->in_urb || !dev->out_urb) |
2387 | !dev->in_urb || !dev->out_urb) | ||
2388 | goto error; | 2471 | goto error; |
2389 | 2472 | ||
2390 | usb_fill_bulk_urb(dev->in_urb, dev->udev, | 2473 | usb_fill_bulk_urb(dev->in_urb, dev->udev, |
2391 | usb_rcvbulkpipe(dev->udev, in_endpoint), | 2474 | usb_rcvbulkpipe(dev->udev, in_endpoint), |
2392 | NULL, 0, NULL, dev); | 2475 | NULL, 0, NULL, dev); |
2393 | usb_fill_bulk_urb(dev->out_urb, dev->udev, | 2476 | usb_fill_bulk_urb(dev->out_urb, dev->udev, |
2394 | usb_sndbulkpipe(dev->udev, out_endpoint), | 2477 | usb_sndbulkpipe(dev->udev, out_endpoint), |
2395 | NULL, 0, | 2478 | NULL, 0, pn533_send_complete, dev); |
2396 | pn533_send_complete, dev); | ||
2397 | 2479 | ||
2398 | INIT_WORK(&dev->cmd_work, pn533_wq_cmd); | 2480 | INIT_WORK(&dev->cmd_work, pn533_wq_cmd); |
2399 | INIT_WORK(&dev->cmd_complete_work, pn533_wq_cmd_complete); | 2481 | INIT_WORK(&dev->cmd_complete_work, pn533_wq_cmd_complete); |
@@ -2414,18 +2496,7 @@ static int pn533_probe(struct usb_interface *interface, | |||
2414 | 2496 | ||
2415 | usb_set_intfdata(interface, dev); | 2497 | usb_set_intfdata(interface, dev); |
2416 | 2498 | ||
2417 | pn533_tx_frame_init(dev->out_frame, PN533_CMD_GET_FIRMWARE_VERSION); | 2499 | dev->ops = &pn533_std_frame_ops; |
2418 | pn533_tx_frame_finish(dev->out_frame); | ||
2419 | |||
2420 | rc = pn533_send_cmd_frame_sync(dev, dev->out_frame, dev->in_frame, | ||
2421 | dev->in_maxlen); | ||
2422 | if (rc) | ||
2423 | goto destroy_wq; | ||
2424 | |||
2425 | fw_ver = (struct pn533_fw_version *) | ||
2426 | PN533_FRAME_CMD_PARAMS_PTR(dev->in_frame); | ||
2427 | nfc_dev_info(&dev->interface->dev, "NXP PN533 firmware ver %d.%d now" | ||
2428 | " attached", fw_ver->ver, fw_ver->rev); | ||
2429 | 2500 | ||
2430 | dev->device_type = id->driver_info; | 2501 | dev->device_type = id->driver_info; |
2431 | switch (dev->device_type) { | 2502 | switch (dev->device_type) { |
@@ -2444,9 +2515,21 @@ static int pn533_probe(struct usb_interface *interface, | |||
2444 | goto destroy_wq; | 2515 | goto destroy_wq; |
2445 | } | 2516 | } |
2446 | 2517 | ||
2518 | memset(&fw_ver, 0, sizeof(fw_ver)); | ||
2519 | rc = pn533_get_firmware_version(dev, &fw_ver); | ||
2520 | if (rc < 0) | ||
2521 | goto destroy_wq; | ||
2522 | |||
2523 | nfc_dev_info(&dev->interface->dev, | ||
2524 | "NXP PN533 firmware ver %d.%d now attached", | ||
2525 | fw_ver.ver, fw_ver.rev); | ||
2526 | |||
2527 | |||
2447 | dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, | 2528 | dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, |
2529 | NFC_SE_NONE, | ||
2530 | dev->ops->tx_header_len + | ||
2448 | PN533_CMD_DATAEXCH_HEAD_LEN, | 2531 | PN533_CMD_DATAEXCH_HEAD_LEN, |
2449 | PN533_FRAME_TAIL_SIZE); | 2532 | dev->ops->tx_tail_len); |
2450 | if (!dev->nfc_dev) | 2533 | if (!dev->nfc_dev) |
2451 | goto destroy_wq; | 2534 | goto destroy_wq; |
2452 | 2535 | ||
@@ -2472,9 +2555,7 @@ free_nfc_dev: | |||
2472 | destroy_wq: | 2555 | destroy_wq: |
2473 | destroy_workqueue(dev->wq); | 2556 | destroy_workqueue(dev->wq); |
2474 | error: | 2557 | error: |
2475 | kfree(dev->in_frame); | ||
2476 | usb_free_urb(dev->in_urb); | 2558 | usb_free_urb(dev->in_urb); |
2477 | kfree(dev->out_frame); | ||
2478 | usb_free_urb(dev->out_urb); | 2559 | usb_free_urb(dev->out_urb); |
2479 | kfree(dev); | 2560 | kfree(dev); |
2480 | return rc; | 2561 | return rc; |
@@ -2505,9 +2586,7 @@ static void pn533_disconnect(struct usb_interface *interface) | |||
2505 | kfree(cmd); | 2586 | kfree(cmd); |
2506 | } | 2587 | } |
2507 | 2588 | ||
2508 | kfree(dev->in_frame); | ||
2509 | usb_free_urb(dev->in_urb); | 2589 | usb_free_urb(dev->in_urb); |
2510 | kfree(dev->out_frame); | ||
2511 | usb_free_urb(dev->out_urb); | 2590 | usb_free_urb(dev->out_urb); |
2512 | kfree(dev); | 2591 | kfree(dev); |
2513 | 2592 | ||
diff --git a/drivers/nfc/pn544/Kconfig b/drivers/nfc/pn544/Kconfig new file mode 100644 index 000000000000..c277790ac71c --- /dev/null +++ b/drivers/nfc/pn544/Kconfig | |||
@@ -0,0 +1,23 @@ | |||
1 | config NFC_PN544 | ||
2 | tristate "NXP PN544 NFC driver" | ||
3 | depends on NFC_HCI | ||
4 | select CRC_CCITT | ||
5 | default n | ||
6 | ---help--- | ||
7 | NXP PN544 core driver. | ||
8 | This is a driver based on the HCI NFC kernel layers and | ||
9 | will thus not work with NXP libnfc library. | ||
10 | |||
11 | To compile this driver as a module, choose m here. The module will | ||
12 | be called pn544. | ||
13 | Say N if unsure. | ||
14 | |||
15 | config NFC_PN544_I2C | ||
16 | tristate "NFC PN544 i2c support" | ||
17 | depends on NFC_PN544 && I2C && NFC_SHDLC | ||
18 | ---help--- | ||
19 | This module adds support for the NXP pn544 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 pn544_i2c. | ||
23 | Say N if unsure. \ No newline at end of file | ||
diff --git a/drivers/nfc/pn544/Makefile b/drivers/nfc/pn544/Makefile index 725733881eb3..ac076793687d 100644 --- a/drivers/nfc/pn544/Makefile +++ b/drivers/nfc/pn544/Makefile | |||
@@ -2,6 +2,7 @@ | |||
2 | # Makefile for PN544 HCI based NFC driver | 2 | # Makefile for PN544 HCI based NFC driver |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PN544_HCI_NFC) += pn544_i2c.o | 5 | pn544_i2c-objs = i2c.o |
6 | 6 | ||
7 | pn544_i2c-y := pn544.o i2c.o | 7 | obj-$(CONFIG_NFC_PN544) += pn544.o |
8 | obj-$(CONFIG_NFC_PN544_I2C) += pn544_i2c.o | ||
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index 2a9c8d93d2e8..8cf64c19f022 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c | |||
@@ -376,12 +376,12 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, | |||
376 | return -ENODEV; | 376 | return -ENODEV; |
377 | } | 377 | } |
378 | 378 | ||
379 | phy = kzalloc(sizeof(struct pn544_i2c_phy), GFP_KERNEL); | 379 | phy = devm_kzalloc(&client->dev, sizeof(struct pn544_i2c_phy), |
380 | GFP_KERNEL); | ||
380 | if (!phy) { | 381 | if (!phy) { |
381 | dev_err(&client->dev, | 382 | dev_err(&client->dev, |
382 | "Cannot allocate memory for pn544 i2c phy.\n"); | 383 | "Cannot allocate memory for pn544 i2c phy.\n"); |
383 | r = -ENOMEM; | 384 | return -ENOMEM; |
384 | goto err_phy_alloc; | ||
385 | } | 385 | } |
386 | 386 | ||
387 | phy->i2c_dev = client; | 387 | phy->i2c_dev = client; |
@@ -390,20 +390,18 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, | |||
390 | pdata = client->dev.platform_data; | 390 | pdata = client->dev.platform_data; |
391 | if (pdata == NULL) { | 391 | if (pdata == NULL) { |
392 | dev_err(&client->dev, "No platform data\n"); | 392 | dev_err(&client->dev, "No platform data\n"); |
393 | r = -EINVAL; | 393 | return -EINVAL; |
394 | goto err_pdata; | ||
395 | } | 394 | } |
396 | 395 | ||
397 | if (pdata->request_resources == NULL) { | 396 | if (pdata->request_resources == NULL) { |
398 | dev_err(&client->dev, "request_resources() missing\n"); | 397 | dev_err(&client->dev, "request_resources() missing\n"); |
399 | r = -EINVAL; | 398 | return -EINVAL; |
400 | goto err_pdata; | ||
401 | } | 399 | } |
402 | 400 | ||
403 | r = pdata->request_resources(client); | 401 | r = pdata->request_resources(client); |
404 | if (r) { | 402 | if (r) { |
405 | dev_err(&client->dev, "Cannot get platform resources\n"); | 403 | dev_err(&client->dev, "Cannot get platform resources\n"); |
406 | goto err_pdata; | 404 | return r; |
407 | } | 405 | } |
408 | 406 | ||
409 | phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); | 407 | phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); |
@@ -435,10 +433,6 @@ err_rti: | |||
435 | if (pdata->free_resources != NULL) | 433 | if (pdata->free_resources != NULL) |
436 | pdata->free_resources(); | 434 | pdata->free_resources(); |
437 | 435 | ||
438 | err_pdata: | ||
439 | kfree(phy); | ||
440 | |||
441 | err_phy_alloc: | ||
442 | return r; | 436 | return r; |
443 | } | 437 | } |
444 | 438 | ||
@@ -458,8 +452,6 @@ static int pn544_hci_i2c_remove(struct i2c_client *client) | |||
458 | if (pdata->free_resources) | 452 | if (pdata->free_resources) |
459 | pdata->free_resources(); | 453 | pdata->free_resources(); |
460 | 454 | ||
461 | kfree(phy); | ||
462 | |||
463 | return 0; | 455 | return 0; |
464 | } | 456 | } |
465 | 457 | ||
@@ -472,29 +464,7 @@ static struct i2c_driver pn544_hci_i2c_driver = { | |||
472 | .remove = pn544_hci_i2c_remove, | 464 | .remove = pn544_hci_i2c_remove, |
473 | }; | 465 | }; |
474 | 466 | ||
475 | static int __init pn544_hci_i2c_init(void) | 467 | module_i2c_driver(pn544_hci_i2c_driver); |
476 | { | ||
477 | int r; | ||
478 | |||
479 | pr_debug(DRIVER_DESC ": %s\n", __func__); | ||
480 | |||
481 | r = i2c_add_driver(&pn544_hci_i2c_driver); | ||
482 | if (r) { | ||
483 | pr_err(PN544_HCI_I2C_DRIVER_NAME | ||
484 | ": driver registration failed\n"); | ||
485 | return r; | ||
486 | } | ||
487 | |||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | static void __exit pn544_hci_i2c_exit(void) | ||
492 | { | ||
493 | i2c_del_driver(&pn544_hci_i2c_driver); | ||
494 | } | ||
495 | |||
496 | module_init(pn544_hci_i2c_init); | ||
497 | module_exit(pn544_hci_i2c_exit); | ||
498 | 468 | ||
499 | MODULE_LICENSE("GPL"); | 469 | MODULE_LICENSE("GPL"); |
500 | MODULE_DESCRIPTION(DRIVER_DESC); | 470 | MODULE_DESCRIPTION(DRIVER_DESC); |
diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index cc666de3b8e5..9c5f16e7baef 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/module.h> | ||
23 | 24 | ||
24 | #include <linux/nfc.h> | 25 | #include <linux/nfc.h> |
25 | #include <net/nfc/hci.h> | 26 | #include <net/nfc/hci.h> |
@@ -675,11 +676,17 @@ static int pn544_hci_im_transceive(struct nfc_hci_dev *hdev, | |||
675 | 676 | ||
676 | static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) | 677 | static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) |
677 | { | 678 | { |
679 | int r; | ||
680 | |||
678 | /* Set default false for multiple information chaining */ | 681 | /* Set default false for multiple information chaining */ |
679 | *skb_push(skb, 1) = 0; | 682 | *skb_push(skb, 1) = 0; |
680 | 683 | ||
681 | return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | 684 | r = nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, |
682 | PN544_HCI_EVT_SND_DATA, skb->data, skb->len); | 685 | PN544_HCI_EVT_SND_DATA, skb->data, skb->len); |
686 | |||
687 | kfree_skb(skb); | ||
688 | |||
689 | return r; | ||
683 | } | 690 | } |
684 | 691 | ||
685 | static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, | 692 | static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, |
@@ -714,35 +721,40 @@ static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, | |||
714 | return 0; | 721 | return 0; |
715 | } | 722 | } |
716 | 723 | ||
717 | static void pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, | 724 | /* |
718 | u8 event, struct sk_buff *skb) | 725 | * Returns: |
726 | * <= 0: driver handled the event, skb consumed | ||
727 | * 1: driver does not handle the event, please do standard processing | ||
728 | */ | ||
729 | static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, | ||
730 | struct sk_buff *skb) | ||
719 | { | 731 | { |
720 | struct sk_buff *rgb_skb = NULL; | 732 | struct sk_buff *rgb_skb = NULL; |
721 | int r = 0; | 733 | int r; |
722 | 734 | ||
723 | pr_debug("hci event %d", event); | 735 | pr_debug("hci event %d", event); |
724 | switch (event) { | 736 | switch (event) { |
725 | case PN544_HCI_EVT_ACTIVATED: | 737 | case PN544_HCI_EVT_ACTIVATED: |
726 | if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) | 738 | if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) { |
727 | nfc_hci_target_discovered(hdev, gate); | 739 | r = nfc_hci_target_discovered(hdev, gate); |
728 | else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) { | 740 | } else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) { |
729 | r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ, | 741 | r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ, |
730 | &rgb_skb); | 742 | &rgb_skb); |
731 | |||
732 | if (r < 0) | 743 | if (r < 0) |
733 | goto exit; | 744 | goto exit; |
734 | 745 | ||
735 | nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, | 746 | r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, |
736 | NFC_COMM_PASSIVE, rgb_skb->data, | 747 | NFC_COMM_PASSIVE, rgb_skb->data, |
737 | rgb_skb->len); | 748 | rgb_skb->len); |
738 | 749 | ||
739 | kfree_skb(rgb_skb); | 750 | kfree_skb(rgb_skb); |
751 | } else { | ||
752 | r = -EINVAL; | ||
740 | } | 753 | } |
741 | |||
742 | break; | 754 | break; |
743 | case PN544_HCI_EVT_DEACTIVATED: | 755 | case PN544_HCI_EVT_DEACTIVATED: |
744 | nfc_hci_send_event(hdev, gate, | 756 | r = nfc_hci_send_event(hdev, gate, NFC_HCI_EVT_END_OPERATION, |
745 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | 757 | NULL, 0); |
746 | break; | 758 | break; |
747 | case PN544_HCI_EVT_RCV_DATA: | 759 | case PN544_HCI_EVT_RCV_DATA: |
748 | if (skb->len < 2) { | 760 | if (skb->len < 2) { |
@@ -757,15 +769,15 @@ static void pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, | |||
757 | } | 769 | } |
758 | 770 | ||
759 | skb_pull(skb, 2); | 771 | skb_pull(skb, 2); |
760 | nfc_tm_data_received(hdev->ndev, skb); | 772 | return nfc_tm_data_received(hdev->ndev, skb); |
761 | |||
762 | return; | ||
763 | default: | 773 | default: |
764 | break; | 774 | return 1; |
765 | } | 775 | } |
766 | 776 | ||
767 | exit: | 777 | exit: |
768 | kfree_skb(skb); | 778 | kfree_skb(skb); |
779 | |||
780 | return r; | ||
769 | } | 781 | } |
770 | 782 | ||
771 | static struct nfc_hci_ops pn544_hci_ops = { | 783 | static struct nfc_hci_ops pn544_hci_ops = { |
@@ -789,7 +801,7 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | |||
789 | struct nfc_hci_dev **hdev) | 801 | struct nfc_hci_dev **hdev) |
790 | { | 802 | { |
791 | struct pn544_hci_info *info; | 803 | struct pn544_hci_info *info; |
792 | u32 protocols; | 804 | u32 protocols, se; |
793 | struct nfc_hci_init_data init_data; | 805 | struct nfc_hci_init_data init_data; |
794 | int r; | 806 | int r; |
795 | 807 | ||
@@ -822,8 +834,10 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | |||
822 | NFC_PROTO_ISO14443_B_MASK | | 834 | NFC_PROTO_ISO14443_B_MASK | |
823 | NFC_PROTO_NFC_DEP_MASK; | 835 | NFC_PROTO_NFC_DEP_MASK; |
824 | 836 | ||
825 | info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, | 837 | se = NFC_SE_UICC | NFC_SE_EMBEDDED; |
826 | protocols, llc_name, | 838 | |
839 | info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, 0, | ||
840 | protocols, se, llc_name, | ||
827 | phy_headroom + PN544_CMDS_HEADROOM, | 841 | phy_headroom + PN544_CMDS_HEADROOM, |
828 | phy_tailroom, phy_payload); | 842 | phy_tailroom, phy_payload); |
829 | if (!info->hdev) { | 843 | if (!info->hdev) { |
@@ -851,6 +865,7 @@ err_alloc_hdev: | |||
851 | err_info_alloc: | 865 | err_info_alloc: |
852 | return r; | 866 | return r; |
853 | } | 867 | } |
868 | EXPORT_SYMBOL(pn544_hci_probe); | ||
854 | 869 | ||
855 | void pn544_hci_remove(struct nfc_hci_dev *hdev) | 870 | void pn544_hci_remove(struct nfc_hci_dev *hdev) |
856 | { | 871 | { |
@@ -860,3 +875,7 @@ void pn544_hci_remove(struct nfc_hci_dev *hdev) | |||
860 | nfc_hci_free_device(hdev); | 875 | nfc_hci_free_device(hdev); |
861 | kfree(info); | 876 | kfree(info); |
862 | } | 877 | } |
878 | EXPORT_SYMBOL(pn544_hci_remove); | ||
879 | |||
880 | MODULE_LICENSE("GPL"); | ||
881 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index 5d6f2ec1c705..5ff3a4f19443 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig | |||
@@ -136,6 +136,11 @@ config SSB_DRIVER_MIPS | |||
136 | 136 | ||
137 | If unsure, say N | 137 | If unsure, say N |
138 | 138 | ||
139 | config SSB_SFLASH | ||
140 | bool "SSB serial flash support" | ||
141 | depends on SSB_DRIVER_MIPS && BROKEN | ||
142 | default y | ||
143 | |||
139 | # Assumption: We are on embedded, if we compile the MIPS core. | 144 | # Assumption: We are on embedded, if we compile the MIPS core. |
140 | config SSB_EMBEDDED | 145 | config SSB_EMBEDDED |
141 | bool | 146 | bool |
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile index 9159ba77c388..b1ddc116d387 100644 --- a/drivers/ssb/Makefile +++ b/drivers/ssb/Makefile | |||
@@ -11,6 +11,7 @@ ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o | |||
11 | # built-in drivers | 11 | # built-in drivers |
12 | ssb-y += driver_chipcommon.o | 12 | ssb-y += driver_chipcommon.o |
13 | ssb-y += driver_chipcommon_pmu.o | 13 | ssb-y += driver_chipcommon_pmu.o |
14 | ssb-$(CONFIG_SSB_SFLASH) += driver_chipcommon_sflash.o | ||
14 | ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o | 15 | ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o |
15 | ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o | 16 | ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o |
16 | ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o | 17 | ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o |
diff --git a/drivers/ssb/driver_chipcommon_sflash.c b/drivers/ssb/driver_chipcommon_sflash.c new file mode 100644 index 000000000000..720665ca2bb1 --- /dev/null +++ b/drivers/ssb/driver_chipcommon_sflash.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * ChipCommon serial flash interface | ||
4 | * | ||
5 | * Licensed under the GNU/GPL. See COPYING for details. | ||
6 | */ | ||
7 | |||
8 | #include <linux/ssb/ssb.h> | ||
9 | |||
10 | #include "ssb_private.h" | ||
11 | |||
12 | struct ssb_sflash_tbl_e { | ||
13 | char *name; | ||
14 | u32 id; | ||
15 | u32 blocksize; | ||
16 | u16 numblocks; | ||
17 | }; | ||
18 | |||
19 | static struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { | ||
20 | { "M25P20", 0x11, 0x10000, 4, }, | ||
21 | { "M25P40", 0x12, 0x10000, 8, }, | ||
22 | |||
23 | { "M25P16", 0x14, 0x10000, 32, }, | ||
24 | { "M25P32", 0x15, 0x10000, 64, }, | ||
25 | { "M25P64", 0x16, 0x10000, 128, }, | ||
26 | { "M25FL128", 0x17, 0x10000, 256, }, | ||
27 | { 0 }, | ||
28 | }; | ||
29 | |||
30 | static struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { | ||
31 | { "SST25WF512", 1, 0x1000, 16, }, | ||
32 | { "SST25VF512", 0x48, 0x1000, 16, }, | ||
33 | { "SST25WF010", 2, 0x1000, 32, }, | ||
34 | { "SST25VF010", 0x49, 0x1000, 32, }, | ||
35 | { "SST25WF020", 3, 0x1000, 64, }, | ||
36 | { "SST25VF020", 0x43, 0x1000, 64, }, | ||
37 | { "SST25WF040", 4, 0x1000, 128, }, | ||
38 | { "SST25VF040", 0x44, 0x1000, 128, }, | ||
39 | { "SST25VF040B", 0x8d, 0x1000, 128, }, | ||
40 | { "SST25WF080", 5, 0x1000, 256, }, | ||
41 | { "SST25VF080B", 0x8e, 0x1000, 256, }, | ||
42 | { "SST25VF016", 0x41, 0x1000, 512, }, | ||
43 | { "SST25VF032", 0x4a, 0x1000, 1024, }, | ||
44 | { "SST25VF064", 0x4b, 0x1000, 2048, }, | ||
45 | { 0 }, | ||
46 | }; | ||
47 | |||
48 | static struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { | ||
49 | { "AT45DB011", 0xc, 256, 512, }, | ||
50 | { "AT45DB021", 0x14, 256, 1024, }, | ||
51 | { "AT45DB041", 0x1c, 256, 2048, }, | ||
52 | { "AT45DB081", 0x24, 256, 4096, }, | ||
53 | { "AT45DB161", 0x2c, 512, 4096, }, | ||
54 | { "AT45DB321", 0x34, 512, 8192, }, | ||
55 | { "AT45DB642", 0x3c, 1024, 8192, }, | ||
56 | { 0 }, | ||
57 | }; | ||
58 | |||
59 | static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) | ||
60 | { | ||
61 | int i; | ||
62 | chipco_write32(cc, SSB_CHIPCO_FLASHCTL, | ||
63 | SSB_CHIPCO_FLASHCTL_START | opcode); | ||
64 | for (i = 0; i < 1000; i++) { | ||
65 | if (!(chipco_read32(cc, SSB_CHIPCO_FLASHCTL) & | ||
66 | SSB_CHIPCO_FLASHCTL_BUSY)) | ||
67 | return; | ||
68 | cpu_relax(); | ||
69 | } | ||
70 | pr_err("SFLASH control command failed (timeout)!\n"); | ||
71 | } | ||
72 | |||
73 | /* Initialize serial flash access */ | ||
74 | int ssb_sflash_init(struct ssb_chipcommon *cc) | ||
75 | { | ||
76 | struct ssb_sflash_tbl_e *e; | ||
77 | u32 id, id2; | ||
78 | |||
79 | switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { | ||
80 | case SSB_CHIPCO_FLASHT_STSER: | ||
81 | ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_DP); | ||
82 | |||
83 | chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 0); | ||
84 | ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); | ||
85 | id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); | ||
86 | |||
87 | chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 1); | ||
88 | ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); | ||
89 | id2 = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); | ||
90 | |||
91 | switch (id) { | ||
92 | case 0xbf: | ||
93 | for (e = ssb_sflash_sst_tbl; e->name; e++) { | ||
94 | if (e->id == id2) | ||
95 | break; | ||
96 | } | ||
97 | break; | ||
98 | case 0x13: | ||
99 | return -ENOTSUPP; | ||
100 | default: | ||
101 | for (e = ssb_sflash_st_tbl; e->name; e++) { | ||
102 | if (e->id == id) | ||
103 | break; | ||
104 | } | ||
105 | break; | ||
106 | } | ||
107 | if (!e->name) { | ||
108 | pr_err("Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", | ||
109 | id, id2); | ||
110 | return -ENOTSUPP; | ||
111 | } | ||
112 | |||
113 | break; | ||
114 | case SSB_CHIPCO_FLASHT_ATSER: | ||
115 | ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_STATUS); | ||
116 | id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA) & 0x3c; | ||
117 | |||
118 | for (e = ssb_sflash_at_tbl; e->name; e++) { | ||
119 | if (e->id == id) | ||
120 | break; | ||
121 | } | ||
122 | if (!e->name) { | ||
123 | pr_err("Unsupported Atmel serial flash (id: 0x%X)\n", | ||
124 | id); | ||
125 | return -ENOTSUPP; | ||
126 | } | ||
127 | |||
128 | break; | ||
129 | default: | ||
130 | pr_err("Unsupported flash type\n"); | ||
131 | return -ENOTSUPP; | ||
132 | } | ||
133 | |||
134 | pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", | ||
135 | e->name, e->blocksize, e->numblocks); | ||
136 | |||
137 | pr_err("Serial flash support is not implemented yet!\n"); | ||
138 | |||
139 | return -ENOTSUPP; | ||
140 | } | ||
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 5bd05b136d22..2a7684c90243 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c | |||
@@ -203,7 +203,8 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) | |||
203 | switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) { | 203 | switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) { |
204 | case SSB_CHIPCO_FLASHT_STSER: | 204 | case SSB_CHIPCO_FLASHT_STSER: |
205 | case SSB_CHIPCO_FLASHT_ATSER: | 205 | case SSB_CHIPCO_FLASHT_ATSER: |
206 | pr_err("Serial flash not supported\n"); | 206 | pr_debug("Found serial flash\n"); |
207 | ssb_sflash_init(&bus->chipco); | ||
207 | break; | 208 | break; |
208 | case SSB_CHIPCO_FLASHT_PARA: | 209 | case SSB_CHIPCO_FLASHT_PARA: |
209 | pr_debug("Found parallel flash\n"); | 210 | pr_debug("Found parallel flash\n"); |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 6c10b66c796c..77d942630750 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -217,6 +217,17 @@ extern u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, | |||
217 | u32 ticks); | 217 | u32 ticks); |
218 | extern u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms); | 218 | extern u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms); |
219 | 219 | ||
220 | /* driver_chipcommon_sflash.c */ | ||
221 | #ifdef CONFIG_SSB_SFLASH | ||
222 | int ssb_sflash_init(struct ssb_chipcommon *cc); | ||
223 | #else | ||
224 | static inline int ssb_sflash_init(struct ssb_chipcommon *cc) | ||
225 | { | ||
226 | pr_err("Serial flash not supported\n"); | ||
227 | return 0; | ||
228 | } | ||
229 | #endif /* CONFIG_SSB_SFLASH */ | ||
230 | |||
220 | #ifdef CONFIG_SSB_DRIVER_EXTIF | 231 | #ifdef CONFIG_SSB_DRIVER_EXTIF |
221 | extern u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks); | 232 | extern u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks); |
222 | extern u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms); | 233 | extern u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms); |
diff --git a/include/linux/bcma/bcma_driver_mips.h b/include/linux/bcma/bcma_driver_mips.h index 0baf8a56b794..0d1ea297851a 100644 --- a/include/linux/bcma/bcma_driver_mips.h +++ b/include/linux/bcma/bcma_driver_mips.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #define BCMA_MIPS_MIPS74K_GPIOEN 0x0048 | 28 | #define BCMA_MIPS_MIPS74K_GPIOEN 0x0048 |
29 | #define BCMA_MIPS_MIPS74K_CLKCTLST 0x01E0 | 29 | #define BCMA_MIPS_MIPS74K_CLKCTLST 0x01E0 |
30 | 30 | ||
31 | #define BCMA_MIPS_OOBSELINA74 0x004 | ||
31 | #define BCMA_MIPS_OOBSELOUTA30 0x100 | 32 | #define BCMA_MIPS_OOBSELOUTA30 0x100 |
32 | 33 | ||
33 | struct bcma_device; | 34 | struct bcma_device; |
@@ -36,7 +37,6 @@ struct bcma_drv_mips { | |||
36 | struct bcma_device *core; | 37 | struct bcma_device *core; |
37 | u8 setup_done:1; | 38 | u8 setup_done:1; |
38 | u8 early_setup_done:1; | 39 | u8 early_setup_done:1; |
39 | unsigned int assigned_irqs; | ||
40 | }; | 40 | }; |
41 | 41 | ||
42 | #ifdef CONFIG_BCMA_DRIVER_MIPS | 42 | #ifdef CONFIG_BCMA_DRIVER_MIPS |
@@ -49,6 +49,6 @@ static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { } | |||
49 | 49 | ||
50 | extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore); | 50 | extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore); |
51 | 51 | ||
52 | extern unsigned int bcma_core_mips_irq(struct bcma_device *dev); | 52 | extern unsigned int bcma_core_irq(struct bcma_device *core); |
53 | 53 | ||
54 | #endif /* LINUX_BCMA_DRIVER_MIPS_H_ */ | 54 | #endif /* LINUX_BCMA_DRIVER_MIPS_H_ */ |
diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h index c48d98d27b77..424760f01b9d 100644 --- a/include/linux/bcma/bcma_driver_pci.h +++ b/include/linux/bcma/bcma_driver_pci.h | |||
@@ -179,6 +179,8 @@ struct pci_dev; | |||
179 | #define BCMA_CORE_PCI_CFG_FUN_MASK 7 /* Function mask */ | 179 | #define BCMA_CORE_PCI_CFG_FUN_MASK 7 /* Function mask */ |
180 | #define BCMA_CORE_PCI_CFG_OFF_MASK 0xfff /* Register mask */ | 180 | #define BCMA_CORE_PCI_CFG_OFF_MASK 0xfff /* Register mask */ |
181 | 181 | ||
182 | #define BCMA_CORE_PCI_CFG_DEVCTRL 0xd8 | ||
183 | |||
182 | /* PCIE Root Capability Register bits (Host mode only) */ | 184 | /* PCIE Root Capability Register bits (Host mode only) */ |
183 | #define BCMA_CORE_PCI_RC_CRS_VISIBILITY 0x0001 | 185 | #define BCMA_CORE_PCI_RC_CRS_VISIBILITY 0x0001 |
184 | 186 | ||
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index f0859cc73861..ccf9ee1dca8c 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -180,7 +180,7 @@ struct ieee80211_hdr { | |||
180 | u8 addr3[6]; | 180 | u8 addr3[6]; |
181 | __le16 seq_ctrl; | 181 | __le16 seq_ctrl; |
182 | u8 addr4[6]; | 182 | u8 addr4[6]; |
183 | } __attribute__ ((packed)); | 183 | } __packed; |
184 | 184 | ||
185 | struct ieee80211_hdr_3addr { | 185 | struct ieee80211_hdr_3addr { |
186 | __le16 frame_control; | 186 | __le16 frame_control; |
@@ -189,7 +189,7 @@ struct ieee80211_hdr_3addr { | |||
189 | u8 addr2[6]; | 189 | u8 addr2[6]; |
190 | u8 addr3[6]; | 190 | u8 addr3[6]; |
191 | __le16 seq_ctrl; | 191 | __le16 seq_ctrl; |
192 | } __attribute__ ((packed)); | 192 | } __packed; |
193 | 193 | ||
194 | struct ieee80211_qos_hdr { | 194 | struct ieee80211_qos_hdr { |
195 | __le16 frame_control; | 195 | __le16 frame_control; |
@@ -199,7 +199,7 @@ struct ieee80211_qos_hdr { | |||
199 | u8 addr3[6]; | 199 | u8 addr3[6]; |
200 | __le16 seq_ctrl; | 200 | __le16 seq_ctrl; |
201 | __le16 qos_ctrl; | 201 | __le16 qos_ctrl; |
202 | } __attribute__ ((packed)); | 202 | } __packed; |
203 | 203 | ||
204 | /** | 204 | /** |
205 | * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set | 205 | * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set |
@@ -576,7 +576,7 @@ struct ieee80211s_hdr { | |||
576 | __le32 seqnum; | 576 | __le32 seqnum; |
577 | u8 eaddr1[6]; | 577 | u8 eaddr1[6]; |
578 | u8 eaddr2[6]; | 578 | u8 eaddr2[6]; |
579 | } __attribute__ ((packed)); | 579 | } __packed; |
580 | 580 | ||
581 | /* Mesh flags */ | 581 | /* Mesh flags */ |
582 | #define MESH_FLAGS_AE_A4 0x1 | 582 | #define MESH_FLAGS_AE_A4 0x1 |
@@ -614,7 +614,7 @@ struct ieee80211_quiet_ie { | |||
614 | u8 period; | 614 | u8 period; |
615 | __le16 duration; | 615 | __le16 duration; |
616 | __le16 offset; | 616 | __le16 offset; |
617 | } __attribute__ ((packed)); | 617 | } __packed; |
618 | 618 | ||
619 | /** | 619 | /** |
620 | * struct ieee80211_msrment_ie | 620 | * struct ieee80211_msrment_ie |
@@ -626,7 +626,7 @@ struct ieee80211_msrment_ie { | |||
626 | u8 mode; | 626 | u8 mode; |
627 | u8 type; | 627 | u8 type; |
628 | u8 request[0]; | 628 | u8 request[0]; |
629 | } __attribute__ ((packed)); | 629 | } __packed; |
630 | 630 | ||
631 | /** | 631 | /** |
632 | * struct ieee80211_channel_sw_ie | 632 | * struct ieee80211_channel_sw_ie |
@@ -637,7 +637,7 @@ struct ieee80211_channel_sw_ie { | |||
637 | u8 mode; | 637 | u8 mode; |
638 | u8 new_ch_num; | 638 | u8 new_ch_num; |
639 | u8 count; | 639 | u8 count; |
640 | } __attribute__ ((packed)); | 640 | } __packed; |
641 | 641 | ||
642 | /** | 642 | /** |
643 | * struct ieee80211_tim | 643 | * struct ieee80211_tim |
@@ -650,7 +650,7 @@ struct ieee80211_tim_ie { | |||
650 | u8 bitmap_ctrl; | 650 | u8 bitmap_ctrl; |
651 | /* variable size: 1 - 251 bytes */ | 651 | /* variable size: 1 - 251 bytes */ |
652 | u8 virtual_map[1]; | 652 | u8 virtual_map[1]; |
653 | } __attribute__ ((packed)); | 653 | } __packed; |
654 | 654 | ||
655 | /** | 655 | /** |
656 | * struct ieee80211_meshconf_ie | 656 | * struct ieee80211_meshconf_ie |
@@ -665,7 +665,7 @@ struct ieee80211_meshconf_ie { | |||
665 | u8 meshconf_auth; | 665 | u8 meshconf_auth; |
666 | u8 meshconf_form; | 666 | u8 meshconf_form; |
667 | u8 meshconf_cap; | 667 | u8 meshconf_cap; |
668 | } __attribute__ ((packed)); | 668 | } __packed; |
669 | 669 | ||
670 | /** | 670 | /** |
671 | * enum mesh_config_capab_flags - Mesh Configuration IE capability field flags | 671 | * enum mesh_config_capab_flags - Mesh Configuration IE capability field flags |
@@ -695,12 +695,17 @@ struct ieee80211_rann_ie { | |||
695 | __le32 rann_seq; | 695 | __le32 rann_seq; |
696 | __le32 rann_interval; | 696 | __le32 rann_interval; |
697 | __le32 rann_metric; | 697 | __le32 rann_metric; |
698 | } __attribute__ ((packed)); | 698 | } __packed; |
699 | 699 | ||
700 | enum ieee80211_rann_flags { | 700 | enum ieee80211_rann_flags { |
701 | RANN_FLAG_IS_GATE = 1 << 0, | 701 | RANN_FLAG_IS_GATE = 1 << 0, |
702 | }; | 702 | }; |
703 | 703 | ||
704 | enum ieee80211_ht_chanwidth_values { | ||
705 | IEEE80211_HT_CHANWIDTH_20MHZ = 0, | ||
706 | IEEE80211_HT_CHANWIDTH_ANY = 1, | ||
707 | }; | ||
708 | |||
704 | #define WLAN_SA_QUERY_TR_ID_LEN 2 | 709 | #define WLAN_SA_QUERY_TR_ID_LEN 2 |
705 | 710 | ||
706 | struct ieee80211_mgmt { | 711 | struct ieee80211_mgmt { |
@@ -717,33 +722,33 @@ struct ieee80211_mgmt { | |||
717 | __le16 status_code; | 722 | __le16 status_code; |
718 | /* possibly followed by Challenge text */ | 723 | /* possibly followed by Challenge text */ |
719 | u8 variable[0]; | 724 | u8 variable[0]; |
720 | } __attribute__ ((packed)) auth; | 725 | } __packed auth; |
721 | struct { | 726 | struct { |
722 | __le16 reason_code; | 727 | __le16 reason_code; |
723 | } __attribute__ ((packed)) deauth; | 728 | } __packed deauth; |
724 | struct { | 729 | struct { |
725 | __le16 capab_info; | 730 | __le16 capab_info; |
726 | __le16 listen_interval; | 731 | __le16 listen_interval; |
727 | /* followed by SSID and Supported rates */ | 732 | /* followed by SSID and Supported rates */ |
728 | u8 variable[0]; | 733 | u8 variable[0]; |
729 | } __attribute__ ((packed)) assoc_req; | 734 | } __packed assoc_req; |
730 | struct { | 735 | struct { |
731 | __le16 capab_info; | 736 | __le16 capab_info; |
732 | __le16 status_code; | 737 | __le16 status_code; |
733 | __le16 aid; | 738 | __le16 aid; |
734 | /* followed by Supported rates */ | 739 | /* followed by Supported rates */ |
735 | u8 variable[0]; | 740 | u8 variable[0]; |
736 | } __attribute__ ((packed)) assoc_resp, reassoc_resp; | 741 | } __packed assoc_resp, reassoc_resp; |
737 | struct { | 742 | struct { |
738 | __le16 capab_info; | 743 | __le16 capab_info; |
739 | __le16 listen_interval; | 744 | __le16 listen_interval; |
740 | u8 current_ap[6]; | 745 | u8 current_ap[6]; |
741 | /* followed by SSID and Supported rates */ | 746 | /* followed by SSID and Supported rates */ |
742 | u8 variable[0]; | 747 | u8 variable[0]; |
743 | } __attribute__ ((packed)) reassoc_req; | 748 | } __packed reassoc_req; |
744 | struct { | 749 | struct { |
745 | __le16 reason_code; | 750 | __le16 reason_code; |
746 | } __attribute__ ((packed)) disassoc; | 751 | } __packed disassoc; |
747 | struct { | 752 | struct { |
748 | __le64 timestamp; | 753 | __le64 timestamp; |
749 | __le16 beacon_int; | 754 | __le16 beacon_int; |
@@ -751,11 +756,11 @@ struct ieee80211_mgmt { | |||
751 | /* followed by some of SSID, Supported rates, | 756 | /* followed by some of SSID, Supported rates, |
752 | * FH Params, DS Params, CF Params, IBSS Params, TIM */ | 757 | * FH Params, DS Params, CF Params, IBSS Params, TIM */ |
753 | u8 variable[0]; | 758 | u8 variable[0]; |
754 | } __attribute__ ((packed)) beacon; | 759 | } __packed beacon; |
755 | struct { | 760 | struct { |
756 | /* only variable items: SSID, Supported rates */ | 761 | /* only variable items: SSID, Supported rates */ |
757 | u8 variable[0]; | 762 | u8 variable[0]; |
758 | } __attribute__ ((packed)) probe_req; | 763 | } __packed probe_req; |
759 | struct { | 764 | struct { |
760 | __le64 timestamp; | 765 | __le64 timestamp; |
761 | __le16 beacon_int; | 766 | __le16 beacon_int; |
@@ -763,7 +768,7 @@ struct ieee80211_mgmt { | |||
763 | /* followed by some of SSID, Supported rates, | 768 | /* followed by some of SSID, Supported rates, |
764 | * FH Params, DS Params, CF Params, IBSS Params */ | 769 | * FH Params, DS Params, CF Params, IBSS Params */ |
765 | u8 variable[0]; | 770 | u8 variable[0]; |
766 | } __attribute__ ((packed)) probe_resp; | 771 | } __packed probe_resp; |
767 | struct { | 772 | struct { |
768 | u8 category; | 773 | u8 category; |
769 | union { | 774 | union { |
@@ -772,55 +777,59 @@ struct ieee80211_mgmt { | |||
772 | u8 dialog_token; | 777 | u8 dialog_token; |
773 | u8 status_code; | 778 | u8 status_code; |
774 | u8 variable[0]; | 779 | u8 variable[0]; |
775 | } __attribute__ ((packed)) wme_action; | 780 | } __packed wme_action; |
776 | struct{ | 781 | struct{ |
777 | u8 action_code; | 782 | u8 action_code; |
778 | u8 element_id; | 783 | u8 element_id; |
779 | u8 length; | 784 | u8 length; |
780 | struct ieee80211_channel_sw_ie sw_elem; | 785 | struct ieee80211_channel_sw_ie sw_elem; |
781 | } __attribute__((packed)) chan_switch; | 786 | } __packed chan_switch; |
782 | struct{ | 787 | struct{ |
783 | u8 action_code; | 788 | u8 action_code; |
784 | u8 dialog_token; | 789 | u8 dialog_token; |
785 | u8 element_id; | 790 | u8 element_id; |
786 | u8 length; | 791 | u8 length; |
787 | struct ieee80211_msrment_ie msr_elem; | 792 | struct ieee80211_msrment_ie msr_elem; |
788 | } __attribute__((packed)) measurement; | 793 | } __packed measurement; |
789 | struct{ | 794 | struct{ |
790 | u8 action_code; | 795 | u8 action_code; |
791 | u8 dialog_token; | 796 | u8 dialog_token; |
792 | __le16 capab; | 797 | __le16 capab; |
793 | __le16 timeout; | 798 | __le16 timeout; |
794 | __le16 start_seq_num; | 799 | __le16 start_seq_num; |
795 | } __attribute__((packed)) addba_req; | 800 | } __packed addba_req; |
796 | struct{ | 801 | struct{ |
797 | u8 action_code; | 802 | u8 action_code; |
798 | u8 dialog_token; | 803 | u8 dialog_token; |
799 | __le16 status; | 804 | __le16 status; |
800 | __le16 capab; | 805 | __le16 capab; |
801 | __le16 timeout; | 806 | __le16 timeout; |
802 | } __attribute__((packed)) addba_resp; | 807 | } __packed addba_resp; |
803 | struct{ | 808 | struct{ |
804 | u8 action_code; | 809 | u8 action_code; |
805 | __le16 params; | 810 | __le16 params; |
806 | __le16 reason_code; | 811 | __le16 reason_code; |
807 | } __attribute__((packed)) delba; | 812 | } __packed delba; |
808 | struct { | 813 | struct { |
809 | u8 action_code; | 814 | u8 action_code; |
810 | u8 variable[0]; | 815 | u8 variable[0]; |
811 | } __attribute__((packed)) self_prot; | 816 | } __packed self_prot; |
812 | struct{ | 817 | struct{ |
813 | u8 action_code; | 818 | u8 action_code; |
814 | u8 variable[0]; | 819 | u8 variable[0]; |
815 | } __attribute__((packed)) mesh_action; | 820 | } __packed mesh_action; |
816 | struct { | 821 | struct { |
817 | u8 action; | 822 | u8 action; |
818 | u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; | 823 | u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; |
819 | } __attribute__ ((packed)) sa_query; | 824 | } __packed sa_query; |
820 | struct { | 825 | struct { |
821 | u8 action; | 826 | u8 action; |
822 | u8 smps_control; | 827 | u8 smps_control; |
823 | } __attribute__ ((packed)) ht_smps; | 828 | } __packed ht_smps; |
829 | struct { | ||
830 | u8 action_code; | ||
831 | u8 chanwidth; | ||
832 | } __packed ht_notify_cw; | ||
824 | struct { | 833 | struct { |
825 | u8 action_code; | 834 | u8 action_code; |
826 | u8 dialog_token; | 835 | u8 dialog_token; |
@@ -828,9 +837,9 @@ struct ieee80211_mgmt { | |||
828 | u8 variable[0]; | 837 | u8 variable[0]; |
829 | } __packed tdls_discover_resp; | 838 | } __packed tdls_discover_resp; |
830 | } u; | 839 | } u; |
831 | } __attribute__ ((packed)) action; | 840 | } __packed action; |
832 | } u; | 841 | } u; |
833 | } __attribute__ ((packed)); | 842 | } __packed; |
834 | 843 | ||
835 | /* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */ | 844 | /* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */ |
836 | #define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 | 845 | #define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 |
@@ -846,7 +855,7 @@ struct ieee80211_mmie { | |||
846 | __le16 key_id; | 855 | __le16 key_id; |
847 | u8 sequence_number[6]; | 856 | u8 sequence_number[6]; |
848 | u8 mic[8]; | 857 | u8 mic[8]; |
849 | } __attribute__ ((packed)); | 858 | } __packed; |
850 | 859 | ||
851 | struct ieee80211_vendor_ie { | 860 | struct ieee80211_vendor_ie { |
852 | u8 element_id; | 861 | u8 element_id; |
@@ -861,20 +870,20 @@ struct ieee80211_rts { | |||
861 | __le16 duration; | 870 | __le16 duration; |
862 | u8 ra[6]; | 871 | u8 ra[6]; |
863 | u8 ta[6]; | 872 | u8 ta[6]; |
864 | } __attribute__ ((packed)); | 873 | } __packed; |
865 | 874 | ||
866 | struct ieee80211_cts { | 875 | struct ieee80211_cts { |
867 | __le16 frame_control; | 876 | __le16 frame_control; |
868 | __le16 duration; | 877 | __le16 duration; |
869 | u8 ra[6]; | 878 | u8 ra[6]; |
870 | } __attribute__ ((packed)); | 879 | } __packed; |
871 | 880 | ||
872 | struct ieee80211_pspoll { | 881 | struct ieee80211_pspoll { |
873 | __le16 frame_control; | 882 | __le16 frame_control; |
874 | __le16 aid; | 883 | __le16 aid; |
875 | u8 bssid[6]; | 884 | u8 bssid[6]; |
876 | u8 ta[6]; | 885 | u8 ta[6]; |
877 | } __attribute__ ((packed)); | 886 | } __packed; |
878 | 887 | ||
879 | /* TDLS */ | 888 | /* TDLS */ |
880 | 889 | ||
@@ -967,7 +976,7 @@ struct ieee80211_bar { | |||
967 | __u8 ta[6]; | 976 | __u8 ta[6]; |
968 | __le16 control; | 977 | __le16 control; |
969 | __le16 start_seq_num; | 978 | __le16 start_seq_num; |
970 | } __attribute__((packed)); | 979 | } __packed; |
971 | 980 | ||
972 | /* 802.11 BAR control masks */ | 981 | /* 802.11 BAR control masks */ |
973 | #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 | 982 | #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 |
@@ -992,7 +1001,7 @@ struct ieee80211_mcs_info { | |||
992 | __le16 rx_highest; | 1001 | __le16 rx_highest; |
993 | u8 tx_params; | 1002 | u8 tx_params; |
994 | u8 reserved[3]; | 1003 | u8 reserved[3]; |
995 | } __attribute__((packed)); | 1004 | } __packed; |
996 | 1005 | ||
997 | /* 802.11n HT capability MSC set */ | 1006 | /* 802.11n HT capability MSC set */ |
998 | #define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff | 1007 | #define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff |
@@ -1031,7 +1040,7 @@ struct ieee80211_ht_cap { | |||
1031 | __le16 extended_ht_cap_info; | 1040 | __le16 extended_ht_cap_info; |
1032 | __le32 tx_BF_cap_info; | 1041 | __le32 tx_BF_cap_info; |
1033 | u8 antenna_selection_info; | 1042 | u8 antenna_selection_info; |
1034 | } __attribute__ ((packed)); | 1043 | } __packed; |
1035 | 1044 | ||
1036 | /* 802.11n HT capabilities masks (for cap_info) */ | 1045 | /* 802.11n HT capabilities masks (for cap_info) */ |
1037 | #define IEEE80211_HT_CAP_LDPC_CODING 0x0001 | 1046 | #define IEEE80211_HT_CAP_LDPC_CODING 0x0001 |
@@ -1102,7 +1111,7 @@ struct ieee80211_ht_operation { | |||
1102 | __le16 operation_mode; | 1111 | __le16 operation_mode; |
1103 | __le16 stbc_param; | 1112 | __le16 stbc_param; |
1104 | u8 basic_set[16]; | 1113 | u8 basic_set[16]; |
1105 | } __attribute__ ((packed)); | 1114 | } __packed; |
1106 | 1115 | ||
1107 | /* for ht_param */ | 1116 | /* for ht_param */ |
1108 | #define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 | 1117 | #define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 |
@@ -1311,16 +1320,21 @@ struct ieee80211_vht_operation { | |||
1311 | #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) | 1320 | #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) |
1312 | #define WLAN_CAPABILITY_QOS (1<<9) | 1321 | #define WLAN_CAPABILITY_QOS (1<<9) |
1313 | #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) | 1322 | #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) |
1323 | #define WLAN_CAPABILITY_APSD (1<<11) | ||
1324 | #define WLAN_CAPABILITY_RADIO_MEASURE (1<<12) | ||
1314 | #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) | 1325 | #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) |
1326 | #define WLAN_CAPABILITY_DEL_BACK (1<<14) | ||
1327 | #define WLAN_CAPABILITY_IMM_BACK (1<<15) | ||
1315 | 1328 | ||
1316 | /* DMG (60gHz) 802.11ad */ | 1329 | /* DMG (60gHz) 802.11ad */ |
1317 | /* type - bits 0..1 */ | 1330 | /* type - bits 0..1 */ |
1331 | #define WLAN_CAPABILITY_DMG_TYPE_MASK (3<<0) | ||
1318 | #define WLAN_CAPABILITY_DMG_TYPE_IBSS (1<<0) /* Tx by: STA */ | 1332 | #define WLAN_CAPABILITY_DMG_TYPE_IBSS (1<<0) /* Tx by: STA */ |
1319 | #define WLAN_CAPABILITY_DMG_TYPE_PBSS (2<<0) /* Tx by: PCP */ | 1333 | #define WLAN_CAPABILITY_DMG_TYPE_PBSS (2<<0) /* Tx by: PCP */ |
1320 | #define WLAN_CAPABILITY_DMG_TYPE_AP (3<<0) /* Tx by: AP */ | 1334 | #define WLAN_CAPABILITY_DMG_TYPE_AP (3<<0) /* Tx by: AP */ |
1321 | 1335 | ||
1322 | #define WLAN_CAPABILITY_DMG_CBAP_ONLY (1<<2) | 1336 | #define WLAN_CAPABILITY_DMG_CBAP_ONLY (1<<2) |
1323 | #define WLAN_CAPABILITY_DMG_CBAP_SOURCE (1<<3) | 1337 | #define WLAN_CAPABILITY_DMG_CBAP_SOURCE (1<<3) |
1324 | #define WLAN_CAPABILITY_DMG_PRIVACY (1<<4) | 1338 | #define WLAN_CAPABILITY_DMG_PRIVACY (1<<4) |
1325 | #define WLAN_CAPABILITY_DMG_ECPAC (1<<5) | 1339 | #define WLAN_CAPABILITY_DMG_ECPAC (1<<5) |
1326 | 1340 | ||
@@ -1834,14 +1848,14 @@ struct ieee80211_country_ie_triplet { | |||
1834 | u8 first_channel; | 1848 | u8 first_channel; |
1835 | u8 num_channels; | 1849 | u8 num_channels; |
1836 | s8 max_power; | 1850 | s8 max_power; |
1837 | } __attribute__ ((packed)) chans; | 1851 | } __packed chans; |
1838 | struct { | 1852 | struct { |
1839 | u8 reg_extension_id; | 1853 | u8 reg_extension_id; |
1840 | u8 reg_class; | 1854 | u8 reg_class; |
1841 | u8 coverage_class; | 1855 | u8 coverage_class; |
1842 | } __attribute__ ((packed)) ext; | 1856 | } __packed ext; |
1843 | }; | 1857 | }; |
1844 | } __attribute__ ((packed)); | 1858 | } __packed; |
1845 | 1859 | ||
1846 | enum ieee80211_timeout_interval_type { | 1860 | enum ieee80211_timeout_interval_type { |
1847 | WLAN_TIMEOUT_REASSOC_DEADLINE = 1 /* 802.11r */, | 1861 | WLAN_TIMEOUT_REASSOC_DEADLINE = 1 /* 802.11r */, |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f78fa19a07b0..1b9830ebe6c6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -281,9 +281,13 @@ struct ieee80211_supported_band { | |||
281 | /** | 281 | /** |
282 | * struct vif_params - describes virtual interface parameters | 282 | * struct vif_params - describes virtual interface parameters |
283 | * @use_4addr: use 4-address frames | 283 | * @use_4addr: use 4-address frames |
284 | * @macaddr: address to use for this virtual interface. This will only | ||
285 | * be used for non-netdevice interfaces. If this parameter is set | ||
286 | * to zero address the driver may determine the address as needed. | ||
284 | */ | 287 | */ |
285 | struct vif_params { | 288 | struct vif_params { |
286 | int use_4addr; | 289 | int use_4addr; |
290 | u8 macaddr[ETH_ALEN]; | ||
287 | }; | 291 | }; |
288 | 292 | ||
289 | /** | 293 | /** |
@@ -326,7 +330,7 @@ struct cfg80211_chan_def { | |||
326 | * cfg80211_get_chandef_type - return old channel type from chandef | 330 | * cfg80211_get_chandef_type - return old channel type from chandef |
327 | * @chandef: the channel definition | 331 | * @chandef: the channel definition |
328 | * | 332 | * |
329 | * Returns the old channel type (NOHT, HT20, HT40+/-) from a given | 333 | * Return: The old channel type (NOHT, HT20, HT40+/-) from a given |
330 | * chandef, which must have a bandwidth allowing this conversion. | 334 | * chandef, which must have a bandwidth allowing this conversion. |
331 | */ | 335 | */ |
332 | static inline enum nl80211_channel_type | 336 | static inline enum nl80211_channel_type |
@@ -364,7 +368,7 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef, | |||
364 | * @chandef1: first channel definition | 368 | * @chandef1: first channel definition |
365 | * @chandef2: second channel definition | 369 | * @chandef2: second channel definition |
366 | * | 370 | * |
367 | * Returns %true if the channels defined by the channel definitions are | 371 | * Return: %true if the channels defined by the channel definitions are |
368 | * identical, %false otherwise. | 372 | * identical, %false otherwise. |
369 | */ | 373 | */ |
370 | static inline bool | 374 | static inline bool |
@@ -382,7 +386,7 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1, | |||
382 | * @chandef1: first channel definition | 386 | * @chandef1: first channel definition |
383 | * @chandef2: second channel definition | 387 | * @chandef2: second channel definition |
384 | * | 388 | * |
385 | * Returns %NULL if the given channel definitions are incompatible, | 389 | * Return: %NULL if the given channel definitions are incompatible, |
386 | * chandef1 or chandef2 otherwise. | 390 | * chandef1 or chandef2 otherwise. |
387 | */ | 391 | */ |
388 | const struct cfg80211_chan_def * | 392 | const struct cfg80211_chan_def * |
@@ -392,6 +396,7 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1, | |||
392 | /** | 396 | /** |
393 | * cfg80211_chandef_valid - check if a channel definition is valid | 397 | * cfg80211_chandef_valid - check if a channel definition is valid |
394 | * @chandef: the channel definition to check | 398 | * @chandef: the channel definition to check |
399 | * Return: %true if the channel definition is valid. %false otherwise. | ||
395 | */ | 400 | */ |
396 | bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef); | 401 | bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef); |
397 | 402 | ||
@@ -399,7 +404,8 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef); | |||
399 | * cfg80211_chandef_usable - check if secondary channels can be used | 404 | * cfg80211_chandef_usable - check if secondary channels can be used |
400 | * @wiphy: the wiphy to validate against | 405 | * @wiphy: the wiphy to validate against |
401 | * @chandef: the channel definition to check | 406 | * @chandef: the channel definition to check |
402 | * @prohibited_flags: the regulatory chanenl flags that must not be set | 407 | * @prohibited_flags: the regulatory channel flags that must not be set |
408 | * Return: %true if secondary channels are usable. %false otherwise. | ||
403 | */ | 409 | */ |
404 | bool cfg80211_chandef_usable(struct wiphy *wiphy, | 410 | bool cfg80211_chandef_usable(struct wiphy *wiphy, |
405 | const struct cfg80211_chan_def *chandef, | 411 | const struct cfg80211_chan_def *chandef, |
@@ -608,6 +614,8 @@ enum station_parameters_apply_mask { | |||
608 | * @sta_modify_mask: bitmap indicating which parameters changed | 614 | * @sta_modify_mask: bitmap indicating which parameters changed |
609 | * (for those that don't have a natural "no change" value), | 615 | * (for those that don't have a natural "no change" value), |
610 | * see &enum station_parameters_apply_mask | 616 | * see &enum station_parameters_apply_mask |
617 | * @local_pm: local link-specific mesh power save mode (no change when set | ||
618 | * to unknown) | ||
611 | */ | 619 | */ |
612 | struct station_parameters { | 620 | struct station_parameters { |
613 | u8 *supported_rates; | 621 | u8 *supported_rates; |
@@ -623,6 +631,7 @@ struct station_parameters { | |||
623 | struct ieee80211_vht_cap *vht_capa; | 631 | struct ieee80211_vht_cap *vht_capa; |
624 | u8 uapsd_queues; | 632 | u8 uapsd_queues; |
625 | u8 max_sp; | 633 | u8 max_sp; |
634 | enum nl80211_mesh_power_mode local_pm; | ||
626 | }; | 635 | }; |
627 | 636 | ||
628 | /** | 637 | /** |
@@ -653,6 +662,9 @@ struct station_parameters { | |||
653 | * @STATION_INFO_STA_FLAGS: @sta_flags filled | 662 | * @STATION_INFO_STA_FLAGS: @sta_flags filled |
654 | * @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled | 663 | * @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled |
655 | * @STATION_INFO_T_OFFSET: @t_offset filled | 664 | * @STATION_INFO_T_OFFSET: @t_offset filled |
665 | * @STATION_INFO_LOCAL_PM: @local_pm filled | ||
666 | * @STATION_INFO_PEER_PM: @peer_pm filled | ||
667 | * @STATION_INFO_NONPEER_PM: @nonpeer_pm filled | ||
656 | */ | 668 | */ |
657 | enum station_info_flags { | 669 | enum station_info_flags { |
658 | STATION_INFO_INACTIVE_TIME = 1<<0, | 670 | STATION_INFO_INACTIVE_TIME = 1<<0, |
@@ -676,6 +688,9 @@ enum station_info_flags { | |||
676 | STATION_INFO_STA_FLAGS = 1<<18, | 688 | STATION_INFO_STA_FLAGS = 1<<18, |
677 | STATION_INFO_BEACON_LOSS_COUNT = 1<<19, | 689 | STATION_INFO_BEACON_LOSS_COUNT = 1<<19, |
678 | STATION_INFO_T_OFFSET = 1<<20, | 690 | STATION_INFO_T_OFFSET = 1<<20, |
691 | STATION_INFO_LOCAL_PM = 1<<21, | ||
692 | STATION_INFO_PEER_PM = 1<<22, | ||
693 | STATION_INFO_NONPEER_PM = 1<<23, | ||
679 | }; | 694 | }; |
680 | 695 | ||
681 | /** | 696 | /** |
@@ -789,6 +804,9 @@ struct sta_bss_parameters { | |||
789 | * @sta_flags: station flags mask & values | 804 | * @sta_flags: station flags mask & values |
790 | * @beacon_loss_count: Number of times beacon loss event has triggered. | 805 | * @beacon_loss_count: Number of times beacon loss event has triggered. |
791 | * @t_offset: Time offset of the station relative to this host. | 806 | * @t_offset: Time offset of the station relative to this host. |
807 | * @local_pm: local mesh STA power save mode | ||
808 | * @peer_pm: peer mesh STA power save mode | ||
809 | * @nonpeer_pm: non-peer mesh STA power save mode | ||
792 | */ | 810 | */ |
793 | struct station_info { | 811 | struct station_info { |
794 | u32 filled; | 812 | u32 filled; |
@@ -818,6 +836,9 @@ struct station_info { | |||
818 | 836 | ||
819 | u32 beacon_loss_count; | 837 | u32 beacon_loss_count; |
820 | s64 t_offset; | 838 | s64 t_offset; |
839 | enum nl80211_mesh_power_mode local_pm; | ||
840 | enum nl80211_mesh_power_mode peer_pm; | ||
841 | enum nl80211_mesh_power_mode nonpeer_pm; | ||
821 | 842 | ||
822 | /* | 843 | /* |
823 | * Note: Add a new enum station_info_flags value for each new field and | 844 | * Note: Add a new enum station_info_flags value for each new field and |
@@ -993,6 +1014,10 @@ struct bss_parameters { | |||
993 | * @dot11MeshHWMPconfirmationInterval: The minimum interval of time (in TUs) | 1014 | * @dot11MeshHWMPconfirmationInterval: The minimum interval of time (in TUs) |
994 | * during which a mesh STA can send only one Action frame containing | 1015 | * during which a mesh STA can send only one Action frame containing |
995 | * a PREQ element for root path confirmation. | 1016 | * a PREQ element for root path confirmation. |
1017 | * @power_mode: The default mesh power save mode which will be the initial | ||
1018 | * setting for new peer links. | ||
1019 | * @dot11MeshAwakeWindowDuration: The duration in TUs the STA will remain awake | ||
1020 | * after transmitting its beacon. | ||
996 | */ | 1021 | */ |
997 | struct mesh_config { | 1022 | struct mesh_config { |
998 | u16 dot11MeshRetryTimeout; | 1023 | u16 dot11MeshRetryTimeout; |
@@ -1020,6 +1045,8 @@ struct mesh_config { | |||
1020 | u32 dot11MeshHWMPactivePathToRootTimeout; | 1045 | u32 dot11MeshHWMPactivePathToRootTimeout; |
1021 | u16 dot11MeshHWMProotInterval; | 1046 | u16 dot11MeshHWMProotInterval; |
1022 | u16 dot11MeshHWMPconfirmationInterval; | 1047 | u16 dot11MeshHWMPconfirmationInterval; |
1048 | enum nl80211_mesh_power_mode power_mode; | ||
1049 | u16 dot11MeshAwakeWindowDuration; | ||
1023 | }; | 1050 | }; |
1024 | 1051 | ||
1025 | /** | 1052 | /** |
@@ -1034,6 +1061,8 @@ struct mesh_config { | |||
1034 | * @ie_len: length of vendor information elements | 1061 | * @ie_len: length of vendor information elements |
1035 | * @is_authenticated: this mesh requires authentication | 1062 | * @is_authenticated: this mesh requires authentication |
1036 | * @is_secure: this mesh uses security | 1063 | * @is_secure: this mesh uses security |
1064 | * @dtim_period: DTIM period to use | ||
1065 | * @beacon_interval: beacon interval to use | ||
1037 | * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] | 1066 | * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] |
1038 | * | 1067 | * |
1039 | * These parameters are fixed when the mesh is created. | 1068 | * These parameters are fixed when the mesh is created. |
@@ -1049,6 +1078,8 @@ struct mesh_setup { | |||
1049 | u8 ie_len; | 1078 | u8 ie_len; |
1050 | bool is_authenticated; | 1079 | bool is_authenticated; |
1051 | bool is_secure; | 1080 | bool is_secure; |
1081 | u8 dtim_period; | ||
1082 | u16 beacon_interval; | ||
1052 | int mcast_rate[IEEE80211_NUM_BANDS]; | 1083 | int mcast_rate[IEEE80211_NUM_BANDS]; |
1053 | }; | 1084 | }; |
1054 | 1085 | ||
@@ -1256,7 +1287,7 @@ struct cfg80211_bss { | |||
1256 | 1287 | ||
1257 | u8 bssid[ETH_ALEN]; | 1288 | u8 bssid[ETH_ALEN]; |
1258 | 1289 | ||
1259 | u8 priv[0] __attribute__((__aligned__(sizeof(void *)))); | 1290 | u8 priv[0] __aligned(sizeof(void *)); |
1260 | }; | 1291 | }; |
1261 | 1292 | ||
1262 | /** | 1293 | /** |
@@ -1266,7 +1297,7 @@ struct cfg80211_bss { | |||
1266 | * | 1297 | * |
1267 | * Note that the return value is an RCU-protected pointer, so | 1298 | * Note that the return value is an RCU-protected pointer, so |
1268 | * rcu_read_lock() must be held when calling this function. | 1299 | * rcu_read_lock() must be held when calling this function. |
1269 | * Returns %NULL if not found. | 1300 | * Return: %NULL if not found. |
1270 | */ | 1301 | */ |
1271 | const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); | 1302 | const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); |
1272 | 1303 | ||
@@ -1434,6 +1465,7 @@ struct cfg80211_ibss_params { | |||
1434 | * @ie: IEs for association request | 1465 | * @ie: IEs for association request |
1435 | * @ie_len: Length of assoc_ie in octets | 1466 | * @ie_len: Length of assoc_ie in octets |
1436 | * @privacy: indicates whether privacy-enabled APs should be used | 1467 | * @privacy: indicates whether privacy-enabled APs should be used |
1468 | * @mfp: indicate whether management frame protection is used | ||
1437 | * @crypto: crypto settings | 1469 | * @crypto: crypto settings |
1438 | * @key_len: length of WEP key for shared key authentication | 1470 | * @key_len: length of WEP key for shared key authentication |
1439 | * @key_idx: index of WEP key for shared key authentication | 1471 | * @key_idx: index of WEP key for shared key authentication |
@@ -1454,6 +1486,7 @@ struct cfg80211_connect_params { | |||
1454 | u8 *ie; | 1486 | u8 *ie; |
1455 | size_t ie_len; | 1487 | size_t ie_len; |
1456 | bool privacy; | 1488 | bool privacy; |
1489 | enum nl80211_mfp mfp; | ||
1457 | struct cfg80211_crypto_settings crypto; | 1490 | struct cfg80211_crypto_settings crypto; |
1458 | const u8 *key; | 1491 | const u8 *key; |
1459 | u8 key_len, key_idx; | 1492 | u8 key_len, key_idx; |
@@ -2092,6 +2125,7 @@ struct ieee80211_iface_limit { | |||
2092 | * @beacon_int_infra_match: In this combination, the beacon intervals | 2125 | * @beacon_int_infra_match: In this combination, the beacon intervals |
2093 | * between infrastructure and AP types must match. This is required | 2126 | * between infrastructure and AP types must match. This is required |
2094 | * only in special cases. | 2127 | * only in special cases. |
2128 | * @radar_detect_widths: bitmap of channel widths supported for radar detection | ||
2095 | * | 2129 | * |
2096 | * These examples can be expressed as follows: | 2130 | * These examples can be expressed as follows: |
2097 | * | 2131 | * |
@@ -2144,6 +2178,7 @@ struct ieee80211_iface_combination { | |||
2144 | u16 max_interfaces; | 2178 | u16 max_interfaces; |
2145 | u8 n_limits; | 2179 | u8 n_limits; |
2146 | bool beacon_int_infra_match; | 2180 | bool beacon_int_infra_match; |
2181 | u8 radar_detect_widths; | ||
2147 | }; | 2182 | }; |
2148 | 2183 | ||
2149 | struct mac_address { | 2184 | struct mac_address { |
@@ -2364,12 +2399,12 @@ struct wiphy { | |||
2364 | struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; | 2399 | struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; |
2365 | 2400 | ||
2366 | /* Lets us get back the wiphy on the callback */ | 2401 | /* Lets us get back the wiphy on the callback */ |
2367 | int (*reg_notifier)(struct wiphy *wiphy, | 2402 | void (*reg_notifier)(struct wiphy *wiphy, |
2368 | struct regulatory_request *request); | 2403 | struct regulatory_request *request); |
2369 | 2404 | ||
2370 | /* fields below are read-only, assigned by cfg80211 */ | 2405 | /* fields below are read-only, assigned by cfg80211 */ |
2371 | 2406 | ||
2372 | const struct ieee80211_regdomain *regd; | 2407 | const struct ieee80211_regdomain __rcu *regd; |
2373 | 2408 | ||
2374 | /* the item in /sys/class/ieee80211/ points to this, | 2409 | /* the item in /sys/class/ieee80211/ points to this, |
2375 | * you need use set_wiphy_dev() (see below) */ | 2410 | * you need use set_wiphy_dev() (see below) */ |
@@ -2392,7 +2427,7 @@ struct wiphy { | |||
2392 | const struct iw_handler_def *wext; | 2427 | const struct iw_handler_def *wext; |
2393 | #endif | 2428 | #endif |
2394 | 2429 | ||
2395 | char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); | 2430 | char priv[0] __aligned(NETDEV_ALIGN); |
2396 | }; | 2431 | }; |
2397 | 2432 | ||
2398 | static inline struct net *wiphy_net(struct wiphy *wiphy) | 2433 | static inline struct net *wiphy_net(struct wiphy *wiphy) |
@@ -2409,6 +2444,7 @@ static inline void wiphy_net_set(struct wiphy *wiphy, struct net *net) | |||
2409 | * wiphy_priv - return priv from wiphy | 2444 | * wiphy_priv - return priv from wiphy |
2410 | * | 2445 | * |
2411 | * @wiphy: the wiphy whose priv pointer to return | 2446 | * @wiphy: the wiphy whose priv pointer to return |
2447 | * Return: The priv of @wiphy. | ||
2412 | */ | 2448 | */ |
2413 | static inline void *wiphy_priv(struct wiphy *wiphy) | 2449 | static inline void *wiphy_priv(struct wiphy *wiphy) |
2414 | { | 2450 | { |
@@ -2420,6 +2456,7 @@ static inline void *wiphy_priv(struct wiphy *wiphy) | |||
2420 | * priv_to_wiphy - return the wiphy containing the priv | 2456 | * priv_to_wiphy - return the wiphy containing the priv |
2421 | * | 2457 | * |
2422 | * @priv: a pointer previously returned by wiphy_priv | 2458 | * @priv: a pointer previously returned by wiphy_priv |
2459 | * Return: The wiphy of @priv. | ||
2423 | */ | 2460 | */ |
2424 | static inline struct wiphy *priv_to_wiphy(void *priv) | 2461 | static inline struct wiphy *priv_to_wiphy(void *priv) |
2425 | { | 2462 | { |
@@ -2442,6 +2479,7 @@ static inline void set_wiphy_dev(struct wiphy *wiphy, struct device *dev) | |||
2442 | * wiphy_dev - get wiphy dev pointer | 2479 | * wiphy_dev - get wiphy dev pointer |
2443 | * | 2480 | * |
2444 | * @wiphy: The wiphy whose device struct to look up | 2481 | * @wiphy: The wiphy whose device struct to look up |
2482 | * Return: The dev of @wiphy. | ||
2445 | */ | 2483 | */ |
2446 | static inline struct device *wiphy_dev(struct wiphy *wiphy) | 2484 | static inline struct device *wiphy_dev(struct wiphy *wiphy) |
2447 | { | 2485 | { |
@@ -2452,6 +2490,7 @@ static inline struct device *wiphy_dev(struct wiphy *wiphy) | |||
2452 | * wiphy_name - get wiphy name | 2490 | * wiphy_name - get wiphy name |
2453 | * | 2491 | * |
2454 | * @wiphy: The wiphy whose name to return | 2492 | * @wiphy: The wiphy whose name to return |
2493 | * Return: The name of @wiphy. | ||
2455 | */ | 2494 | */ |
2456 | static inline const char *wiphy_name(const struct wiphy *wiphy) | 2495 | static inline const char *wiphy_name(const struct wiphy *wiphy) |
2457 | { | 2496 | { |
@@ -2467,8 +2506,8 @@ static inline const char *wiphy_name(const struct wiphy *wiphy) | |||
2467 | * Create a new wiphy and associate the given operations with it. | 2506 | * Create a new wiphy and associate the given operations with it. |
2468 | * @sizeof_priv bytes are allocated for private use. | 2507 | * @sizeof_priv bytes are allocated for private use. |
2469 | * | 2508 | * |
2470 | * The returned pointer must be assigned to each netdev's | 2509 | * Return: A pointer to the new wiphy. This pointer must be |
2471 | * ieee80211_ptr for proper operation. | 2510 | * assigned to each netdev's ieee80211_ptr for proper operation. |
2472 | */ | 2511 | */ |
2473 | struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv); | 2512 | struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv); |
2474 | 2513 | ||
@@ -2477,7 +2516,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv); | |||
2477 | * | 2516 | * |
2478 | * @wiphy: The wiphy to register. | 2517 | * @wiphy: The wiphy to register. |
2479 | * | 2518 | * |
2480 | * Returns a non-negative wiphy index or a negative error code. | 2519 | * Return: A non-negative wiphy index or a negative error code. |
2481 | */ | 2520 | */ |
2482 | extern int wiphy_register(struct wiphy *wiphy); | 2521 | extern int wiphy_register(struct wiphy *wiphy); |
2483 | 2522 | ||
@@ -2626,6 +2665,7 @@ static inline u8 *wdev_address(struct wireless_dev *wdev) | |||
2626 | * wdev_priv - return wiphy priv from wireless_dev | 2665 | * wdev_priv - return wiphy priv from wireless_dev |
2627 | * | 2666 | * |
2628 | * @wdev: The wireless device whose wiphy's priv pointer to return | 2667 | * @wdev: The wireless device whose wiphy's priv pointer to return |
2668 | * Return: The wiphy priv of @wdev. | ||
2629 | */ | 2669 | */ |
2630 | static inline void *wdev_priv(struct wireless_dev *wdev) | 2670 | static inline void *wdev_priv(struct wireless_dev *wdev) |
2631 | { | 2671 | { |
@@ -2643,12 +2683,14 @@ static inline void *wdev_priv(struct wireless_dev *wdev) | |||
2643 | * ieee80211_channel_to_frequency - convert channel number to frequency | 2683 | * ieee80211_channel_to_frequency - convert channel number to frequency |
2644 | * @chan: channel number | 2684 | * @chan: channel number |
2645 | * @band: band, necessary due to channel number overlap | 2685 | * @band: band, necessary due to channel number overlap |
2686 | * Return: The corresponding frequency (in MHz), or 0 if the conversion failed. | ||
2646 | */ | 2687 | */ |
2647 | extern int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band); | 2688 | extern int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band); |
2648 | 2689 | ||
2649 | /** | 2690 | /** |
2650 | * ieee80211_frequency_to_channel - convert frequency to channel number | 2691 | * ieee80211_frequency_to_channel - convert frequency to channel number |
2651 | * @freq: center frequency | 2692 | * @freq: center frequency |
2693 | * Return: The corresponding channel, or 0 if the conversion failed. | ||
2652 | */ | 2694 | */ |
2653 | extern int ieee80211_frequency_to_channel(int freq); | 2695 | extern int ieee80211_frequency_to_channel(int freq); |
2654 | 2696 | ||
@@ -2665,6 +2707,7 @@ extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy, | |||
2665 | * ieee80211_get_channel - get channel struct from wiphy for specified frequency | 2707 | * ieee80211_get_channel - get channel struct from wiphy for specified frequency |
2666 | * @wiphy: the struct wiphy to get the channel for | 2708 | * @wiphy: the struct wiphy to get the channel for |
2667 | * @freq: the center frequency of the channel | 2709 | * @freq: the center frequency of the channel |
2710 | * Return: The channel struct from @wiphy at @freq. | ||
2668 | */ | 2711 | */ |
2669 | static inline struct ieee80211_channel * | 2712 | static inline struct ieee80211_channel * |
2670 | ieee80211_get_channel(struct wiphy *wiphy, int freq) | 2713 | ieee80211_get_channel(struct wiphy *wiphy, int freq) |
@@ -2679,10 +2722,10 @@ ieee80211_get_channel(struct wiphy *wiphy, int freq) | |||
2679 | * @basic_rates: bitmap of basic rates | 2722 | * @basic_rates: bitmap of basic rates |
2680 | * @bitrate: the bitrate for which to find the basic rate | 2723 | * @bitrate: the bitrate for which to find the basic rate |
2681 | * | 2724 | * |
2682 | * This function returns the basic rate corresponding to a given | 2725 | * Return: The basic rate corresponding to a given bitrate, that |
2683 | * bitrate, that is the next lower bitrate contained in the basic | 2726 | * is the next lower bitrate contained in the basic rate map, |
2684 | * rate map, which is, for this function, given as a bitmap of | 2727 | * which is, for this function, given as a bitmap of indices of |
2685 | * indices of rates in the band's bitrate table. | 2728 | * rates in the band's bitrate table. |
2686 | */ | 2729 | */ |
2687 | struct ieee80211_rate * | 2730 | struct ieee80211_rate * |
2688 | ieee80211_get_response_rate(struct ieee80211_supported_band *sband, | 2731 | ieee80211_get_response_rate(struct ieee80211_supported_band *sband, |
@@ -2775,18 +2818,21 @@ extern const unsigned char bridge_tunnel_header[6]; | |||
2775 | /** | 2818 | /** |
2776 | * ieee80211_get_hdrlen_from_skb - get header length from data | 2819 | * ieee80211_get_hdrlen_from_skb - get header length from data |
2777 | * | 2820 | * |
2821 | * @skb: the frame | ||
2822 | * | ||
2778 | * Given an skb with a raw 802.11 header at the data pointer this function | 2823 | * Given an skb with a raw 802.11 header at the data pointer this function |
2779 | * returns the 802.11 header length in bytes (not including encryption | 2824 | * returns the 802.11 header length. |
2780 | * headers). If the data in the sk_buff is too short to contain a valid 802.11 | ||
2781 | * header the function returns 0. | ||
2782 | * | 2825 | * |
2783 | * @skb: the frame | 2826 | * Return: The 802.11 header length in bytes (not including encryption |
2827 | * headers). Or 0 if the data in the sk_buff is too short to contain a valid | ||
2828 | * 802.11 header. | ||
2784 | */ | 2829 | */ |
2785 | unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); | 2830 | unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); |
2786 | 2831 | ||
2787 | /** | 2832 | /** |
2788 | * ieee80211_hdrlen - get header length in bytes from frame control | 2833 | * ieee80211_hdrlen - get header length in bytes from frame control |
2789 | * @fc: frame control field in little-endian format | 2834 | * @fc: frame control field in little-endian format |
2835 | * Return: The header length in bytes. | ||
2790 | */ | 2836 | */ |
2791 | unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); | 2837 | unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); |
2792 | 2838 | ||
@@ -2794,7 +2840,7 @@ unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); | |||
2794 | * ieee80211_get_mesh_hdrlen - get mesh extension header length | 2840 | * ieee80211_get_mesh_hdrlen - get mesh extension header length |
2795 | * @meshhdr: the mesh extension header, only the flags field | 2841 | * @meshhdr: the mesh extension header, only the flags field |
2796 | * (first byte) will be accessed | 2842 | * (first byte) will be accessed |
2797 | * Returns the length of the extension header, which is always at | 2843 | * Return: The length of the extension header, which is always at |
2798 | * least 6 bytes and at most 18 if address 5 and 6 are present. | 2844 | * least 6 bytes and at most 18 if address 5 and 6 are present. |
2799 | */ | 2845 | */ |
2800 | unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); | 2846 | unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); |
@@ -2812,6 +2858,7 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); | |||
2812 | * @skb: the 802.11 data frame | 2858 | * @skb: the 802.11 data frame |
2813 | * @addr: the device MAC address | 2859 | * @addr: the device MAC address |
2814 | * @iftype: the virtual interface type | 2860 | * @iftype: the virtual interface type |
2861 | * Return: 0 on success. Non-zero on error. | ||
2815 | */ | 2862 | */ |
2816 | int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | 2863 | int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, |
2817 | enum nl80211_iftype iftype); | 2864 | enum nl80211_iftype iftype); |
@@ -2823,6 +2870,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
2823 | * @iftype: the virtual interface type | 2870 | * @iftype: the virtual interface type |
2824 | * @bssid: the network bssid (used only for iftype STATION and ADHOC) | 2871 | * @bssid: the network bssid (used only for iftype STATION and ADHOC) |
2825 | * @qos: build 802.11 QoS data frame | 2872 | * @qos: build 802.11 QoS data frame |
2873 | * Return: 0 on success, or a negative error code. | ||
2826 | */ | 2874 | */ |
2827 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, | 2875 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, |
2828 | enum nl80211_iftype iftype, u8 *bssid, bool qos); | 2876 | enum nl80211_iftype iftype, u8 *bssid, bool qos); |
@@ -2850,6 +2898,7 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, | |||
2850 | /** | 2898 | /** |
2851 | * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame | 2899 | * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame |
2852 | * @skb: the data frame | 2900 | * @skb: the data frame |
2901 | * Return: The 802.1p/1d tag. | ||
2853 | */ | 2902 | */ |
2854 | unsigned int cfg80211_classify8021d(struct sk_buff *skb); | 2903 | unsigned int cfg80211_classify8021d(struct sk_buff *skb); |
2855 | 2904 | ||
@@ -2860,12 +2909,13 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb); | |||
2860 | * @ies: data consisting of IEs | 2909 | * @ies: data consisting of IEs |
2861 | * @len: length of data | 2910 | * @len: length of data |
2862 | * | 2911 | * |
2863 | * This function will return %NULL if the element ID could | 2912 | * Return: %NULL if the element ID could not be found or if |
2864 | * not be found or if the element is invalid (claims to be | 2913 | * the element is invalid (claims to be longer than the given |
2865 | * longer than the given data), or a pointer to the first byte | 2914 | * data), or a pointer to the first byte of the requested |
2866 | * of the requested element, that is the byte containing the | 2915 | * element, that is the byte containing the element ID. |
2867 | * element ID. There are no checks on the element length | 2916 | * |
2868 | * other than having to fit into the given data. | 2917 | * Note: There are no checks on the element length other than |
2918 | * having to fit into the given data. | ||
2869 | */ | 2919 | */ |
2870 | const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len); | 2920 | const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len); |
2871 | 2921 | ||
@@ -2877,12 +2927,13 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len); | |||
2877 | * @ies: data consisting of IEs | 2927 | * @ies: data consisting of IEs |
2878 | * @len: length of data | 2928 | * @len: length of data |
2879 | * | 2929 | * |
2880 | * This function will return %NULL if the vendor specific element ID | 2930 | * Return: %NULL if the vendor specific element ID could not be found or if the |
2881 | * could not be found or if the element is invalid (claims to be | 2931 | * element is invalid (claims to be longer than the given data), or a pointer to |
2882 | * longer than the given data), or a pointer to the first byte | 2932 | * the first byte of the requested element, that is the byte containing the |
2883 | * of the requested element, that is the byte containing the | 2933 | * element ID. |
2884 | * element ID. There are no checks on the element length | 2934 | * |
2885 | * other than having to fit into the given data. | 2935 | * Note: There are no checks on the element length other than having to fit into |
2936 | * the given data. | ||
2886 | */ | 2937 | */ |
2887 | const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, | 2938 | const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, |
2888 | const u8 *ies, int len); | 2939 | const u8 *ies, int len); |
@@ -2915,6 +2966,8 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, | |||
2915 | * | 2966 | * |
2916 | * Drivers should check the return value, its possible you can get | 2967 | * Drivers should check the return value, its possible you can get |
2917 | * an -ENOMEM. | 2968 | * an -ENOMEM. |
2969 | * | ||
2970 | * Return: 0 on success. -ENOMEM. | ||
2918 | */ | 2971 | */ |
2919 | extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2); | 2972 | extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2); |
2920 | 2973 | ||
@@ -2938,28 +2991,22 @@ extern void wiphy_apply_custom_regulatory( | |||
2938 | * freq_reg_info - get regulatory information for the given frequency | 2991 | * freq_reg_info - get regulatory information for the given frequency |
2939 | * @wiphy: the wiphy for which we want to process this rule for | 2992 | * @wiphy: the wiphy for which we want to process this rule for |
2940 | * @center_freq: Frequency in KHz for which we want regulatory information for | 2993 | * @center_freq: Frequency in KHz for which we want regulatory information for |
2941 | * @desired_bw_khz: the desired max bandwidth you want to use per | ||
2942 | * channel. Note that this is still 20 MHz if you want to use HT40 | ||
2943 | * as HT40 makes use of two channels for its 40 MHz width bandwidth. | ||
2944 | * If set to 0 we'll assume you want the standard 20 MHz. | ||
2945 | * @reg_rule: the regulatory rule which we have for this frequency | ||
2946 | * | 2994 | * |
2947 | * Use this function to get the regulatory rule for a specific frequency on | 2995 | * Use this function to get the regulatory rule for a specific frequency on |
2948 | * a given wireless device. If the device has a specific regulatory domain | 2996 | * a given wireless device. If the device has a specific regulatory domain |
2949 | * it wants to follow we respect that unless a country IE has been received | 2997 | * it wants to follow we respect that unless a country IE has been received |
2950 | * and processed already. | 2998 | * and processed already. |
2951 | * | 2999 | * |
2952 | * Returns 0 if it was able to find a valid regulatory rule which does | 3000 | * Return: A valid pointer, or, when an error occurs, for example if no rule |
2953 | * apply to the given center_freq otherwise it returns non-zero. It will | 3001 | * can be found, the return value is encoded using ERR_PTR(). Use IS_ERR() to |
2954 | * also return -ERANGE if we determine the given center_freq does not even have | 3002 | * check and PTR_ERR() to obtain the numeric return value. The numeric return |
2955 | * a regulatory rule for a frequency range in the center_freq's band. See | 3003 | * value will be -ERANGE if we determine the given center_freq does not even |
2956 | * freq_in_rule_band() for our current definition of a band -- this is purely | 3004 | * have a regulatory rule for a frequency range in the center_freq's band. |
2957 | * subjective and right now its 802.11 specific. | 3005 | * See freq_in_rule_band() for our current definition of a band -- this is |
3006 | * purely subjective and right now it's 802.11 specific. | ||
2958 | */ | 3007 | */ |
2959 | extern int freq_reg_info(struct wiphy *wiphy, | 3008 | const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy, |
2960 | u32 center_freq, | 3009 | u32 center_freq); |
2961 | u32 desired_bw_khz, | ||
2962 | const struct ieee80211_reg_rule **reg_rule); | ||
2963 | 3010 | ||
2964 | /* | 3011 | /* |
2965 | * callbacks for asynchronous cfg80211 methods, notification | 3012 | * callbacks for asynchronous cfg80211 methods, notification |
@@ -3006,7 +3053,8 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy); | |||
3006 | * This informs cfg80211 that BSS information was found and | 3053 | * This informs cfg80211 that BSS information was found and |
3007 | * the BSS should be updated/added. | 3054 | * the BSS should be updated/added. |
3008 | * | 3055 | * |
3009 | * NOTE: Returns a referenced struct, must be released with cfg80211_put_bss()! | 3056 | * Return: A referenced struct, must be released with cfg80211_put_bss()! |
3057 | * Or %NULL on error. | ||
3010 | */ | 3058 | */ |
3011 | struct cfg80211_bss * __must_check | 3059 | struct cfg80211_bss * __must_check |
3012 | cfg80211_inform_bss_frame(struct wiphy *wiphy, | 3060 | cfg80211_inform_bss_frame(struct wiphy *wiphy, |
@@ -3031,7 +3079,8 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
3031 | * This informs cfg80211 that BSS information was found and | 3079 | * This informs cfg80211 that BSS information was found and |
3032 | * the BSS should be updated/added. | 3080 | * the BSS should be updated/added. |
3033 | * | 3081 | * |
3034 | * NOTE: Returns a referenced struct, must be released with cfg80211_put_bss()! | 3082 | * Return: A referenced struct, must be released with cfg80211_put_bss()! |
3083 | * Or %NULL on error. | ||
3035 | */ | 3084 | */ |
3036 | struct cfg80211_bss * __must_check | 3085 | struct cfg80211_bss * __must_check |
3037 | cfg80211_inform_bss(struct wiphy *wiphy, | 3086 | cfg80211_inform_bss(struct wiphy *wiphy, |
@@ -3308,16 +3357,18 @@ void wiphy_rfkill_stop_polling(struct wiphy *wiphy); | |||
3308 | * the testmode command. Since it is intended for a reply, calling | 3357 | * the testmode command. Since it is intended for a reply, calling |
3309 | * it outside of the @testmode_cmd operation is invalid. | 3358 | * it outside of the @testmode_cmd operation is invalid. |
3310 | * | 3359 | * |
3311 | * The returned skb (or %NULL if any errors happen) is pre-filled | 3360 | * The returned skb is pre-filled with the wiphy index and set up in |
3312 | * with the wiphy index and set up in a way that any data that is | 3361 | * a way that any data that is put into the skb (with skb_put(), |
3313 | * put into the skb (with skb_put(), nla_put() or similar) will end | 3362 | * nla_put() or similar) will end up being within the |
3314 | * up being within the %NL80211_ATTR_TESTDATA attribute, so all that | 3363 | * %NL80211_ATTR_TESTDATA attribute, so all that needs to be done |
3315 | * needs to be done with the skb is adding data for the corresponding | 3364 | * with the skb is adding data for the corresponding userspace tool |
3316 | * userspace tool which can then read that data out of the testdata | 3365 | * which can then read that data out of the testdata attribute. You |
3317 | * attribute. You must not modify the skb in any other way. | 3366 | * must not modify the skb in any other way. |
3318 | * | 3367 | * |
3319 | * When done, call cfg80211_testmode_reply() with the skb and return | 3368 | * When done, call cfg80211_testmode_reply() with the skb and return |
3320 | * its error code as the result of the @testmode_cmd operation. | 3369 | * its error code as the result of the @testmode_cmd operation. |
3370 | * | ||
3371 | * Return: An allocated and pre-filled skb. %NULL if any errors happen. | ||
3321 | */ | 3372 | */ |
3322 | struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, | 3373 | struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, |
3323 | int approxlen); | 3374 | int approxlen); |
@@ -3327,11 +3378,12 @@ struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy, | |||
3327 | * @skb: The skb, must have been allocated with | 3378 | * @skb: The skb, must have been allocated with |
3328 | * cfg80211_testmode_alloc_reply_skb() | 3379 | * cfg80211_testmode_alloc_reply_skb() |
3329 | * | 3380 | * |
3330 | * Returns an error code or 0 on success, since calling this | 3381 | * Since calling this function will usually be the last thing |
3331 | * function will usually be the last thing before returning | 3382 | * before returning from the @testmode_cmd you should return |
3332 | * from the @testmode_cmd you should return the error code. | 3383 | * the error code. Note that this function consumes the skb |
3333 | * Note that this function consumes the skb regardless of the | 3384 | * regardless of the return value. |
3334 | * return value. | 3385 | * |
3386 | * Return: An error code or 0 on success. | ||
3335 | */ | 3387 | */ |
3336 | int cfg80211_testmode_reply(struct sk_buff *skb); | 3388 | int cfg80211_testmode_reply(struct sk_buff *skb); |
3337 | 3389 | ||
@@ -3345,14 +3397,16 @@ int cfg80211_testmode_reply(struct sk_buff *skb); | |||
3345 | * This function allocates and pre-fills an skb for an event on the | 3397 | * This function allocates and pre-fills an skb for an event on the |
3346 | * testmode multicast group. | 3398 | * testmode multicast group. |
3347 | * | 3399 | * |
3348 | * The returned skb (or %NULL if any errors happen) is set up in the | 3400 | * The returned skb is set up in the same way as with |
3349 | * same way as with cfg80211_testmode_alloc_reply_skb() but prepared | 3401 | * cfg80211_testmode_alloc_reply_skb() but prepared for an event. As |
3350 | * for an event. As there, you should simply add data to it that will | 3402 | * there, you should simply add data to it that will then end up in the |
3351 | * then end up in the %NL80211_ATTR_TESTDATA attribute. Again, you must | 3403 | * %NL80211_ATTR_TESTDATA attribute. Again, you must not modify the skb |
3352 | * not modify the skb in any other way. | 3404 | * in any other way. |
3353 | * | 3405 | * |
3354 | * When done filling the skb, call cfg80211_testmode_event() with the | 3406 | * When done filling the skb, call cfg80211_testmode_event() with the |
3355 | * skb to send the event. | 3407 | * skb to send the event. |
3408 | * | ||
3409 | * Return: An allocated and pre-filled skb. %NULL if any errors happen. | ||
3356 | */ | 3410 | */ |
3357 | struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, | 3411 | struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, |
3358 | int approxlen, gfp_t gfp); | 3412 | int approxlen, gfp_t gfp); |
@@ -3533,13 +3587,13 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr, | |||
3533 | * @len: length of the frame data | 3587 | * @len: length of the frame data |
3534 | * @gfp: context flags | 3588 | * @gfp: context flags |
3535 | * | 3589 | * |
3536 | * Returns %true if a user space application has registered for this frame. | 3590 | * This function is called whenever an Action frame is received for a station |
3591 | * mode interface, but is not processed in kernel. | ||
3592 | * | ||
3593 | * Return: %true if a user space application has registered for this frame. | ||
3537 | * For action frames, that makes it responsible for rejecting unrecognized | 3594 | * For action frames, that makes it responsible for rejecting unrecognized |
3538 | * action frames; %false otherwise, in which case for action frames the | 3595 | * action frames; %false otherwise, in which case for action frames the |
3539 | * driver is responsible for rejecting the frame. | 3596 | * driver is responsible for rejecting the frame. |
3540 | * | ||
3541 | * This function is called whenever an Action frame is received for a station | ||
3542 | * mode interface, but is not processed in kernel. | ||
3543 | */ | 3597 | */ |
3544 | bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_dbm, | 3598 | bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_dbm, |
3545 | const u8 *buf, size_t len, gfp_t gfp); | 3599 | const u8 *buf, size_t len, gfp_t gfp); |
@@ -3631,7 +3685,7 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, | |||
3631 | * This function is used in AP mode (only!) to inform userspace that | 3685 | * This function is used in AP mode (only!) to inform userspace that |
3632 | * a spurious class 3 frame was received, to be able to deauth the | 3686 | * a spurious class 3 frame was received, to be able to deauth the |
3633 | * sender. | 3687 | * sender. |
3634 | * Returns %true if the frame was passed to userspace (or this failed | 3688 | * Return: %true if the frame was passed to userspace (or this failed |
3635 | * for a reason other than not having a subscription.) | 3689 | * for a reason other than not having a subscription.) |
3636 | */ | 3690 | */ |
3637 | bool cfg80211_rx_spurious_frame(struct net_device *dev, | 3691 | bool cfg80211_rx_spurious_frame(struct net_device *dev, |
@@ -3647,7 +3701,7 @@ bool cfg80211_rx_spurious_frame(struct net_device *dev, | |||
3647 | * an associated station sent a 4addr frame but that wasn't expected. | 3701 | * an associated station sent a 4addr frame but that wasn't expected. |
3648 | * It is allowed and desirable to send this event only once for each | 3702 | * It is allowed and desirable to send this event only once for each |
3649 | * station to avoid event flooding. | 3703 | * station to avoid event flooding. |
3650 | * Returns %true if the frame was passed to userspace (or this failed | 3704 | * Return: %true if the frame was passed to userspace (or this failed |
3651 | * for a reason other than not having a subscription.) | 3705 | * for a reason other than not having a subscription.) |
3652 | */ | 3706 | */ |
3653 | bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, | 3707 | bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, |
@@ -3685,8 +3739,8 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, | |||
3685 | * @wiphy: the wiphy | 3739 | * @wiphy: the wiphy |
3686 | * @chandef: the channel definition | 3740 | * @chandef: the channel definition |
3687 | * | 3741 | * |
3688 | * This function returns true if there is no secondary channel or the secondary | 3742 | * Return: %true if there is no secondary channel or the secondary channel(s) |
3689 | * channel(s) can be used for beaconing (i.e. is not a radar channel etc.) | 3743 | * can be used for beaconing (i.e. is not a radar channel etc.) |
3690 | */ | 3744 | */ |
3691 | bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | 3745 | bool cfg80211_reg_can_beacon(struct wiphy *wiphy, |
3692 | struct cfg80211_chan_def *chandef); | 3746 | struct cfg80211_chan_def *chandef); |
@@ -3756,9 +3810,9 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev); | |||
3756 | * The function finds a given P2P attribute in the (vendor) IEs and | 3810 | * The function finds a given P2P attribute in the (vendor) IEs and |
3757 | * copies its contents to the given buffer. | 3811 | * copies its contents to the given buffer. |
3758 | * | 3812 | * |
3759 | * The return value is a negative error code (-%EILSEQ or -%ENOENT) if | 3813 | * Return: A negative error code (-%EILSEQ or -%ENOENT) if the data is |
3760 | * the data is malformed or the attribute can't be found (respectively), | 3814 | * malformed or the attribute can't be found (respectively), or the |
3761 | * or the length of the found attribute (which can be zero). | 3815 | * length of the found attribute (which can be zero). |
3762 | */ | 3816 | */ |
3763 | int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, | 3817 | int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, |
3764 | enum ieee80211_p2p_attr_id attr, | 3818 | enum ieee80211_p2p_attr_id attr, |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ee50c5eba50c..3037f49e51c8 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -173,7 +173,7 @@ struct ieee80211_chanctx_conf { | |||
173 | 173 | ||
174 | u8 rx_chains_static, rx_chains_dynamic; | 174 | u8 rx_chains_static, rx_chains_dynamic; |
175 | 175 | ||
176 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); | 176 | u8 drv_priv[0] __aligned(sizeof(void *)); |
177 | }; | 177 | }; |
178 | 178 | ||
179 | /** | 179 | /** |
@@ -1059,7 +1059,7 @@ struct ieee80211_vif { | |||
1059 | u32 driver_flags; | 1059 | u32 driver_flags; |
1060 | 1060 | ||
1061 | /* must be last */ | 1061 | /* must be last */ |
1062 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); | 1062 | u8 drv_priv[0] __aligned(sizeof(void *)); |
1063 | }; | 1063 | }; |
1064 | 1064 | ||
1065 | static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) | 1065 | static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) |
@@ -1209,7 +1209,7 @@ struct ieee80211_sta { | |||
1209 | u8 max_sp; | 1209 | u8 max_sp; |
1210 | 1210 | ||
1211 | /* must be last */ | 1211 | /* must be last */ |
1212 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); | 1212 | u8 drv_priv[0] __aligned(sizeof(void *)); |
1213 | }; | 1213 | }; |
1214 | 1214 | ||
1215 | /** | 1215 | /** |
@@ -1522,6 +1522,8 @@ struct ieee80211_hw { | |||
1522 | * structure can then access it via hw->priv. Note that mac802111 drivers should | 1522 | * structure can then access it via hw->priv. Note that mac802111 drivers should |
1523 | * not use wiphy_priv() to try to get their private driver structure as this | 1523 | * not use wiphy_priv() to try to get their private driver structure as this |
1524 | * is already used internally by mac80211. | 1524 | * is already used internally by mac80211. |
1525 | * | ||
1526 | * Return: The mac80211 driver hw struct of @wiphy. | ||
1525 | */ | 1527 | */ |
1526 | struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy); | 1528 | struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy); |
1527 | 1529 | ||
@@ -2033,17 +2035,29 @@ enum ieee80211_filter_flags { | |||
2033 | * calling ieee80211_start_tx_ba_cb_irqsafe, because the peer | 2035 | * calling ieee80211_start_tx_ba_cb_irqsafe, because the peer |
2034 | * might receive the addBA frame and send a delBA right away! | 2036 | * might receive the addBA frame and send a delBA right away! |
2035 | * | 2037 | * |
2036 | * @IEEE80211_AMPDU_RX_START: start Rx aggregation | 2038 | * @IEEE80211_AMPDU_RX_START: start RX aggregation |
2037 | * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation | 2039 | * @IEEE80211_AMPDU_RX_STOP: stop RX aggregation |
2038 | * @IEEE80211_AMPDU_TX_START: start Tx aggregation | 2040 | * @IEEE80211_AMPDU_TX_START: start TX aggregation |
2039 | * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation | ||
2040 | * @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational | 2041 | * @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational |
2042 | * @IEEE80211_AMPDU_TX_STOP_CONT: stop TX aggregation but continue transmitting | ||
2043 | * queued packets, now unaggregated. After all packets are transmitted the | ||
2044 | * driver has to call ieee80211_stop_tx_ba_cb_irqsafe(). | ||
2045 | * @IEEE80211_AMPDU_TX_STOP_FLUSH: stop TX aggregation and flush all packets, | ||
2046 | * called when the station is removed. There's no need or reason to call | ||
2047 | * ieee80211_stop_tx_ba_cb_irqsafe() in this case as mac80211 assumes the | ||
2048 | * session is gone and removes the station. | ||
2049 | * @IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: called when TX aggregation is stopped | ||
2050 | * but the driver hasn't called ieee80211_stop_tx_ba_cb_irqsafe() yet and | ||
2051 | * now the connection is dropped and the station will be removed. Drivers | ||
2052 | * should clean up and drop remaining packets when this is called. | ||
2041 | */ | 2053 | */ |
2042 | enum ieee80211_ampdu_mlme_action { | 2054 | enum ieee80211_ampdu_mlme_action { |
2043 | IEEE80211_AMPDU_RX_START, | 2055 | IEEE80211_AMPDU_RX_START, |
2044 | IEEE80211_AMPDU_RX_STOP, | 2056 | IEEE80211_AMPDU_RX_STOP, |
2045 | IEEE80211_AMPDU_TX_START, | 2057 | IEEE80211_AMPDU_TX_START, |
2046 | IEEE80211_AMPDU_TX_STOP, | 2058 | IEEE80211_AMPDU_TX_STOP_CONT, |
2059 | IEEE80211_AMPDU_TX_STOP_FLUSH, | ||
2060 | IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, | ||
2047 | IEEE80211_AMPDU_TX_OPERATIONAL, | 2061 | IEEE80211_AMPDU_TX_OPERATIONAL, |
2048 | }; | 2062 | }; |
2049 | 2063 | ||
@@ -2474,7 +2488,10 @@ enum ieee80211_rate_control_changed { | |||
2474 | * | 2488 | * |
2475 | * @restart_complete: Called after a call to ieee80211_restart_hw(), when the | 2489 | * @restart_complete: Called after a call to ieee80211_restart_hw(), when the |
2476 | * reconfiguration has completed. This can help the driver implement the | 2490 | * reconfiguration has completed. This can help the driver implement the |
2477 | * reconfiguration step. This callback may sleep. | 2491 | * reconfiguration step. Also called when reconfiguring because the |
2492 | * driver's resume function returned 1, as this is just like an "inline" | ||
2493 | * hardware restart. This callback may sleep. | ||
2494 | * | ||
2478 | */ | 2495 | */ |
2479 | struct ieee80211_ops { | 2496 | struct ieee80211_ops { |
2480 | void (*tx)(struct ieee80211_hw *hw, | 2497 | void (*tx)(struct ieee80211_hw *hw, |
@@ -2661,6 +2678,8 @@ struct ieee80211_ops { | |||
2661 | * | 2678 | * |
2662 | * @priv_data_len: length of private data | 2679 | * @priv_data_len: length of private data |
2663 | * @ops: callbacks for this device | 2680 | * @ops: callbacks for this device |
2681 | * | ||
2682 | * Return: A pointer to the new hardware device, or %NULL on error. | ||
2664 | */ | 2683 | */ |
2665 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 2684 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
2666 | const struct ieee80211_ops *ops); | 2685 | const struct ieee80211_ops *ops); |
@@ -2673,6 +2692,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
2673 | * need to fill the contained wiphy's information. | 2692 | * need to fill the contained wiphy's information. |
2674 | * | 2693 | * |
2675 | * @hw: the device to register as returned by ieee80211_alloc_hw() | 2694 | * @hw: the device to register as returned by ieee80211_alloc_hw() |
2695 | * | ||
2696 | * Return: 0 on success. An error code otherwise. | ||
2676 | */ | 2697 | */ |
2677 | int ieee80211_register_hw(struct ieee80211_hw *hw); | 2698 | int ieee80211_register_hw(struct ieee80211_hw *hw); |
2678 | 2699 | ||
@@ -2719,6 +2740,8 @@ extern char *__ieee80211_create_tpt_led_trigger( | |||
2719 | * of the trigger so you can automatically link the LED device. | 2740 | * of the trigger so you can automatically link the LED device. |
2720 | * | 2741 | * |
2721 | * @hw: the hardware to get the LED trigger name for | 2742 | * @hw: the hardware to get the LED trigger name for |
2743 | * | ||
2744 | * Return: The name of the LED trigger. %NULL if not configured for LEDs. | ||
2722 | */ | 2745 | */ |
2723 | static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw) | 2746 | static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw) |
2724 | { | 2747 | { |
@@ -2738,6 +2761,8 @@ static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw) | |||
2738 | * of the trigger so you can automatically link the LED device. | 2761 | * of the trigger so you can automatically link the LED device. |
2739 | * | 2762 | * |
2740 | * @hw: the hardware to get the LED trigger name for | 2763 | * @hw: the hardware to get the LED trigger name for |
2764 | * | ||
2765 | * Return: The name of the LED trigger. %NULL if not configured for LEDs. | ||
2741 | */ | 2766 | */ |
2742 | static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw) | 2767 | static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw) |
2743 | { | 2768 | { |
@@ -2757,6 +2782,8 @@ static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw) | |||
2757 | * of the trigger so you can automatically link the LED device. | 2782 | * of the trigger so you can automatically link the LED device. |
2758 | * | 2783 | * |
2759 | * @hw: the hardware to get the LED trigger name for | 2784 | * @hw: the hardware to get the LED trigger name for |
2785 | * | ||
2786 | * Return: The name of the LED trigger. %NULL if not configured for LEDs. | ||
2760 | */ | 2787 | */ |
2761 | static inline char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) | 2788 | static inline char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) |
2762 | { | 2789 | { |
@@ -2776,6 +2803,8 @@ static inline char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) | |||
2776 | * of the trigger so you can automatically link the LED device. | 2803 | * of the trigger so you can automatically link the LED device. |
2777 | * | 2804 | * |
2778 | * @hw: the hardware to get the LED trigger name for | 2805 | * @hw: the hardware to get the LED trigger name for |
2806 | * | ||
2807 | * Return: The name of the LED trigger. %NULL if not configured for LEDs. | ||
2779 | */ | 2808 | */ |
2780 | static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw) | 2809 | static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw) |
2781 | { | 2810 | { |
@@ -2793,9 +2822,10 @@ static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw) | |||
2793 | * @blink_table: the blink table -- needs to be ordered by throughput | 2822 | * @blink_table: the blink table -- needs to be ordered by throughput |
2794 | * @blink_table_len: size of the blink table | 2823 | * @blink_table_len: size of the blink table |
2795 | * | 2824 | * |
2796 | * This function returns %NULL (in case of error, or if no LED | 2825 | * Return: %NULL (in case of error, or if no LED triggers are |
2797 | * triggers are configured) or the name of the new trigger. | 2826 | * configured) or the name of the new trigger. |
2798 | * This function must be called before ieee80211_register_hw(). | 2827 | * |
2828 | * Note: This function must be called before ieee80211_register_hw(). | ||
2799 | */ | 2829 | */ |
2800 | static inline char * | 2830 | static inline char * |
2801 | ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, unsigned int flags, | 2831 | ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, unsigned int flags, |
@@ -2928,10 +2958,10 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw, | |||
2928 | * Calls to this function for a single hardware must be synchronized against | 2958 | * Calls to this function for a single hardware must be synchronized against |
2929 | * each other. | 2959 | * each other. |
2930 | * | 2960 | * |
2931 | * The function returns -EINVAL when the requested PS mode is already set. | ||
2932 | * | ||
2933 | * @sta: currently connected sta | 2961 | * @sta: currently connected sta |
2934 | * @start: start or stop PS | 2962 | * @start: start or stop PS |
2963 | * | ||
2964 | * Return: 0 on success. -EINVAL when the requested PS mode is already set. | ||
2935 | */ | 2965 | */ |
2936 | int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start); | 2966 | int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start); |
2937 | 2967 | ||
@@ -2945,6 +2975,8 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start); | |||
2945 | * | 2975 | * |
2946 | * @sta: currently connected sta | 2976 | * @sta: currently connected sta |
2947 | * @start: start or stop PS | 2977 | * @start: start or stop PS |
2978 | * | ||
2979 | * Return: Like ieee80211_sta_ps_transition(). | ||
2948 | */ | 2980 | */ |
2949 | static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, | 2981 | static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, |
2950 | bool start) | 2982 | bool start) |
@@ -3082,6 +3114,8 @@ void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets); | |||
3082 | * according to the current DTIM parameters/TIM bitmap. | 3114 | * according to the current DTIM parameters/TIM bitmap. |
3083 | * | 3115 | * |
3084 | * The driver is responsible for freeing the returned skb. | 3116 | * The driver is responsible for freeing the returned skb. |
3117 | * | ||
3118 | * Return: The beacon template. %NULL on error. | ||
3085 | */ | 3119 | */ |
3086 | struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | 3120 | struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, |
3087 | struct ieee80211_vif *vif, | 3121 | struct ieee80211_vif *vif, |
@@ -3093,6 +3127,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
3093 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | 3127 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
3094 | * | 3128 | * |
3095 | * See ieee80211_beacon_get_tim(). | 3129 | * See ieee80211_beacon_get_tim(). |
3130 | * | ||
3131 | * Return: See ieee80211_beacon_get_tim(). | ||
3096 | */ | 3132 | */ |
3097 | static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | 3133 | static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, |
3098 | struct ieee80211_vif *vif) | 3134 | struct ieee80211_vif *vif) |
@@ -3109,6 +3145,8 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
3109 | * hardware. The destination address should be set by the caller. | 3145 | * hardware. The destination address should be set by the caller. |
3110 | * | 3146 | * |
3111 | * Can only be called in AP mode. | 3147 | * Can only be called in AP mode. |
3148 | * | ||
3149 | * Return: The Probe Response template. %NULL on error. | ||
3112 | */ | 3150 | */ |
3113 | struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, | 3151 | struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, |
3114 | struct ieee80211_vif *vif); | 3152 | struct ieee80211_vif *vif); |
@@ -3124,6 +3162,8 @@ struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, | |||
3124 | * | 3162 | * |
3125 | * Note: Caller (or hardware) is responsible for setting the | 3163 | * Note: Caller (or hardware) is responsible for setting the |
3126 | * &IEEE80211_FCTL_PM bit. | 3164 | * &IEEE80211_FCTL_PM bit. |
3165 | * | ||
3166 | * Return: The PS Poll template. %NULL on error. | ||
3127 | */ | 3167 | */ |
3128 | struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, | 3168 | struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, |
3129 | struct ieee80211_vif *vif); | 3169 | struct ieee80211_vif *vif); |
@@ -3139,6 +3179,8 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, | |||
3139 | * | 3179 | * |
3140 | * Note: Caller (or hardware) is responsible for setting the | 3180 | * Note: Caller (or hardware) is responsible for setting the |
3141 | * &IEEE80211_FCTL_PM bit as well as Duration and Sequence Control fields. | 3181 | * &IEEE80211_FCTL_PM bit as well as Duration and Sequence Control fields. |
3182 | * | ||
3183 | * Return: The nullfunc template. %NULL on error. | ||
3142 | */ | 3184 | */ |
3143 | struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | 3185 | struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, |
3144 | struct ieee80211_vif *vif); | 3186 | struct ieee80211_vif *vif); |
@@ -3153,6 +3195,8 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | |||
3153 | * | 3195 | * |
3154 | * Creates a Probe Request template which can, for example, be uploaded to | 3196 | * Creates a Probe Request template which can, for example, be uploaded to |
3155 | * hardware. | 3197 | * hardware. |
3198 | * | ||
3199 | * Return: The Probe Request template. %NULL on error. | ||
3156 | */ | 3200 | */ |
3157 | struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, | 3201 | struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, |
3158 | struct ieee80211_vif *vif, | 3202 | struct ieee80211_vif *vif, |
@@ -3188,6 +3232,8 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
3188 | * If the RTS is generated in firmware, but the host system must provide | 3232 | * If the RTS is generated in firmware, but the host system must provide |
3189 | * the duration field, the low-level driver uses this function to receive | 3233 | * the duration field, the low-level driver uses this function to receive |
3190 | * the duration field value in little-endian byteorder. | 3234 | * the duration field value in little-endian byteorder. |
3235 | * | ||
3236 | * Return: The duration. | ||
3191 | */ | 3237 | */ |
3192 | __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | 3238 | __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, |
3193 | struct ieee80211_vif *vif, size_t frame_len, | 3239 | struct ieee80211_vif *vif, size_t frame_len, |
@@ -3223,6 +3269,8 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw, | |||
3223 | * If the CTS-to-self is generated in firmware, but the host system must provide | 3269 | * If the CTS-to-self is generated in firmware, but the host system must provide |
3224 | * the duration field, the low-level driver uses this function to receive | 3270 | * the duration field, the low-level driver uses this function to receive |
3225 | * the duration field value in little-endian byteorder. | 3271 | * the duration field value in little-endian byteorder. |
3272 | * | ||
3273 | * Return: The duration. | ||
3226 | */ | 3274 | */ |
3227 | __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | 3275 | __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, |
3228 | struct ieee80211_vif *vif, | 3276 | struct ieee80211_vif *vif, |
@@ -3239,6 +3287,8 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
3239 | * | 3287 | * |
3240 | * Calculate the duration field of some generic frame, given its | 3288 | * Calculate the duration field of some generic frame, given its |
3241 | * length and transmission rate (in 100kbps). | 3289 | * length and transmission rate (in 100kbps). |
3290 | * | ||
3291 | * Return: The duration. | ||
3242 | */ | 3292 | */ |
3243 | __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | 3293 | __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, |
3244 | struct ieee80211_vif *vif, | 3294 | struct ieee80211_vif *vif, |
@@ -3255,9 +3305,10 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | |||
3255 | * hardware/firmware does not implement buffering of broadcast/multicast | 3305 | * hardware/firmware does not implement buffering of broadcast/multicast |
3256 | * frames when power saving is used, 802.11 code buffers them in the host | 3306 | * frames when power saving is used, 802.11 code buffers them in the host |
3257 | * memory. The low-level driver uses this function to fetch next buffered | 3307 | * memory. The low-level driver uses this function to fetch next buffered |
3258 | * frame. In most cases, this is used when generating beacon frame. This | 3308 | * frame. In most cases, this is used when generating beacon frame. |
3259 | * function returns a pointer to the next buffered skb or NULL if no more | 3309 | * |
3260 | * buffered frames are available. | 3310 | * Return: A pointer to the next buffered skb or NULL if no more buffered |
3311 | * frames are available. | ||
3261 | * | 3312 | * |
3262 | * Note: buffered frames are returned only after DTIM beacon frame was | 3313 | * Note: buffered frames are returned only after DTIM beacon frame was |
3263 | * generated with ieee80211_beacon_get() and the low-level driver must thus | 3314 | * generated with ieee80211_beacon_get() and the low-level driver must thus |
@@ -3437,6 +3488,8 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue); | |||
3437 | * @queue: queue number (counted from zero). | 3488 | * @queue: queue number (counted from zero). |
3438 | * | 3489 | * |
3439 | * Drivers should use this function instead of netif_stop_queue. | 3490 | * Drivers should use this function instead of netif_stop_queue. |
3491 | * | ||
3492 | * Return: %true if the queue is stopped. %false otherwise. | ||
3440 | */ | 3493 | */ |
3441 | 3494 | ||
3442 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue); | 3495 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue); |
@@ -3634,7 +3687,9 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra, | |||
3634 | * @vif: virtual interface to look for station on | 3687 | * @vif: virtual interface to look for station on |
3635 | * @addr: station's address | 3688 | * @addr: station's address |
3636 | * | 3689 | * |
3637 | * This function must be called under RCU lock and the | 3690 | * Return: The station, if found. %NULL otherwise. |
3691 | * | ||
3692 | * Note: This function must be called under RCU lock and the | ||
3638 | * resulting pointer is only valid under RCU lock as well. | 3693 | * resulting pointer is only valid under RCU lock as well. |
3639 | */ | 3694 | */ |
3640 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, | 3695 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, |
@@ -3647,7 +3702,9 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, | |||
3647 | * @addr: remote station's address | 3702 | * @addr: remote station's address |
3648 | * @localaddr: local address (vif->sdata->vif.addr). Use NULL for 'any'. | 3703 | * @localaddr: local address (vif->sdata->vif.addr). Use NULL for 'any'. |
3649 | * | 3704 | * |
3650 | * This function must be called under RCU lock and the | 3705 | * Return: The station, if found. %NULL otherwise. |
3706 | * | ||
3707 | * Note: This function must be called under RCU lock and the | ||
3651 | * resulting pointer is only valid under RCU lock as well. | 3708 | * resulting pointer is only valid under RCU lock as well. |
3652 | * | 3709 | * |
3653 | * NOTE: You may pass NULL for localaddr, but then you will just get | 3710 | * NOTE: You may pass NULL for localaddr, but then you will just get |
@@ -3754,6 +3811,11 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw, | |||
3754 | * The iterator will not find a context that's being added (during | 3811 | * The iterator will not find a context that's being added (during |
3755 | * the driver callback to add it) but will find it while it's being | 3812 | * the driver callback to add it) but will find it while it's being |
3756 | * removed. | 3813 | * removed. |
3814 | * | ||
3815 | * Note that during hardware restart, all contexts that existed | ||
3816 | * before the restart are considered already present so will be | ||
3817 | * found while iterating, whether they've been re-added already | ||
3818 | * or not. | ||
3757 | */ | 3819 | */ |
3758 | void ieee80211_iter_chan_contexts_atomic( | 3820 | void ieee80211_iter_chan_contexts_atomic( |
3759 | struct ieee80211_hw *hw, | 3821 | struct ieee80211_hw *hw, |
@@ -3772,7 +3834,9 @@ void ieee80211_iter_chan_contexts_atomic( | |||
3772 | * information. This function must only be called from within the | 3834 | * information. This function must only be called from within the |
3773 | * .bss_info_changed callback function and only in managed mode. The function | 3835 | * .bss_info_changed callback function and only in managed mode. The function |
3774 | * is only useful when the interface is associated, otherwise it will return | 3836 | * is only useful when the interface is associated, otherwise it will return |
3775 | * NULL. | 3837 | * %NULL. |
3838 | * | ||
3839 | * Return: The Probe Request template. %NULL on error. | ||
3776 | */ | 3840 | */ |
3777 | struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | 3841 | struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, |
3778 | struct ieee80211_vif *vif); | 3842 | struct ieee80211_vif *vif); |
@@ -4119,12 +4183,14 @@ void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, | |||
4119 | void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif); | 4183 | void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif); |
4120 | 4184 | ||
4121 | /** | 4185 | /** |
4122 | * ieee80211_ave_rssi - report the average rssi for the specified interface | 4186 | * ieee80211_ave_rssi - report the average RSSI for the specified interface |
4123 | * | 4187 | * |
4124 | * @vif: the specified virtual interface | 4188 | * @vif: the specified virtual interface |
4125 | * | 4189 | * |
4126 | * This function return the average rssi value for the requested interface. | 4190 | * Note: This function assumes that the given vif is valid. |
4127 | * It assumes that the given vif is valid. | 4191 | * |
4192 | * Return: The average RSSI value for the requested interface, or 0 if not | ||
4193 | * applicable. | ||
4128 | */ | 4194 | */ |
4129 | int ieee80211_ave_rssi(struct ieee80211_vif *vif); | 4195 | int ieee80211_ave_rssi(struct ieee80211_vif *vif); |
4130 | 4196 | ||
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index 671953e11575..b87a1692b086 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h | |||
@@ -57,8 +57,10 @@ struct nfc_hci_ops { | |||
57 | int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb); | 57 | int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb); |
58 | int (*check_presence)(struct nfc_hci_dev *hdev, | 58 | int (*check_presence)(struct nfc_hci_dev *hdev, |
59 | struct nfc_target *target); | 59 | struct nfc_target *target); |
60 | void (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, | 60 | int (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, |
61 | struct sk_buff *skb); | 61 | struct sk_buff *skb); |
62 | int (*enable_se)(struct nfc_dev *dev, u32 secure_element); | ||
63 | int (*disable_se)(struct nfc_dev *dev, u32 secure_element); | ||
62 | }; | 64 | }; |
63 | 65 | ||
64 | /* Pipes */ | 66 | /* Pipes */ |
@@ -82,11 +84,23 @@ typedef int (*xmit) (struct sk_buff *skb, void *cb_data); | |||
82 | 84 | ||
83 | #define NFC_HCI_MAX_GATES 256 | 85 | #define NFC_HCI_MAX_GATES 256 |
84 | 86 | ||
87 | /* | ||
88 | * These values can be specified by a driver to indicate it requires some | ||
89 | * adaptation of the HCI standard. | ||
90 | * | ||
91 | * NFC_HCI_QUIRK_SHORT_CLEAR - send HCI_ADM_CLEAR_ALL_PIPE cmd with no params | ||
92 | */ | ||
93 | enum { | ||
94 | NFC_HCI_QUIRK_SHORT_CLEAR = 0, | ||
95 | }; | ||
96 | |||
85 | struct nfc_hci_dev { | 97 | struct nfc_hci_dev { |
86 | struct nfc_dev *ndev; | 98 | struct nfc_dev *ndev; |
87 | 99 | ||
88 | u32 max_data_link_payload; | 100 | u32 max_data_link_payload; |
89 | 101 | ||
102 | bool shutting_down; | ||
103 | |||
90 | struct mutex msg_tx_mutex; | 104 | struct mutex msg_tx_mutex; |
91 | 105 | ||
92 | struct list_head msg_tx_queue; | 106 | struct list_head msg_tx_queue; |
@@ -129,12 +143,16 @@ struct nfc_hci_dev { | |||
129 | 143 | ||
130 | u8 *gb; | 144 | u8 *gb; |
131 | size_t gb_len; | 145 | size_t gb_len; |
146 | |||
147 | unsigned long quirks; | ||
132 | }; | 148 | }; |
133 | 149 | ||
134 | /* hci device allocation */ | 150 | /* hci device allocation */ |
135 | struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, | 151 | struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, |
136 | struct nfc_hci_init_data *init_data, | 152 | struct nfc_hci_init_data *init_data, |
153 | unsigned long quirks, | ||
137 | u32 protocols, | 154 | u32 protocols, |
155 | u32 supported_se, | ||
138 | const char *llc_name, | 156 | const char *llc_name, |
139 | int tx_headroom, | 157 | int tx_headroom, |
140 | int tx_tailroom, | 158 | int tx_tailroom, |
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index d705d8674949..5bc0c460edc0 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h | |||
@@ -147,6 +147,7 @@ struct nci_dev { | |||
147 | /* ----- NCI Devices ----- */ | 147 | /* ----- NCI Devices ----- */ |
148 | struct nci_dev *nci_allocate_device(struct nci_ops *ops, | 148 | struct nci_dev *nci_allocate_device(struct nci_ops *ops, |
149 | __u32 supported_protocols, | 149 | __u32 supported_protocols, |
150 | __u32 supported_se, | ||
150 | int tx_headroom, | 151 | int tx_headroom, |
151 | int tx_tailroom); | 152 | int tx_tailroom); |
152 | void nci_free_device(struct nci_dev *ndev); | 153 | void nci_free_device(struct nci_dev *ndev); |
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index fce80b2f9be7..87a6417fc934 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h | |||
@@ -68,6 +68,8 @@ struct nfc_ops { | |||
68 | void *cb_context); | 68 | void *cb_context); |
69 | int (*tm_send)(struct nfc_dev *dev, struct sk_buff *skb); | 69 | int (*tm_send)(struct nfc_dev *dev, struct sk_buff *skb); |
70 | int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target); | 70 | int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target); |
71 | int (*enable_se)(struct nfc_dev *dev, u32 secure_element); | ||
72 | int (*disable_se)(struct nfc_dev *dev, u32 secure_element); | ||
71 | }; | 73 | }; |
72 | 74 | ||
73 | #define NFC_TARGET_IDX_ANY -1 | 75 | #define NFC_TARGET_IDX_ANY -1 |
@@ -109,12 +111,17 @@ struct nfc_dev { | |||
109 | struct nfc_genl_data genl_data; | 111 | struct nfc_genl_data genl_data; |
110 | u32 supported_protocols; | 112 | u32 supported_protocols; |
111 | 113 | ||
114 | u32 supported_se; | ||
115 | u32 active_se; | ||
116 | |||
112 | int tx_headroom; | 117 | int tx_headroom; |
113 | int tx_tailroom; | 118 | int tx_tailroom; |
114 | 119 | ||
115 | struct timer_list check_pres_timer; | 120 | struct timer_list check_pres_timer; |
116 | struct work_struct check_pres_work; | 121 | struct work_struct check_pres_work; |
117 | 122 | ||
123 | bool shutting_down; | ||
124 | |||
118 | struct nfc_ops *ops; | 125 | struct nfc_ops *ops; |
119 | }; | 126 | }; |
120 | #define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev) | 127 | #define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev) |
@@ -123,6 +130,7 @@ extern struct class nfc_class; | |||
123 | 130 | ||
124 | struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | 131 | struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, |
125 | u32 supported_protocols, | 132 | u32 supported_protocols, |
133 | u32 supported_se, | ||
126 | int tx_headroom, | 134 | int tx_headroom, |
127 | int tx_tailroom); | 135 | int tx_tailroom); |
128 | 136 | ||
diff --git a/include/net/regulatory.h b/include/net/regulatory.h index 7dcaa2794fde..f17ed590d64a 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h | |||
@@ -18,6 +18,7 @@ | |||
18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/rcupdate.h> | ||
21 | 22 | ||
22 | /** | 23 | /** |
23 | * enum environment_cap - Environment parsed from country IE | 24 | * enum environment_cap - Environment parsed from country IE |
@@ -35,6 +36,7 @@ enum environment_cap { | |||
35 | /** | 36 | /** |
36 | * struct regulatory_request - used to keep track of regulatory requests | 37 | * struct regulatory_request - used to keep track of regulatory requests |
37 | * | 38 | * |
39 | * @rcu_head: RCU head struct used to free the request | ||
38 | * @wiphy_idx: this is set if this request's initiator is | 40 | * @wiphy_idx: this is set if this request's initiator is |
39 | * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This | 41 | * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This |
40 | * can be used by the wireless core to deal with conflicts | 42 | * can be used by the wireless core to deal with conflicts |
@@ -72,6 +74,7 @@ enum environment_cap { | |||
72 | * @list: used to insert into the reg_requests_list linked list | 74 | * @list: used to insert into the reg_requests_list linked list |
73 | */ | 75 | */ |
74 | struct regulatory_request { | 76 | struct regulatory_request { |
77 | struct rcu_head rcu_head; | ||
75 | int wiphy_idx; | 78 | int wiphy_idx; |
76 | enum nl80211_reg_initiator initiator; | 79 | enum nl80211_reg_initiator initiator; |
77 | enum nl80211_user_reg_hint_type user_reg_hint_type; | 80 | enum nl80211_user_reg_hint_type user_reg_hint_type; |
@@ -101,6 +104,7 @@ struct ieee80211_reg_rule { | |||
101 | }; | 104 | }; |
102 | 105 | ||
103 | struct ieee80211_regdomain { | 106 | struct ieee80211_regdomain { |
107 | struct rcu_head rcu_head; | ||
104 | u32 n_reg_rules; | 108 | u32 n_reg_rules; |
105 | char alpha2[2]; | 109 | char alpha2[2]; |
106 | u8 dfs_region; | 110 | u8 dfs_region; |
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index 0e63cee8d810..7969f46f1bb3 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h | |||
@@ -5,20 +5,17 @@ | |||
5 | * Lauro Ramos Venancio <lauro.venancio@openbossa.org> | 5 | * Lauro Ramos Venancio <lauro.venancio@openbossa.org> |
6 | * Aloisio Almeida Jr <aloisio.almeida@openbossa.org> | 6 | * Aloisio Almeida Jr <aloisio.almeida@openbossa.org> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * Permission to use, copy, modify, and/or distribute this software for any |
9 | * it under the terms of the GNU General Public License as published by | 9 | * purpose with or without fee is hereby granted, provided that the above |
10 | * the Free Software Foundation; either version 2 of the License, or | 10 | * copyright notice and this permission notice appear in all copies. |
11 | * (at your option) any later version. | ||
12 | * | 11 | * |
13 | * This program is distributed in the hope that it will be useful, | 12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
16 | * GNU General Public License for more details. | 15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
17 | * | 16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
18 | * You should have received a copy of the GNU General Public License | 17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
19 | * along with this program; if not, write to the | 18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
20 | * Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | */ | 19 | */ |
23 | 20 | ||
24 | #ifndef __LINUX_NFC_H | 21 | #ifndef __LINUX_NFC_H |
@@ -67,6 +64,11 @@ | |||
67 | * subsequent CONNECT and CC messages. | 64 | * subsequent CONNECT and CC messages. |
68 | * If one of the passed parameters is wrong none is set and -EINVAL is | 65 | * If one of the passed parameters is wrong none is set and -EINVAL is |
69 | * returned. | 66 | * returned. |
67 | * @NFC_CMD_ENABLE_SE: Enable the physical link to a specific secure element. | ||
68 | * Once enabled a secure element will handle card emulation mode, i.e. | ||
69 | * starting a poll from a device which has a secure element enabled means | ||
70 | * we want to do SE based card emulation. | ||
71 | * @NFC_CMD_DISABLE_SE: Disable the physical link to a specific secure element. | ||
70 | */ | 72 | */ |
71 | enum nfc_commands { | 73 | enum nfc_commands { |
72 | NFC_CMD_UNSPEC, | 74 | NFC_CMD_UNSPEC, |
@@ -86,6 +88,8 @@ enum nfc_commands { | |||
86 | NFC_EVENT_TM_DEACTIVATED, | 88 | NFC_EVENT_TM_DEACTIVATED, |
87 | NFC_CMD_LLC_GET_PARAMS, | 89 | NFC_CMD_LLC_GET_PARAMS, |
88 | NFC_CMD_LLC_SET_PARAMS, | 90 | NFC_CMD_LLC_SET_PARAMS, |
91 | NFC_CMD_ENABLE_SE, | ||
92 | NFC_CMD_DISABLE_SE, | ||
89 | /* private: internal use only */ | 93 | /* private: internal use only */ |
90 | __NFC_CMD_AFTER_LAST | 94 | __NFC_CMD_AFTER_LAST |
91 | }; | 95 | }; |
@@ -114,6 +118,7 @@ enum nfc_commands { | |||
114 | * @NFC_ATTR_LLC_PARAM_LTO: Link TimeOut parameter | 118 | * @NFC_ATTR_LLC_PARAM_LTO: Link TimeOut parameter |
115 | * @NFC_ATTR_LLC_PARAM_RW: Receive Window size parameter | 119 | * @NFC_ATTR_LLC_PARAM_RW: Receive Window size parameter |
116 | * @NFC_ATTR_LLC_PARAM_MIUX: MIU eXtension parameter | 120 | * @NFC_ATTR_LLC_PARAM_MIUX: MIU eXtension parameter |
121 | * @NFC_ATTR_SE: Available Secure Elements | ||
117 | */ | 122 | */ |
118 | enum nfc_attrs { | 123 | enum nfc_attrs { |
119 | NFC_ATTR_UNSPEC, | 124 | NFC_ATTR_UNSPEC, |
@@ -134,6 +139,7 @@ enum nfc_attrs { | |||
134 | NFC_ATTR_LLC_PARAM_LTO, | 139 | NFC_ATTR_LLC_PARAM_LTO, |
135 | NFC_ATTR_LLC_PARAM_RW, | 140 | NFC_ATTR_LLC_PARAM_RW, |
136 | NFC_ATTR_LLC_PARAM_MIUX, | 141 | NFC_ATTR_LLC_PARAM_MIUX, |
142 | NFC_ATTR_SE, | ||
137 | /* private: internal use only */ | 143 | /* private: internal use only */ |
138 | __NFC_ATTR_AFTER_LAST | 144 | __NFC_ATTR_AFTER_LAST |
139 | }; | 145 | }; |
@@ -172,6 +178,11 @@ enum nfc_attrs { | |||
172 | #define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP) | 178 | #define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP) |
173 | #define NFC_PROTO_ISO14443_B_MASK (1 << NFC_PROTO_ISO14443_B) | 179 | #define NFC_PROTO_ISO14443_B_MASK (1 << NFC_PROTO_ISO14443_B) |
174 | 180 | ||
181 | /* NFC Secure Elements */ | ||
182 | #define NFC_SE_NONE 0x0 | ||
183 | #define NFC_SE_UICC 0x1 | ||
184 | #define NFC_SE_EMBEDDED 0x2 | ||
185 | |||
175 | struct sockaddr_nfc { | 186 | struct sockaddr_nfc { |
176 | sa_family_t sa_family; | 187 | sa_family_t sa_family; |
177 | __u32 dev_idx; | 188 | __u32 dev_idx; |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index e3e19f8b16f2..e6eeb4ba5dc5 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -374,8 +374,8 @@ | |||
374 | * requests to connect to a specified network but without separating | 374 | * requests to connect to a specified network but without separating |
375 | * auth and assoc steps. For this, you need to specify the SSID in a | 375 | * auth and assoc steps. For this, you need to specify the SSID in a |
376 | * %NL80211_ATTR_SSID attribute, and can optionally specify the association | 376 | * %NL80211_ATTR_SSID attribute, and can optionally specify the association |
377 | * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC, | 377 | * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, |
378 | * %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, | 378 | * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, |
379 | * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and | 379 | * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and |
380 | * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT. | 380 | * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT. |
381 | * Background scan period can optionally be | 381 | * Background scan period can optionally be |
@@ -958,7 +958,7 @@ enum nl80211_commands { | |||
958 | * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is | 958 | * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is |
959 | * used for the association (&enum nl80211_mfp, represented as a u32); | 959 | * used for the association (&enum nl80211_mfp, represented as a u32); |
960 | * this attribute can be used | 960 | * this attribute can be used |
961 | * with %NL80211_CMD_ASSOCIATE request | 961 | * with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests |
962 | * | 962 | * |
963 | * @NL80211_ATTR_STA_FLAGS2: Attribute containing a | 963 | * @NL80211_ATTR_STA_FLAGS2: Attribute containing a |
964 | * &struct nl80211_sta_flag_update. | 964 | * &struct nl80211_sta_flag_update. |
@@ -1310,6 +1310,9 @@ enum nl80211_commands { | |||
1310 | * if not given in START_AP 0 is assumed, if not given in SET_BSS | 1310 | * if not given in START_AP 0 is assumed, if not given in SET_BSS |
1311 | * no change is made. | 1311 | * no change is made. |
1312 | * | 1312 | * |
1313 | * @NL80211_ATTR_LOCAL_MESH_POWER_MODE: local mesh STA link-specific power mode | ||
1314 | * defined in &enum nl80211_mesh_power_mode. | ||
1315 | * | ||
1313 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1316 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1314 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1317 | * @__NL80211_ATTR_AFTER_LAST: internal use |
1315 | */ | 1318 | */ |
@@ -1580,6 +1583,8 @@ enum nl80211_attrs { | |||
1580 | NL80211_ATTR_P2P_CTWINDOW, | 1583 | NL80211_ATTR_P2P_CTWINDOW, |
1581 | NL80211_ATTR_P2P_OPPPS, | 1584 | NL80211_ATTR_P2P_OPPPS, |
1582 | 1585 | ||
1586 | NL80211_ATTR_LOCAL_MESH_POWER_MODE, | ||
1587 | |||
1583 | /* add attributes here, update the policy in nl80211.c */ | 1588 | /* add attributes here, update the policy in nl80211.c */ |
1584 | 1589 | ||
1585 | __NL80211_ATTR_AFTER_LAST, | 1590 | __NL80211_ATTR_AFTER_LAST, |
@@ -1697,6 +1702,9 @@ enum nl80211_iftype { | |||
1697 | * flag can't be changed, it is only valid while adding a station, and | 1702 | * flag can't be changed, it is only valid while adding a station, and |
1698 | * attempts to change it will silently be ignored (rather than rejected | 1703 | * attempts to change it will silently be ignored (rather than rejected |
1699 | * as errors.) | 1704 | * as errors.) |
1705 | * @NL80211_STA_FLAG_ASSOCIATED: station is associated; used with drivers | ||
1706 | * that support %NL80211_FEATURE_FULL_AP_CLIENT_STATE to transition a | ||
1707 | * previously added station into associated state | ||
1700 | * @NL80211_STA_FLAG_MAX: highest station flag number currently defined | 1708 | * @NL80211_STA_FLAG_MAX: highest station flag number currently defined |
1701 | * @__NL80211_STA_FLAG_AFTER_LAST: internal use | 1709 | * @__NL80211_STA_FLAG_AFTER_LAST: internal use |
1702 | */ | 1710 | */ |
@@ -1708,6 +1716,7 @@ enum nl80211_sta_flags { | |||
1708 | NL80211_STA_FLAG_MFP, | 1716 | NL80211_STA_FLAG_MFP, |
1709 | NL80211_STA_FLAG_AUTHENTICATED, | 1717 | NL80211_STA_FLAG_AUTHENTICATED, |
1710 | NL80211_STA_FLAG_TDLS_PEER, | 1718 | NL80211_STA_FLAG_TDLS_PEER, |
1719 | NL80211_STA_FLAG_ASSOCIATED, | ||
1711 | 1720 | ||
1712 | /* keep last */ | 1721 | /* keep last */ |
1713 | __NL80211_STA_FLAG_AFTER_LAST, | 1722 | __NL80211_STA_FLAG_AFTER_LAST, |
@@ -1834,6 +1843,10 @@ enum nl80211_sta_bss_param { | |||
1834 | * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update. | 1843 | * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update. |
1835 | * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32) | 1844 | * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32) |
1836 | * @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64) | 1845 | * @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64) |
1846 | * @NL80211_STA_INFO_LOCAL_PM: local mesh STA link-specific power mode | ||
1847 | * @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode | ||
1848 | * @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards | ||
1849 | * non-peer STA | ||
1837 | * @__NL80211_STA_INFO_AFTER_LAST: internal | 1850 | * @__NL80211_STA_INFO_AFTER_LAST: internal |
1838 | * @NL80211_STA_INFO_MAX: highest possible station info attribute | 1851 | * @NL80211_STA_INFO_MAX: highest possible station info attribute |
1839 | */ | 1852 | */ |
@@ -1858,6 +1871,9 @@ enum nl80211_sta_info { | |||
1858 | NL80211_STA_INFO_STA_FLAGS, | 1871 | NL80211_STA_INFO_STA_FLAGS, |
1859 | NL80211_STA_INFO_BEACON_LOSS, | 1872 | NL80211_STA_INFO_BEACON_LOSS, |
1860 | NL80211_STA_INFO_T_OFFSET, | 1873 | NL80211_STA_INFO_T_OFFSET, |
1874 | NL80211_STA_INFO_LOCAL_PM, | ||
1875 | NL80211_STA_INFO_PEER_PM, | ||
1876 | NL80211_STA_INFO_NONPEER_PM, | ||
1861 | 1877 | ||
1862 | /* keep last */ | 1878 | /* keep last */ |
1863 | __NL80211_STA_INFO_AFTER_LAST, | 1879 | __NL80211_STA_INFO_AFTER_LAST, |
@@ -2249,6 +2265,34 @@ enum nl80211_mntr_flags { | |||
2249 | }; | 2265 | }; |
2250 | 2266 | ||
2251 | /** | 2267 | /** |
2268 | * enum nl80211_mesh_power_mode - mesh power save modes | ||
2269 | * | ||
2270 | * @NL80211_MESH_POWER_UNKNOWN: The mesh power mode of the mesh STA is | ||
2271 | * not known or has not been set yet. | ||
2272 | * @NL80211_MESH_POWER_ACTIVE: Active mesh power mode. The mesh STA is | ||
2273 | * in Awake state all the time. | ||
2274 | * @NL80211_MESH_POWER_LIGHT_SLEEP: Light sleep mode. The mesh STA will | ||
2275 | * alternate between Active and Doze states, but will wake up for | ||
2276 | * neighbor's beacons. | ||
2277 | * @NL80211_MESH_POWER_DEEP_SLEEP: Deep sleep mode. The mesh STA will | ||
2278 | * alternate between Active and Doze states, but may not wake up | ||
2279 | * for neighbor's beacons. | ||
2280 | * | ||
2281 | * @__NL80211_MESH_POWER_AFTER_LAST - internal use | ||
2282 | * @NL80211_MESH_POWER_MAX - highest possible power save level | ||
2283 | */ | ||
2284 | |||
2285 | enum nl80211_mesh_power_mode { | ||
2286 | NL80211_MESH_POWER_UNKNOWN, | ||
2287 | NL80211_MESH_POWER_ACTIVE, | ||
2288 | NL80211_MESH_POWER_LIGHT_SLEEP, | ||
2289 | NL80211_MESH_POWER_DEEP_SLEEP, | ||
2290 | |||
2291 | __NL80211_MESH_POWER_AFTER_LAST, | ||
2292 | NL80211_MESH_POWER_MAX = __NL80211_MESH_POWER_AFTER_LAST - 1 | ||
2293 | }; | ||
2294 | |||
2295 | /** | ||
2252 | * enum nl80211_meshconf_params - mesh configuration parameters | 2296 | * enum nl80211_meshconf_params - mesh configuration parameters |
2253 | * | 2297 | * |
2254 | * Mesh configuration parameters. These can be changed while the mesh is | 2298 | * Mesh configuration parameters. These can be changed while the mesh is |
@@ -2342,6 +2386,11 @@ enum nl80211_mntr_flags { | |||
2342 | * (in TUs) during which a mesh STA can send only one Action frame | 2386 | * (in TUs) during which a mesh STA can send only one Action frame |
2343 | * containing a PREQ element for root path confirmation. | 2387 | * containing a PREQ element for root path confirmation. |
2344 | * | 2388 | * |
2389 | * @NL80211_MESHCONF_POWER_MODE: Default mesh power mode for new peer links. | ||
2390 | * type &enum nl80211_mesh_power_mode (u32) | ||
2391 | * | ||
2392 | * @NL80211_MESHCONF_AWAKE_WINDOW: awake window duration (in TUs) | ||
2393 | * | ||
2345 | * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use | 2394 | * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use |
2346 | */ | 2395 | */ |
2347 | enum nl80211_meshconf_params { | 2396 | enum nl80211_meshconf_params { |
@@ -2371,6 +2420,8 @@ enum nl80211_meshconf_params { | |||
2371 | NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, | 2420 | NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, |
2372 | NL80211_MESHCONF_HWMP_ROOT_INTERVAL, | 2421 | NL80211_MESHCONF_HWMP_ROOT_INTERVAL, |
2373 | NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, | 2422 | NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, |
2423 | NL80211_MESHCONF_POWER_MODE, | ||
2424 | NL80211_MESHCONF_AWAKE_WINDOW, | ||
2374 | 2425 | ||
2375 | /* keep last */ | 2426 | /* keep last */ |
2376 | __NL80211_MESHCONF_ATTR_AFTER_LAST, | 2427 | __NL80211_MESHCONF_ATTR_AFTER_LAST, |
@@ -2933,6 +2984,8 @@ enum nl80211_iface_limit_attrs { | |||
2933 | * the infrastructure network's beacon interval. | 2984 | * the infrastructure network's beacon interval. |
2934 | * @NL80211_IFACE_COMB_NUM_CHANNELS: u32 attribute specifying how many | 2985 | * @NL80211_IFACE_COMB_NUM_CHANNELS: u32 attribute specifying how many |
2935 | * different channels may be used within this group. | 2986 | * different channels may be used within this group. |
2987 | * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap | ||
2988 | * of supported channel widths for radar detection. | ||
2936 | * @NUM_NL80211_IFACE_COMB: number of attributes | 2989 | * @NUM_NL80211_IFACE_COMB: number of attributes |
2937 | * @MAX_NL80211_IFACE_COMB: highest attribute number | 2990 | * @MAX_NL80211_IFACE_COMB: highest attribute number |
2938 | * | 2991 | * |
@@ -2965,6 +3018,7 @@ enum nl80211_if_combination_attrs { | |||
2965 | NL80211_IFACE_COMB_MAXNUM, | 3018 | NL80211_IFACE_COMB_MAXNUM, |
2966 | NL80211_IFACE_COMB_STA_AP_BI_MATCH, | 3019 | NL80211_IFACE_COMB_STA_AP_BI_MATCH, |
2967 | NL80211_IFACE_COMB_NUM_CHANNELS, | 3020 | NL80211_IFACE_COMB_NUM_CHANNELS, |
3021 | NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, | ||
2968 | 3022 | ||
2969 | /* keep last */ | 3023 | /* keep last */ |
2970 | NUM_NL80211_IFACE_COMB, | 3024 | NUM_NL80211_IFACE_COMB, |
@@ -3140,6 +3194,17 @@ enum nl80211_ap_sme_features { | |||
3140 | * setting | 3194 | * setting |
3141 | * @NL80211_FEATURE_P2P_GO_OPPPS: P2P GO implementation supports opportunistic | 3195 | * @NL80211_FEATURE_P2P_GO_OPPPS: P2P GO implementation supports opportunistic |
3142 | * powersave | 3196 | * powersave |
3197 | * @NL80211_FEATURE_FULL_AP_CLIENT_STATE: The driver supports full state | ||
3198 | * transitions for AP clients. Without this flag (and if the driver | ||
3199 | * doesn't have the AP SME in the device) the driver supports adding | ||
3200 | * stations only when they're associated and adds them in associated | ||
3201 | * state (to later be transitioned into authorized), with this flag | ||
3202 | * they should be added before even sending the authentication reply | ||
3203 | * and then transitioned into authenticated, associated and authorized | ||
3204 | * states using station flags. | ||
3205 | * Note that even for drivers that support this, the default is to add | ||
3206 | * stations in authenticated/associated state, so to add unauthenticated | ||
3207 | * stations the authenticated/associated bits have to be set in the mask. | ||
3143 | */ | 3208 | */ |
3144 | enum nl80211_feature_flags { | 3209 | enum nl80211_feature_flags { |
3145 | NL80211_FEATURE_SK_TX_STATUS = 1 << 0, | 3210 | NL80211_FEATURE_SK_TX_STATUS = 1 << 0, |
@@ -3155,6 +3220,7 @@ enum nl80211_feature_flags { | |||
3155 | NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10, | 3220 | NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10, |
3156 | NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11, | 3221 | NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11, |
3157 | NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12, | 3222 | NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12, |
3223 | NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 13, | ||
3158 | }; | 3224 | }; |
3159 | 3225 | ||
3160 | /** | 3226 | /** |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 596660d37c5e..0f78e34220c9 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -2810,14 +2810,6 @@ static void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
2810 | if (conn) { | 2810 | if (conn) { |
2811 | hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF); | 2811 | hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF); |
2812 | 2812 | ||
2813 | hci_dev_lock(hdev); | ||
2814 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && | ||
2815 | !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) | ||
2816 | mgmt_device_connected(hdev, &conn->dst, conn->type, | ||
2817 | conn->dst_type, 0, NULL, 0, | ||
2818 | conn->dev_class); | ||
2819 | hci_dev_unlock(hdev); | ||
2820 | |||
2821 | /* Send to upper protocol */ | 2813 | /* Send to upper protocol */ |
2822 | l2cap_recv_acldata(conn, skb, flags); | 2814 | l2cap_recv_acldata(conn, skb, flags); |
2823 | return; | 2815 | return; |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 705078a0cc39..81b44481d0d9 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -2688,7 +2688,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2688 | if (ev->opcode != HCI_OP_NOP) | 2688 | if (ev->opcode != HCI_OP_NOP) |
2689 | del_timer(&hdev->cmd_timer); | 2689 | del_timer(&hdev->cmd_timer); |
2690 | 2690 | ||
2691 | if (ev->ncmd) { | 2691 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { |
2692 | atomic_set(&hdev->cmd_cnt, 1); | 2692 | atomic_set(&hdev->cmd_cnt, 1); |
2693 | if (!skb_queue_empty(&hdev->cmd_q)) | 2693 | if (!skb_queue_empty(&hdev->cmd_q)) |
2694 | queue_work(hdev->workqueue, &hdev->cmd_work); | 2694 | queue_work(hdev->workqueue, &hdev->cmd_work); |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index b2bcbe2dc328..a7352ff3fd1e 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -931,7 +931,7 @@ static int hidp_setup_hid(struct hidp_session *session, | |||
931 | hid->version = req->version; | 931 | hid->version = req->version; |
932 | hid->country = req->country; | 932 | hid->country = req->country; |
933 | 933 | ||
934 | strncpy(hid->name, req->name, 128); | 934 | strncpy(hid->name, req->name, sizeof(req->name) - 1); |
935 | 935 | ||
936 | snprintf(hid->phys, sizeof(hid->phys), "%pMR", | 936 | snprintf(hid->phys, sizeof(hid->phys), "%pMR", |
937 | &bt_sk(session->ctrl_sock->sk)->src); | 937 | &bt_sk(session->ctrl_sock->sk)->src); |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 2c78208d793e..22e658322845 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -3727,6 +3727,17 @@ sendresp: | |||
3727 | static int l2cap_connect_req(struct l2cap_conn *conn, | 3727 | static int l2cap_connect_req(struct l2cap_conn *conn, |
3728 | struct l2cap_cmd_hdr *cmd, u8 *data) | 3728 | struct l2cap_cmd_hdr *cmd, u8 *data) |
3729 | { | 3729 | { |
3730 | struct hci_dev *hdev = conn->hcon->hdev; | ||
3731 | struct hci_conn *hcon = conn->hcon; | ||
3732 | |||
3733 | hci_dev_lock(hdev); | ||
3734 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && | ||
3735 | !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) | ||
3736 | mgmt_device_connected(hdev, &hcon->dst, hcon->type, | ||
3737 | hcon->dst_type, 0, NULL, 0, | ||
3738 | hcon->dev_class); | ||
3739 | hci_dev_unlock(hdev); | ||
3740 | |||
3730 | l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); | 3741 | l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); |
3731 | return 0; | 3742 | return 0; |
3732 | } | 3743 | } |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 531a93d613d4..57f250c20e39 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -352,7 +352,7 @@ static void __sco_sock_close(struct sock *sk) | |||
352 | 352 | ||
353 | case BT_CONNECTED: | 353 | case BT_CONNECTED: |
354 | case BT_CONFIG: | 354 | case BT_CONFIG: |
355 | if (sco_pi(sk)->conn) { | 355 | if (sco_pi(sk)->conn->hcon) { |
356 | sk->sk_state = BT_DISCONN; | 356 | sk->sk_state = BT_DISCONN; |
357 | sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT); | 357 | sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT); |
358 | hci_conn_put(sco_pi(sk)->conn->hcon); | 358 | hci_conn_put(sco_pi(sk)->conn->hcon); |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index eb9df22418f0..2f0ccbc5f13e 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -149,16 +149,133 @@ void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, | |||
149 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx); | 149 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx); |
150 | } | 150 | } |
151 | 151 | ||
152 | static inline int ieee80211_ac_from_tid(int tid) | ||
153 | { | ||
154 | return ieee802_1d_to_ac[tid & 7]; | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * When multiple aggregation sessions on multiple stations | ||
159 | * are being created/destroyed simultaneously, we need to | ||
160 | * refcount the global queue stop caused by that in order | ||
161 | * to not get into a situation where one of the aggregation | ||
162 | * setup or teardown re-enables queues before the other is | ||
163 | * ready to handle that. | ||
164 | * | ||
165 | * These two functions take care of this issue by keeping | ||
166 | * a global "agg_queue_stop" refcount. | ||
167 | */ | ||
168 | static void __acquires(agg_queue) | ||
169 | ieee80211_stop_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) | ||
170 | { | ||
171 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; | ||
172 | |||
173 | if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1) | ||
174 | ieee80211_stop_queue_by_reason( | ||
175 | &sdata->local->hw, queue, | ||
176 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | ||
177 | __acquire(agg_queue); | ||
178 | } | ||
179 | |||
180 | static void __releases(agg_queue) | ||
181 | ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) | ||
182 | { | ||
183 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; | ||
184 | |||
185 | if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0) | ||
186 | ieee80211_wake_queue_by_reason( | ||
187 | &sdata->local->hw, queue, | ||
188 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | ||
189 | __release(agg_queue); | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * splice packets from the STA's pending to the local pending, | ||
194 | * requires a call to ieee80211_agg_splice_finish later | ||
195 | */ | ||
196 | static void __acquires(agg_queue) | ||
197 | ieee80211_agg_splice_packets(struct ieee80211_sub_if_data *sdata, | ||
198 | struct tid_ampdu_tx *tid_tx, u16 tid) | ||
199 | { | ||
200 | struct ieee80211_local *local = sdata->local; | ||
201 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; | ||
202 | unsigned long flags; | ||
203 | |||
204 | ieee80211_stop_queue_agg(sdata, tid); | ||
205 | |||
206 | if (WARN(!tid_tx, | ||
207 | "TID %d gone but expected when splicing aggregates from the pending queue\n", | ||
208 | tid)) | ||
209 | return; | ||
210 | |||
211 | if (!skb_queue_empty(&tid_tx->pending)) { | ||
212 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
213 | /* copy over remaining packets */ | ||
214 | skb_queue_splice_tail_init(&tid_tx->pending, | ||
215 | &local->pending[queue]); | ||
216 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | static void __releases(agg_queue) | ||
221 | ieee80211_agg_splice_finish(struct ieee80211_sub_if_data *sdata, u16 tid) | ||
222 | { | ||
223 | ieee80211_wake_queue_agg(sdata, tid); | ||
224 | } | ||
225 | |||
226 | static void ieee80211_remove_tid_tx(struct sta_info *sta, int tid) | ||
227 | { | ||
228 | struct tid_ampdu_tx *tid_tx; | ||
229 | |||
230 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | ||
231 | lockdep_assert_held(&sta->lock); | ||
232 | |||
233 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | ||
234 | |||
235 | /* | ||
236 | * When we get here, the TX path will not be lockless any more wrt. | ||
237 | * aggregation, since the OPERATIONAL bit has long been cleared. | ||
238 | * Thus it will block on getting the lock, if it occurs. So if we | ||
239 | * stop the queue now, we will not get any more packets, and any | ||
240 | * that might be being processed will wait for us here, thereby | ||
241 | * guaranteeing that no packets go to the tid_tx pending queue any | ||
242 | * more. | ||
243 | */ | ||
244 | |||
245 | ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid); | ||
246 | |||
247 | /* future packets must not find the tid_tx struct any more */ | ||
248 | ieee80211_assign_tid_tx(sta, tid, NULL); | ||
249 | |||
250 | ieee80211_agg_splice_finish(sta->sdata, tid); | ||
251 | |||
252 | kfree_rcu(tid_tx, rcu_head); | ||
253 | } | ||
254 | |||
152 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 255 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
153 | enum ieee80211_back_parties initiator, | 256 | enum ieee80211_agg_stop_reason reason) |
154 | bool tx) | ||
155 | { | 257 | { |
156 | struct ieee80211_local *local = sta->local; | 258 | struct ieee80211_local *local = sta->local; |
157 | struct tid_ampdu_tx *tid_tx; | 259 | struct tid_ampdu_tx *tid_tx; |
260 | enum ieee80211_ampdu_mlme_action action; | ||
158 | int ret; | 261 | int ret; |
159 | 262 | ||
160 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | 263 | lockdep_assert_held(&sta->ampdu_mlme.mtx); |
161 | 264 | ||
265 | switch (reason) { | ||
266 | case AGG_STOP_DECLINED: | ||
267 | case AGG_STOP_LOCAL_REQUEST: | ||
268 | case AGG_STOP_PEER_REQUEST: | ||
269 | action = IEEE80211_AMPDU_TX_STOP_CONT; | ||
270 | break; | ||
271 | case AGG_STOP_DESTROY_STA: | ||
272 | action = IEEE80211_AMPDU_TX_STOP_FLUSH; | ||
273 | break; | ||
274 | default: | ||
275 | WARN_ON_ONCE(1); | ||
276 | return -EINVAL; | ||
277 | } | ||
278 | |||
162 | spin_lock_bh(&sta->lock); | 279 | spin_lock_bh(&sta->lock); |
163 | 280 | ||
164 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 281 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
@@ -167,10 +284,19 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
167 | return -ENOENT; | 284 | return -ENOENT; |
168 | } | 285 | } |
169 | 286 | ||
170 | /* if we're already stopping ignore any new requests to stop */ | 287 | /* |
288 | * if we're already stopping ignore any new requests to stop | ||
289 | * unless we're destroying it in which case notify the driver | ||
290 | */ | ||
171 | if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | 291 | if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { |
172 | spin_unlock_bh(&sta->lock); | 292 | spin_unlock_bh(&sta->lock); |
173 | return -EALREADY; | 293 | if (reason != AGG_STOP_DESTROY_STA) |
294 | return -EALREADY; | ||
295 | ret = drv_ampdu_action(local, sta->sdata, | ||
296 | IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, | ||
297 | &sta->sta, tid, NULL, 0); | ||
298 | WARN_ON_ONCE(ret); | ||
299 | goto remove_tid_tx; | ||
174 | } | 300 | } |
175 | 301 | ||
176 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { | 302 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { |
@@ -212,11 +338,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
212 | */ | 338 | */ |
213 | synchronize_net(); | 339 | synchronize_net(); |
214 | 340 | ||
215 | tid_tx->stop_initiator = initiator; | 341 | tid_tx->stop_initiator = reason == AGG_STOP_PEER_REQUEST ? |
216 | tid_tx->tx_stop = tx; | 342 | WLAN_BACK_RECIPIENT : |
343 | WLAN_BACK_INITIATOR; | ||
344 | tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST; | ||
217 | 345 | ||
218 | ret = drv_ampdu_action(local, sta->sdata, | 346 | ret = drv_ampdu_action(local, sta->sdata, action, |
219 | IEEE80211_AMPDU_TX_STOP, | ||
220 | &sta->sta, tid, NULL, 0); | 347 | &sta->sta, tid, NULL, 0); |
221 | 348 | ||
222 | /* HW shall not deny going back to legacy */ | 349 | /* HW shall not deny going back to legacy */ |
@@ -227,7 +354,14 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
227 | */ | 354 | */ |
228 | } | 355 | } |
229 | 356 | ||
230 | return ret; | 357 | if (reason == AGG_STOP_DESTROY_STA) { |
358 | remove_tid_tx: | ||
359 | spin_lock_bh(&sta->lock); | ||
360 | ieee80211_remove_tid_tx(sta, tid); | ||
361 | spin_unlock_bh(&sta->lock); | ||
362 | } | ||
363 | |||
364 | return 0; | ||
231 | } | 365 | } |
232 | 366 | ||
233 | /* | 367 | /* |
@@ -264,80 +398,6 @@ static void sta_addba_resp_timer_expired(unsigned long data) | |||
264 | rcu_read_unlock(); | 398 | rcu_read_unlock(); |
265 | } | 399 | } |
266 | 400 | ||
267 | static inline int ieee80211_ac_from_tid(int tid) | ||
268 | { | ||
269 | return ieee802_1d_to_ac[tid & 7]; | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * When multiple aggregation sessions on multiple stations | ||
274 | * are being created/destroyed simultaneously, we need to | ||
275 | * refcount the global queue stop caused by that in order | ||
276 | * to not get into a situation where one of the aggregation | ||
277 | * setup or teardown re-enables queues before the other is | ||
278 | * ready to handle that. | ||
279 | * | ||
280 | * These two functions take care of this issue by keeping | ||
281 | * a global "agg_queue_stop" refcount. | ||
282 | */ | ||
283 | static void __acquires(agg_queue) | ||
284 | ieee80211_stop_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) | ||
285 | { | ||
286 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; | ||
287 | |||
288 | if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1) | ||
289 | ieee80211_stop_queue_by_reason( | ||
290 | &sdata->local->hw, queue, | ||
291 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | ||
292 | __acquire(agg_queue); | ||
293 | } | ||
294 | |||
295 | static void __releases(agg_queue) | ||
296 | ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) | ||
297 | { | ||
298 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; | ||
299 | |||
300 | if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0) | ||
301 | ieee80211_wake_queue_by_reason( | ||
302 | &sdata->local->hw, queue, | ||
303 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | ||
304 | __release(agg_queue); | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * splice packets from the STA's pending to the local pending, | ||
309 | * requires a call to ieee80211_agg_splice_finish later | ||
310 | */ | ||
311 | static void __acquires(agg_queue) | ||
312 | ieee80211_agg_splice_packets(struct ieee80211_sub_if_data *sdata, | ||
313 | struct tid_ampdu_tx *tid_tx, u16 tid) | ||
314 | { | ||
315 | struct ieee80211_local *local = sdata->local; | ||
316 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; | ||
317 | unsigned long flags; | ||
318 | |||
319 | ieee80211_stop_queue_agg(sdata, tid); | ||
320 | |||
321 | if (WARN(!tid_tx, | ||
322 | "TID %d gone but expected when splicing aggregates from the pending queue\n", | ||
323 | tid)) | ||
324 | return; | ||
325 | |||
326 | if (!skb_queue_empty(&tid_tx->pending)) { | ||
327 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
328 | /* copy over remaining packets */ | ||
329 | skb_queue_splice_tail_init(&tid_tx->pending, | ||
330 | &local->pending[queue]); | ||
331 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
332 | } | ||
333 | } | ||
334 | |||
335 | static void __releases(agg_queue) | ||
336 | ieee80211_agg_splice_finish(struct ieee80211_sub_if_data *sdata, u16 tid) | ||
337 | { | ||
338 | ieee80211_wake_queue_agg(sdata, tid); | ||
339 | } | ||
340 | |||
341 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | 401 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) |
342 | { | 402 | { |
343 | struct tid_ampdu_tx *tid_tx; | 403 | struct tid_ampdu_tx *tid_tx; |
@@ -660,14 +720,13 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
660 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); | 720 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); |
661 | 721 | ||
662 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 722 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
663 | enum ieee80211_back_parties initiator, | 723 | enum ieee80211_agg_stop_reason reason) |
664 | bool tx) | ||
665 | { | 724 | { |
666 | int ret; | 725 | int ret; |
667 | 726 | ||
668 | mutex_lock(&sta->ampdu_mlme.mtx); | 727 | mutex_lock(&sta->ampdu_mlme.mtx); |
669 | 728 | ||
670 | ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator, tx); | 729 | ret = ___ieee80211_stop_tx_ba_session(sta, tid, reason); |
671 | 730 | ||
672 | mutex_unlock(&sta->ampdu_mlme.mtx); | 731 | mutex_unlock(&sta->ampdu_mlme.mtx); |
673 | 732 | ||
@@ -751,24 +810,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
751 | ieee80211_send_delba(sta->sdata, ra, tid, | 810 | ieee80211_send_delba(sta->sdata, ra, tid, |
752 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | 811 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); |
753 | 812 | ||
754 | /* | 813 | ieee80211_remove_tid_tx(sta, tid); |
755 | * When we get here, the TX path will not be lockless any more wrt. | ||
756 | * aggregation, since the OPERATIONAL bit has long been cleared. | ||
757 | * Thus it will block on getting the lock, if it occurs. So if we | ||
758 | * stop the queue now, we will not get any more packets, and any | ||
759 | * that might be being processed will wait for us here, thereby | ||
760 | * guaranteeing that no packets go to the tid_tx pending queue any | ||
761 | * more. | ||
762 | */ | ||
763 | |||
764 | ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid); | ||
765 | |||
766 | /* future packets must not find the tid_tx struct any more */ | ||
767 | ieee80211_assign_tid_tx(sta, tid, NULL); | ||
768 | |||
769 | ieee80211_agg_splice_finish(sta->sdata, tid); | ||
770 | |||
771 | kfree_rcu(tid_tx, rcu_head); | ||
772 | 814 | ||
773 | unlock_sta: | 815 | unlock_sta: |
774 | spin_unlock_bh(&sta->lock); | 816 | spin_unlock_bh(&sta->lock); |
@@ -868,8 +910,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
868 | } | 910 | } |
869 | 911 | ||
870 | } else { | 912 | } else { |
871 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, | 913 | ___ieee80211_stop_tx_ba_session(sta, tid, AGG_STOP_DECLINED); |
872 | false); | ||
873 | } | 914 | } |
874 | 915 | ||
875 | out: | 916 | out: |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 47e0aca614b7..661b878bd19c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -164,7 +164,17 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
164 | sta = sta_info_get(sdata, mac_addr); | 164 | sta = sta_info_get(sdata, mac_addr); |
165 | else | 165 | else |
166 | sta = sta_info_get_bss(sdata, mac_addr); | 166 | sta = sta_info_get_bss(sdata, mac_addr); |
167 | if (!sta) { | 167 | /* |
168 | * The ASSOC test makes sure the driver is ready to | ||
169 | * receive the key. When wpa_supplicant has roamed | ||
170 | * using FT, it attempts to set the key before | ||
171 | * association has completed, this rejects that attempt | ||
172 | * so it will set the key again after assocation. | ||
173 | * | ||
174 | * TODO: accept the key if we have a station entry and | ||
175 | * add it to the device after the station. | ||
176 | */ | ||
177 | if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { | ||
168 | ieee80211_key_free(sdata->local, key); | 178 | ieee80211_key_free(sdata->local, key); |
169 | err = -ENOENT; | 179 | err = -ENOENT; |
170 | goto out_unlock; | 180 | goto out_unlock; |
@@ -510,6 +520,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
510 | BIT(NL80211_STA_FLAG_WME) | | 520 | BIT(NL80211_STA_FLAG_WME) | |
511 | BIT(NL80211_STA_FLAG_MFP) | | 521 | BIT(NL80211_STA_FLAG_MFP) | |
512 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | | 522 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | |
523 | BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
513 | BIT(NL80211_STA_FLAG_TDLS_PEER); | 524 | BIT(NL80211_STA_FLAG_TDLS_PEER); |
514 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | 525 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) |
515 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED); | 526 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED); |
@@ -521,6 +532,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
521 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP); | 532 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP); |
522 | if (test_sta_flag(sta, WLAN_STA_AUTH)) | 533 | if (test_sta_flag(sta, WLAN_STA_AUTH)) |
523 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); | 534 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); |
535 | if (test_sta_flag(sta, WLAN_STA_ASSOC)) | ||
536 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
524 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | 537 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) |
525 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); | 538 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); |
526 | } | 539 | } |
@@ -930,6 +943,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
930 | 943 | ||
931 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 944 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
932 | sdata->vif.bss_conf.dtim_period = params->dtim_period; | 945 | sdata->vif.bss_conf.dtim_period = params->dtim_period; |
946 | sdata->vif.bss_conf.enable_beacon = true; | ||
933 | 947 | ||
934 | sdata->vif.bss_conf.ssid_len = params->ssid_len; | 948 | sdata->vif.bss_conf.ssid_len = params->ssid_len; |
935 | if (params->ssid_len) | 949 | if (params->ssid_len) |
@@ -1010,8 +1024,15 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1010 | kfree_rcu(old_probe_resp, rcu_head); | 1024 | kfree_rcu(old_probe_resp, rcu_head); |
1011 | 1025 | ||
1012 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 1026 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) |
1013 | sta_info_flush(local, vlan); | 1027 | sta_info_flush_defer(vlan); |
1014 | sta_info_flush(local, sdata); | 1028 | sta_info_flush_defer(sdata); |
1029 | rcu_barrier(); | ||
1030 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
1031 | sta_info_flush_cleanup(vlan); | ||
1032 | sta_info_flush_cleanup(sdata); | ||
1033 | |||
1034 | sdata->vif.bss_conf.enable_beacon = false; | ||
1035 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | ||
1015 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 1036 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
1016 | 1037 | ||
1017 | drv_stop_ap(sdata->local, sdata); | 1038 | drv_stop_ap(sdata->local, sdata); |
@@ -1069,6 +1090,58 @@ static void ieee80211_send_layer2_update(struct sta_info *sta) | |||
1069 | netif_rx_ni(skb); | 1090 | netif_rx_ni(skb); |
1070 | } | 1091 | } |
1071 | 1092 | ||
1093 | static int sta_apply_auth_flags(struct ieee80211_local *local, | ||
1094 | struct sta_info *sta, | ||
1095 | u32 mask, u32 set) | ||
1096 | { | ||
1097 | int ret; | ||
1098 | |||
1099 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | ||
1100 | set & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | ||
1101 | !test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
1102 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); | ||
1103 | if (ret) | ||
1104 | return ret; | ||
1105 | } | ||
1106 | |||
1107 | if (mask & BIT(NL80211_STA_FLAG_ASSOCIATED) && | ||
1108 | set & BIT(NL80211_STA_FLAG_ASSOCIATED) && | ||
1109 | !test_sta_flag(sta, WLAN_STA_ASSOC)) { | ||
1110 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
1111 | if (ret) | ||
1112 | return ret; | ||
1113 | } | ||
1114 | |||
1115 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | ||
1116 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
1117 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
1118 | else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
1119 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
1120 | else | ||
1121 | ret = 0; | ||
1122 | if (ret) | ||
1123 | return ret; | ||
1124 | } | ||
1125 | |||
1126 | if (mask & BIT(NL80211_STA_FLAG_ASSOCIATED) && | ||
1127 | !(set & BIT(NL80211_STA_FLAG_ASSOCIATED)) && | ||
1128 | test_sta_flag(sta, WLAN_STA_ASSOC)) { | ||
1129 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); | ||
1130 | if (ret) | ||
1131 | return ret; | ||
1132 | } | ||
1133 | |||
1134 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | ||
1135 | !(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) && | ||
1136 | test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
1137 | ret = sta_info_move_state(sta, IEEE80211_STA_NONE); | ||
1138 | if (ret) | ||
1139 | return ret; | ||
1140 | } | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1072 | static int sta_apply_parameters(struct ieee80211_local *local, | 1145 | static int sta_apply_parameters(struct ieee80211_local *local, |
1073 | struct sta_info *sta, | 1146 | struct sta_info *sta, |
1074 | struct station_parameters *params) | 1147 | struct station_parameters *params) |
@@ -1086,52 +1159,20 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1086 | mask = params->sta_flags_mask; | 1159 | mask = params->sta_flags_mask; |
1087 | set = params->sta_flags_set; | 1160 | set = params->sta_flags_set; |
1088 | 1161 | ||
1089 | /* | 1162 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1090 | * In mesh mode, we can clear AUTHENTICATED flag but must | 1163 | /* |
1091 | * also make ASSOCIATED follow appropriately for the driver | 1164 | * In mesh mode, ASSOCIATED isn't part of the nl80211 |
1092 | * API. See also below, after AUTHORIZED changes. | 1165 | * API but must follow AUTHENTICATED for driver state. |
1093 | */ | 1166 | */ |
1094 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | 1167 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) |
1095 | /* cfg80211 should not allow this in non-mesh modes */ | 1168 | mask |= BIT(NL80211_STA_FLAG_ASSOCIATED); |
1096 | if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif))) | 1169 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) |
1097 | return -EINVAL; | 1170 | set |= BIT(NL80211_STA_FLAG_ASSOCIATED); |
1098 | |||
1099 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | ||
1100 | !test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
1101 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); | ||
1102 | if (ret) | ||
1103 | return ret; | ||
1104 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
1105 | if (ret) | ||
1106 | return ret; | ||
1107 | } | ||
1108 | } | ||
1109 | |||
1110 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | ||
1111 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
1112 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
1113 | else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
1114 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
1115 | if (ret) | ||
1116 | return ret; | ||
1117 | } | ||
1118 | |||
1119 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | ||
1120 | /* cfg80211 should not allow this in non-mesh modes */ | ||
1121 | if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif))) | ||
1122 | return -EINVAL; | ||
1123 | |||
1124 | if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) && | ||
1125 | test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
1126 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); | ||
1127 | if (ret) | ||
1128 | return ret; | ||
1129 | ret = sta_info_move_state(sta, IEEE80211_STA_NONE); | ||
1130 | if (ret) | ||
1131 | return ret; | ||
1132 | } | ||
1133 | } | 1171 | } |
1134 | 1172 | ||
1173 | ret = sta_apply_auth_flags(local, sta, mask, set); | ||
1174 | if (ret) | ||
1175 | return ret; | ||
1135 | 1176 | ||
1136 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { | 1177 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { |
1137 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) | 1178 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) |
@@ -1177,10 +1218,11 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1177 | sta->sta.aid = params->aid; | 1218 | sta->sta.aid = params->aid; |
1178 | 1219 | ||
1179 | /* | 1220 | /* |
1180 | * FIXME: updating the following information is racy when this | 1221 | * Some of the following updates would be racy if called on an |
1181 | * function is called from ieee80211_change_station(). | 1222 | * existing station, via ieee80211_change_station(). However, |
1182 | * However, all this information should be static so | 1223 | * all such changes are rejected by cfg80211 except for updates |
1183 | * maybe we should just reject attemps to change it. | 1224 | * changing the supported rates on an existing but not yet used |
1225 | * TDLS peer. | ||
1184 | */ | 1226 | */ |
1185 | 1227 | ||
1186 | if (params->listen_interval >= 0) | 1228 | if (params->listen_interval >= 0) |
@@ -1211,18 +1253,33 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1211 | 1253 | ||
1212 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1254 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1213 | #ifdef CONFIG_MAC80211_MESH | 1255 | #ifdef CONFIG_MAC80211_MESH |
1214 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) | 1256 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) { |
1257 | u32 changed = 0; | ||
1258 | |||
1215 | switch (params->plink_state) { | 1259 | switch (params->plink_state) { |
1216 | case NL80211_PLINK_LISTEN: | ||
1217 | case NL80211_PLINK_ESTAB: | 1260 | case NL80211_PLINK_ESTAB: |
1261 | if (sta->plink_state != NL80211_PLINK_ESTAB) | ||
1262 | changed = mesh_plink_inc_estab_count( | ||
1263 | sdata); | ||
1264 | sta->plink_state = params->plink_state; | ||
1265 | break; | ||
1266 | case NL80211_PLINK_LISTEN: | ||
1218 | case NL80211_PLINK_BLOCKED: | 1267 | case NL80211_PLINK_BLOCKED: |
1268 | case NL80211_PLINK_OPN_SNT: | ||
1269 | case NL80211_PLINK_OPN_RCVD: | ||
1270 | case NL80211_PLINK_CNF_RCVD: | ||
1271 | case NL80211_PLINK_HOLDING: | ||
1272 | if (sta->plink_state == NL80211_PLINK_ESTAB) | ||
1273 | changed = mesh_plink_dec_estab_count( | ||
1274 | sdata); | ||
1219 | sta->plink_state = params->plink_state; | 1275 | sta->plink_state = params->plink_state; |
1220 | break; | 1276 | break; |
1221 | default: | 1277 | default: |
1222 | /* nothing */ | 1278 | /* nothing */ |
1223 | break; | 1279 | break; |
1224 | } | 1280 | } |
1225 | else | 1281 | ieee80211_bss_info_change_notify(sdata, changed); |
1282 | } else { | ||
1226 | switch (params->plink_action) { | 1283 | switch (params->plink_action) { |
1227 | case PLINK_ACTION_OPEN: | 1284 | case PLINK_ACTION_OPEN: |
1228 | mesh_plink_open(sta); | 1285 | mesh_plink_open(sta); |
@@ -1231,6 +1288,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1231 | mesh_plink_block(sta); | 1288 | mesh_plink_block(sta); |
1232 | break; | 1289 | break; |
1233 | } | 1290 | } |
1291 | } | ||
1234 | #endif | 1292 | #endif |
1235 | } | 1293 | } |
1236 | 1294 | ||
@@ -1265,6 +1323,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1265 | if (!sta) | 1323 | if (!sta) |
1266 | return -ENOMEM; | 1324 | return -ENOMEM; |
1267 | 1325 | ||
1326 | /* | ||
1327 | * defaults -- if userspace wants something else we'll | ||
1328 | * change it accordingly in sta_apply_parameters() | ||
1329 | */ | ||
1268 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 1330 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
1269 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | 1331 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
1270 | 1332 | ||
@@ -1301,7 +1363,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1301 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | 1363 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, |
1302 | u8 *mac) | 1364 | u8 *mac) |
1303 | { | 1365 | { |
1304 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1305 | struct ieee80211_sub_if_data *sdata; | 1366 | struct ieee80211_sub_if_data *sdata; |
1306 | 1367 | ||
1307 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1368 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -1309,7 +1370,7 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
1309 | if (mac) | 1370 | if (mac) |
1310 | return sta_info_destroy_addr_bss(sdata, mac); | 1371 | return sta_info_destroy_addr_bss(sdata, mac); |
1311 | 1372 | ||
1312 | sta_info_flush(local, sdata); | 1373 | sta_info_flush(sdata); |
1313 | return 0; | 1374 | return 0; |
1314 | } | 1375 | } |
1315 | 1376 | ||
@@ -1615,6 +1676,9 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, | |||
1615 | memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate, | 1676 | memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate, |
1616 | sizeof(setup->mcast_rate)); | 1677 | sizeof(setup->mcast_rate)); |
1617 | 1678 | ||
1679 | sdata->vif.bss_conf.beacon_int = setup->beacon_interval; | ||
1680 | sdata->vif.bss_conf.dtim_period = setup->dtim_period; | ||
1681 | |||
1618 | return 0; | 1682 | return 0; |
1619 | } | 1683 | } |
1620 | 1684 | ||
@@ -2197,7 +2261,8 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2197 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2261 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2198 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2262 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
2199 | 2263 | ||
2200 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 2264 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
2265 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
2201 | return -EOPNOTSUPP; | 2266 | return -EOPNOTSUPP; |
2202 | 2267 | ||
2203 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) | 2268 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 80e55527504b..1bfe0a8b19d2 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -381,7 +381,8 @@ void ieee80211_iter_chan_contexts_atomic( | |||
381 | 381 | ||
382 | rcu_read_lock(); | 382 | rcu_read_lock(); |
383 | list_for_each_entry_rcu(ctx, &local->chanctx_list, list) | 383 | list_for_each_entry_rcu(ctx, &local->chanctx_list, list) |
384 | iter(hw, &ctx->conf, iter_data); | 384 | if (ctx->driver_present) |
385 | iter(hw, &ctx->conf, iter_data); | ||
385 | rcu_read_unlock(); | 386 | rcu_read_unlock(); |
386 | } | 387 | } |
387 | EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic); | 388 | EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 698dc7e6f309..0c07f94c5378 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -207,6 +207,14 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
207 | { | 207 | { |
208 | might_sleep(); | 208 | might_sleep(); |
209 | 209 | ||
210 | WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON | | ||
211 | BSS_CHANGED_BEACON_ENABLED) && | ||
212 | sdata->vif.type != NL80211_IFTYPE_AP && | ||
213 | sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
214 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT); | ||
215 | WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE && | ||
216 | changed & ~BSS_CHANGED_IDLE); | ||
217 | |||
210 | check_sdata_in_driver(sdata); | 218 | check_sdata_in_driver(sdata); |
211 | 219 | ||
212 | trace_drv_bss_info_changed(local, sdata, info, changed); | 220 | trace_drv_bss_info_changed(local, sdata, info, changed); |
@@ -913,6 +921,8 @@ static inline int drv_add_chanctx(struct ieee80211_local *local, | |||
913 | if (local->ops->add_chanctx) | 921 | if (local->ops->add_chanctx) |
914 | ret = local->ops->add_chanctx(&local->hw, &ctx->conf); | 922 | ret = local->ops->add_chanctx(&local->hw, &ctx->conf); |
915 | trace_drv_return_int(local, ret); | 923 | trace_drv_return_int(local, ret); |
924 | if (!ret) | ||
925 | ctx->driver_present = true; | ||
916 | 926 | ||
917 | return ret; | 927 | return ret; |
918 | } | 928 | } |
@@ -924,6 +934,7 @@ static inline void drv_remove_chanctx(struct ieee80211_local *local, | |||
924 | if (local->ops->remove_chanctx) | 934 | if (local->ops->remove_chanctx) |
925 | local->ops->remove_chanctx(&local->hw, &ctx->conf); | 935 | local->ops->remove_chanctx(&local->hw, &ctx->conf); |
926 | trace_drv_return_void(local); | 936 | trace_drv_return_void(local); |
937 | ctx->driver_present = false; | ||
927 | } | 938 | } |
928 | 939 | ||
929 | static inline void drv_change_chanctx(struct ieee80211_local *local, | 940 | static inline void drv_change_chanctx(struct ieee80211_local *local, |
@@ -931,8 +942,10 @@ static inline void drv_change_chanctx(struct ieee80211_local *local, | |||
931 | u32 changed) | 942 | u32 changed) |
932 | { | 943 | { |
933 | trace_drv_change_chanctx(local, ctx, changed); | 944 | trace_drv_change_chanctx(local, ctx, changed); |
934 | if (local->ops->change_chanctx) | 945 | if (local->ops->change_chanctx) { |
946 | WARN_ON_ONCE(!ctx->driver_present); | ||
935 | local->ops->change_chanctx(&local->hw, &ctx->conf, changed); | 947 | local->ops->change_chanctx(&local->hw, &ctx->conf, changed); |
948 | } | ||
936 | trace_drv_return_void(local); | 949 | trace_drv_return_void(local); |
937 | } | 950 | } |
938 | 951 | ||
@@ -945,10 +958,12 @@ static inline int drv_assign_vif_chanctx(struct ieee80211_local *local, | |||
945 | check_sdata_in_driver(sdata); | 958 | check_sdata_in_driver(sdata); |
946 | 959 | ||
947 | trace_drv_assign_vif_chanctx(local, sdata, ctx); | 960 | trace_drv_assign_vif_chanctx(local, sdata, ctx); |
948 | if (local->ops->assign_vif_chanctx) | 961 | if (local->ops->assign_vif_chanctx) { |
962 | WARN_ON_ONCE(!ctx->driver_present); | ||
949 | ret = local->ops->assign_vif_chanctx(&local->hw, | 963 | ret = local->ops->assign_vif_chanctx(&local->hw, |
950 | &sdata->vif, | 964 | &sdata->vif, |
951 | &ctx->conf); | 965 | &ctx->conf); |
966 | } | ||
952 | trace_drv_return_int(local, ret); | 967 | trace_drv_return_int(local, ret); |
953 | 968 | ||
954 | return ret; | 969 | return ret; |
@@ -961,10 +976,12 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local, | |||
961 | check_sdata_in_driver(sdata); | 976 | check_sdata_in_driver(sdata); |
962 | 977 | ||
963 | trace_drv_unassign_vif_chanctx(local, sdata, ctx); | 978 | trace_drv_unassign_vif_chanctx(local, sdata, ctx); |
964 | if (local->ops->unassign_vif_chanctx) | 979 | if (local->ops->unassign_vif_chanctx) { |
980 | WARN_ON_ONCE(!ctx->driver_present); | ||
965 | local->ops->unassign_vif_chanctx(&local->hw, | 981 | local->ops->unassign_vif_chanctx(&local->hw, |
966 | &sdata->vif, | 982 | &sdata->vif, |
967 | &ctx->conf); | 983 | &ctx->conf); |
984 | } | ||
968 | trace_drv_return_void(local); | 985 | trace_drv_return_void(local); |
969 | } | 986 | } |
970 | 987 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index a71d891794a4..61ac7c48ac0c 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -62,6 +62,9 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | |||
62 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SUP_WIDTH_20_40); | 62 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SUP_WIDTH_20_40); |
63 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_40); | 63 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_40); |
64 | 64 | ||
65 | /* Allow user to disable SGI-20 (SGI-40 is handled above) */ | ||
66 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_20); | ||
67 | |||
65 | /* Allow user to disable the max-AMSDU bit. */ | 68 | /* Allow user to disable the max-AMSDU bit. */ |
66 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_MAX_AMSDU); | 69 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_MAX_AMSDU); |
67 | 70 | ||
@@ -117,6 +120,21 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
117 | IEEE80211_HT_CAP_SGI_20 | | 120 | IEEE80211_HT_CAP_SGI_20 | |
118 | IEEE80211_HT_CAP_SGI_40 | | 121 | IEEE80211_HT_CAP_SGI_40 | |
119 | IEEE80211_HT_CAP_DSSSCCK40)); | 122 | IEEE80211_HT_CAP_DSSSCCK40)); |
123 | |||
124 | /* Unset 40 MHz if we're not using a 40 MHz channel */ | ||
125 | switch (sdata->vif.bss_conf.chandef.width) { | ||
126 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
127 | case NL80211_CHAN_WIDTH_20: | ||
128 | ht_cap->cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
129 | ht_cap->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
130 | break; | ||
131 | case NL80211_CHAN_WIDTH_40: | ||
132 | case NL80211_CHAN_WIDTH_80: | ||
133 | case NL80211_CHAN_WIDTH_80P80: | ||
134 | case NL80211_CHAN_WIDTH_160: | ||
135 | break; | ||
136 | } | ||
137 | |||
120 | /* | 138 | /* |
121 | * The STBC bits are asymmetric -- if we don't have | 139 | * The STBC bits are asymmetric -- if we don't have |
122 | * TX then mask out the peer's RX and vice versa. | 140 | * TX then mask out the peer's RX and vice versa. |
@@ -179,16 +197,19 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
179 | ieee80211_apply_htcap_overrides(sdata, ht_cap); | 197 | ieee80211_apply_htcap_overrides(sdata, ht_cap); |
180 | } | 198 | } |
181 | 199 | ||
182 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx) | 200 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, |
201 | enum ieee80211_agg_stop_reason reason) | ||
183 | { | 202 | { |
184 | int i; | 203 | int i; |
185 | 204 | ||
186 | cancel_work_sync(&sta->ampdu_mlme.work); | 205 | cancel_work_sync(&sta->ampdu_mlme.work); |
187 | 206 | ||
188 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { | 207 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
189 | __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx); | 208 | __ieee80211_stop_tx_ba_session(sta, i, reason); |
190 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, | 209 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, |
191 | WLAN_REASON_QSTA_LEAVE_QBSS, tx); | 210 | WLAN_REASON_QSTA_LEAVE_QBSS, |
211 | reason != AGG_STOP_DESTROY_STA && | ||
212 | reason != AGG_STOP_PEER_REQUEST); | ||
192 | } | 213 | } |
193 | } | 214 | } |
194 | 215 | ||
@@ -245,8 +266,7 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
245 | if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, | 266 | if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, |
246 | &tid_tx->state)) | 267 | &tid_tx->state)) |
247 | ___ieee80211_stop_tx_ba_session(sta, tid, | 268 | ___ieee80211_stop_tx_ba_session(sta, tid, |
248 | WLAN_BACK_INITIATOR, | 269 | AGG_STOP_LOCAL_REQUEST); |
249 | true); | ||
250 | } | 270 | } |
251 | mutex_unlock(&sta->ampdu_mlme.mtx); | 271 | mutex_unlock(&sta->ampdu_mlme.mtx); |
252 | } | 272 | } |
@@ -314,8 +334,7 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
314 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0, | 334 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0, |
315 | true); | 335 | true); |
316 | else | 336 | else |
317 | __ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, | 337 | __ieee80211_stop_tx_ba_session(sta, tid, AGG_STOP_PEER_REQUEST); |
318 | true); | ||
319 | } | 338 | } |
320 | 339 | ||
321 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | 340 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 6b7644e818d8..b4b866f41919 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -67,7 +67,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
67 | skb_reserve(skb, sdata->local->hw.extra_tx_headroom); | 67 | skb_reserve(skb, sdata->local->hw.extra_tx_headroom); |
68 | 68 | ||
69 | if (!ether_addr_equal(ifibss->bssid, bssid)) | 69 | if (!ether_addr_equal(ifibss->bssid, bssid)) |
70 | sta_info_flush(sdata->local, sdata); | 70 | sta_info_flush(sdata); |
71 | 71 | ||
72 | /* if merging, indicate to driver that we leave the old IBSS */ | 72 | /* if merging, indicate to driver that we leave the old IBSS */ |
73 | if (sdata->vif.bss_conf.ibss_joined) { | 73 | if (sdata->vif.bss_conf.ibss_joined) { |
@@ -191,6 +191,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
191 | 191 | ||
192 | rcu_assign_pointer(ifibss->presp, skb); | 192 | rcu_assign_pointer(ifibss->presp, skb); |
193 | 193 | ||
194 | sdata->vif.bss_conf.enable_beacon = true; | ||
194 | sdata->vif.bss_conf.beacon_int = beacon_int; | 195 | sdata->vif.bss_conf.beacon_int = beacon_int; |
195 | sdata->vif.bss_conf.basic_rates = basic_rates; | 196 | sdata->vif.bss_conf.basic_rates = basic_rates; |
196 | bss_change = BSS_CHANGED_BEACON_INT; | 197 | bss_change = BSS_CHANGED_BEACON_INT; |
@@ -425,11 +426,9 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
425 | } | 426 | } |
426 | 427 | ||
427 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 428 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
428 | struct ieee80211_mgmt *mgmt, | 429 | struct ieee80211_mgmt *mgmt, size_t len, |
429 | size_t len, | ||
430 | struct ieee80211_rx_status *rx_status, | 430 | struct ieee80211_rx_status *rx_status, |
431 | struct ieee802_11_elems *elems, | 431 | struct ieee802_11_elems *elems) |
432 | bool beacon) | ||
433 | { | 432 | { |
434 | struct ieee80211_local *local = sdata->local; | 433 | struct ieee80211_local *local = sdata->local; |
435 | int freq; | 434 | int freq; |
@@ -530,7 +529,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
530 | } | 529 | } |
531 | 530 | ||
532 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, | 531 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
533 | channel, beacon); | 532 | channel); |
534 | if (!bss) | 533 | if (!bss) |
535 | return; | 534 | return; |
536 | 535 | ||
@@ -877,14 +876,21 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
877 | ieee80211_tx_skb(sdata, skb); | 876 | ieee80211_tx_skb(sdata, skb); |
878 | } | 877 | } |
879 | 878 | ||
880 | static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | 879 | static |
881 | struct ieee80211_mgmt *mgmt, | 880 | void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata, |
882 | size_t len, | 881 | struct ieee80211_mgmt *mgmt, size_t len, |
883 | struct ieee80211_rx_status *rx_status) | 882 | struct ieee80211_rx_status *rx_status) |
884 | { | 883 | { |
885 | size_t baselen; | 884 | size_t baselen; |
886 | struct ieee802_11_elems elems; | 885 | struct ieee802_11_elems elems; |
887 | 886 | ||
887 | BUILD_BUG_ON(offsetof(typeof(mgmt->u.probe_resp), variable) != | ||
888 | offsetof(typeof(mgmt->u.beacon), variable)); | ||
889 | |||
890 | /* | ||
891 | * either beacon or probe_resp but the variable field is at the | ||
892 | * same offset | ||
893 | */ | ||
888 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 894 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
889 | if (baselen > len) | 895 | if (baselen > len) |
890 | return; | 896 | return; |
@@ -892,25 +898,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
892 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, | 898 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, |
893 | &elems); | 899 | &elems); |
894 | 900 | ||
895 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); | 901 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); |
896 | } | ||
897 | |||
898 | static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | ||
899 | struct ieee80211_mgmt *mgmt, | ||
900 | size_t len, | ||
901 | struct ieee80211_rx_status *rx_status) | ||
902 | { | ||
903 | size_t baselen; | ||
904 | struct ieee802_11_elems elems; | ||
905 | |||
906 | /* Process beacon from the current BSS */ | ||
907 | baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; | ||
908 | if (baselen > len) | ||
909 | return; | ||
910 | |||
911 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); | ||
912 | |||
913 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); | ||
914 | } | 902 | } |
915 | 903 | ||
916 | void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 904 | void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
@@ -934,12 +922,9 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
934 | ieee80211_rx_mgmt_probe_req(sdata, skb); | 922 | ieee80211_rx_mgmt_probe_req(sdata, skb); |
935 | break; | 923 | break; |
936 | case IEEE80211_STYPE_PROBE_RESP: | 924 | case IEEE80211_STYPE_PROBE_RESP: |
937 | ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, | ||
938 | rx_status); | ||
939 | break; | ||
940 | case IEEE80211_STYPE_BEACON: | 925 | case IEEE80211_STYPE_BEACON: |
941 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, | 926 | ieee80211_rx_mgmt_probe_beacon(sdata, mgmt, skb->len, |
942 | rx_status); | 927 | rx_status); |
943 | break; | 928 | break; |
944 | case IEEE80211_STYPE_AUTH: | 929 | case IEEE80211_STYPE_AUTH: |
945 | ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len); | 930 | ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len); |
@@ -1182,7 +1167,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
1182 | memset(ifibss->bssid, 0, ETH_ALEN); | 1167 | memset(ifibss->bssid, 0, ETH_ALEN); |
1183 | ifibss->ssid_len = 0; | 1168 | ifibss->ssid_len = 0; |
1184 | 1169 | ||
1185 | sta_info_flush(sdata->local, sdata); | 1170 | sta_info_flush(sdata); |
1186 | 1171 | ||
1187 | spin_lock_bh(&ifibss->incomplete_lock); | 1172 | spin_lock_bh(&ifibss->incomplete_lock); |
1188 | while (!list_empty(&ifibss->incomplete_stations)) { | 1173 | while (!list_empty(&ifibss->incomplete_stations)) { |
@@ -1205,6 +1190,8 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
1205 | RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); | 1190 | RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); |
1206 | sdata->vif.bss_conf.ibss_joined = false; | 1191 | sdata->vif.bss_conf.ibss_joined = false; |
1207 | sdata->vif.bss_conf.ibss_creator = false; | 1192 | sdata->vif.bss_conf.ibss_creator = false; |
1193 | sdata->vif.bss_conf.enable_beacon = false; | ||
1194 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | ||
1208 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | 1195 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | |
1209 | BSS_CHANGED_IBSS); | 1196 | BSS_CHANGED_IBSS); |
1210 | synchronize_rcu(); | 1197 | synchronize_rcu(); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8563b9a5cac3..63f0430c131e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -405,6 +405,8 @@ struct ieee80211_mgd_assoc_data { | |||
405 | 405 | ||
406 | u8 ap_ht_param; | 406 | u8 ap_ht_param; |
407 | 407 | ||
408 | struct ieee80211_vht_cap ap_vht_cap; | ||
409 | |||
408 | size_t ie_len; | 410 | size_t ie_len; |
409 | u8 ie[]; | 411 | u8 ie[]; |
410 | }; | 412 | }; |
@@ -659,10 +661,13 @@ enum ieee80211_sub_if_data_flags { | |||
659 | * change handling while the interface is up | 661 | * change handling while the interface is up |
660 | * @SDATA_STATE_OFFCHANNEL: This interface is currently in offchannel | 662 | * @SDATA_STATE_OFFCHANNEL: This interface is currently in offchannel |
661 | * mode, so queues are stopped | 663 | * mode, so queues are stopped |
664 | * @SDATA_STATE_OFFCHANNEL_BEACON_STOPPED: Beaconing was stopped due | ||
665 | * to offchannel, reset when offchannel returns | ||
662 | */ | 666 | */ |
663 | enum ieee80211_sdata_state_bits { | 667 | enum ieee80211_sdata_state_bits { |
664 | SDATA_STATE_RUNNING, | 668 | SDATA_STATE_RUNNING, |
665 | SDATA_STATE_OFFCHANNEL, | 669 | SDATA_STATE_OFFCHANNEL, |
670 | SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, | ||
666 | }; | 671 | }; |
667 | 672 | ||
668 | /** | 673 | /** |
@@ -685,6 +690,7 @@ struct ieee80211_chanctx { | |||
685 | 690 | ||
686 | enum ieee80211_chanctx_mode mode; | 691 | enum ieee80211_chanctx_mode mode; |
687 | int refcount; | 692 | int refcount; |
693 | bool driver_present; | ||
688 | 694 | ||
689 | struct ieee80211_chanctx_conf conf; | 695 | struct ieee80211_chanctx_conf conf; |
690 | }; | 696 | }; |
@@ -783,6 +789,11 @@ struct ieee80211_sub_if_data { | |||
783 | struct dentry *default_mgmt_key; | 789 | struct dentry *default_mgmt_key; |
784 | } debugfs; | 790 | } debugfs; |
785 | #endif | 791 | #endif |
792 | |||
793 | #ifdef CONFIG_PM | ||
794 | struct ieee80211_bss_conf suspend_bss_conf; | ||
795 | #endif | ||
796 | |||
786 | /* must be last, dynamically sized area in this! */ | 797 | /* must be last, dynamically sized area in this! */ |
787 | struct ieee80211_vif vif; | 798 | struct ieee80211_vif vif; |
788 | }; | 799 | }; |
@@ -1346,8 +1357,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
1346 | struct ieee80211_mgmt *mgmt, | 1357 | struct ieee80211_mgmt *mgmt, |
1347 | size_t len, | 1358 | size_t len, |
1348 | struct ieee802_11_elems *elems, | 1359 | struct ieee802_11_elems *elems, |
1349 | struct ieee80211_channel *channel, | 1360 | struct ieee80211_channel *channel); |
1350 | bool beacon); | ||
1351 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 1361 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
1352 | struct ieee80211_bss *bss); | 1362 | struct ieee80211_bss *bss); |
1353 | 1363 | ||
@@ -1358,10 +1368,8 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); | |||
1358 | void ieee80211_sched_scan_stopped_work(struct work_struct *work); | 1368 | void ieee80211_sched_scan_stopped_work(struct work_struct *work); |
1359 | 1369 | ||
1360 | /* off-channel helpers */ | 1370 | /* off-channel helpers */ |
1361 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | 1371 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local); |
1362 | bool offchannel_ps_enable); | 1372 | void ieee80211_offchannel_return(struct ieee80211_local *local); |
1363 | void ieee80211_offchannel_return(struct ieee80211_local *local, | ||
1364 | bool offchannel_ps_disable); | ||
1365 | void ieee80211_roc_setup(struct ieee80211_local *local); | 1373 | void ieee80211_roc_setup(struct ieee80211_local *local); |
1366 | void ieee80211_start_next_roc(struct ieee80211_local *local); | 1374 | void ieee80211_start_next_roc(struct ieee80211_local *local); |
1367 | void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata); | 1375 | void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata); |
@@ -1422,7 +1430,8 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
1422 | u16 initiator, u16 reason, bool stop); | 1430 | u16 initiator, u16 reason, bool stop); |
1423 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1431 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1424 | u16 initiator, u16 reason, bool stop); | 1432 | u16 initiator, u16 reason, bool stop); |
1425 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx); | 1433 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, |
1434 | enum ieee80211_agg_stop_reason reason); | ||
1426 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 1435 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
1427 | struct sta_info *sta, | 1436 | struct sta_info *sta, |
1428 | struct ieee80211_mgmt *mgmt, size_t len); | 1437 | struct ieee80211_mgmt *mgmt, size_t len); |
@@ -1436,11 +1445,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
1436 | size_t len); | 1445 | size_t len); |
1437 | 1446 | ||
1438 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 1447 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
1439 | enum ieee80211_back_parties initiator, | 1448 | enum ieee80211_agg_stop_reason reason); |
1440 | bool tx); | ||
1441 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 1449 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
1442 | enum ieee80211_back_parties initiator, | 1450 | enum ieee80211_agg_stop_reason reason); |
1443 | bool tx); | ||
1444 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); | 1451 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); |
1445 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); | 1452 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); |
1446 | void ieee80211_ba_session_work(struct work_struct *work); | 1453 | void ieee80211_ba_session_work(struct work_struct *work); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 8be854e86cd9..06fac2991d40 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -747,7 +747,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
747 | unsigned long flags; | 747 | unsigned long flags; |
748 | struct sk_buff *skb, *tmp; | 748 | struct sk_buff *skb, *tmp; |
749 | u32 hw_reconf_flags = 0; | 749 | u32 hw_reconf_flags = 0; |
750 | int i; | 750 | int i, flushed; |
751 | 751 | ||
752 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | 752 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
753 | 753 | ||
@@ -772,11 +772,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
772 | * (because if we remove a STA after ops->remove_interface() | 772 | * (because if we remove a STA after ops->remove_interface() |
773 | * the driver will have removed the vif info already!) | 773 | * the driver will have removed the vif info already!) |
774 | * | 774 | * |
775 | * This is relevant only in AP, WDS and mesh modes, since in | 775 | * This is relevant only in WDS mode, in all other modes we've |
776 | * all other modes we've already removed all stations when | 776 | * already removed all stations when disconnecting or similar, |
777 | * disconnecting etc. | 777 | * so warn otherwise. |
778 | * | ||
779 | * We call sta_info_flush_cleanup() later, to combine RCU waits. | ||
778 | */ | 780 | */ |
779 | sta_info_flush(local, sdata); | 781 | flushed = sta_info_flush_defer(sdata); |
782 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || | ||
783 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); | ||
780 | 784 | ||
781 | /* | 785 | /* |
782 | * Don't count this interface for promisc/allmulti while it | 786 | * Don't count this interface for promisc/allmulti while it |
@@ -859,11 +863,17 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
859 | cancel_work_sync(&sdata->work); | 863 | cancel_work_sync(&sdata->work); |
860 | /* | 864 | /* |
861 | * When we get here, the interface is marked down. | 865 | * When we get here, the interface is marked down. |
862 | * Call synchronize_rcu() to wait for the RX path | 866 | * |
863 | * should it be using the interface and enqueuing | 867 | * sta_info_flush_cleanup() requires rcu_barrier() |
864 | * frames at this very time on another CPU. | 868 | * first to wait for the station call_rcu() calls |
869 | * to complete, here we need at least sychronize_rcu() | ||
870 | * it to wait for the RX path in case it is using the | ||
871 | * interface and enqueuing frames at this very time on | ||
872 | * another CPU. | ||
865 | */ | 873 | */ |
866 | synchronize_rcu(); | 874 | rcu_barrier(); |
875 | sta_info_flush_cleanup(sdata); | ||
876 | |||
867 | skb_queue_purge(&sdata->skb_queue); | 877 | skb_queue_purge(&sdata->skb_queue); |
868 | 878 | ||
869 | /* | 879 | /* |
@@ -961,7 +971,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
961 | */ | 971 | */ |
962 | static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) | 972 | static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) |
963 | { | 973 | { |
964 | struct ieee80211_local *local = sdata->local; | ||
965 | int flushed; | 974 | int flushed; |
966 | int i; | 975 | int i; |
967 | 976 | ||
@@ -977,7 +986,7 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) | |||
977 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 986 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
978 | mesh_rmc_free(sdata); | 987 | mesh_rmc_free(sdata); |
979 | 988 | ||
980 | flushed = sta_info_flush(local, sdata); | 989 | flushed = sta_info_flush(sdata); |
981 | WARN_ON(flushed); | 990 | WARN_ON(flushed); |
982 | } | 991 | } |
983 | 992 | ||
@@ -1218,6 +1227,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1218 | case NL80211_IFTYPE_AP: | 1227 | case NL80211_IFTYPE_AP: |
1219 | skb_queue_head_init(&sdata->u.ap.ps.bc_buf); | 1228 | skb_queue_head_init(&sdata->u.ap.ps.bc_buf); |
1220 | INIT_LIST_HEAD(&sdata->u.ap.vlans); | 1229 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
1230 | sdata->vif.bss_conf.bssid = sdata->vif.addr; | ||
1221 | break; | 1231 | break; |
1222 | case NL80211_IFTYPE_P2P_CLIENT: | 1232 | case NL80211_IFTYPE_P2P_CLIENT: |
1223 | type = NL80211_IFTYPE_STATION; | 1233 | type = NL80211_IFTYPE_STATION; |
@@ -1225,9 +1235,11 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1225 | sdata->vif.p2p = true; | 1235 | sdata->vif.p2p = true; |
1226 | /* fall through */ | 1236 | /* fall through */ |
1227 | case NL80211_IFTYPE_STATION: | 1237 | case NL80211_IFTYPE_STATION: |
1238 | sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; | ||
1228 | ieee80211_sta_setup_sdata(sdata); | 1239 | ieee80211_sta_setup_sdata(sdata); |
1229 | break; | 1240 | break; |
1230 | case NL80211_IFTYPE_ADHOC: | 1241 | case NL80211_IFTYPE_ADHOC: |
1242 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; | ||
1231 | ieee80211_ibss_setup_sdata(sdata); | 1243 | ieee80211_ibss_setup_sdata(sdata); |
1232 | break; | 1244 | break; |
1233 | case NL80211_IFTYPE_MESH_POINT: | 1245 | case NL80211_IFTYPE_MESH_POINT: |
@@ -1241,8 +1253,12 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1241 | MONITOR_FLAG_OTHER_BSS; | 1253 | MONITOR_FLAG_OTHER_BSS; |
1242 | break; | 1254 | break; |
1243 | case NL80211_IFTYPE_WDS: | 1255 | case NL80211_IFTYPE_WDS: |
1256 | sdata->vif.bss_conf.bssid = NULL; | ||
1257 | break; | ||
1244 | case NL80211_IFTYPE_AP_VLAN: | 1258 | case NL80211_IFTYPE_AP_VLAN: |
1259 | break; | ||
1245 | case NL80211_IFTYPE_P2P_DEVICE: | 1260 | case NL80211_IFTYPE_P2P_DEVICE: |
1261 | sdata->vif.bss_conf.bssid = sdata->vif.addr; | ||
1246 | break; | 1262 | break; |
1247 | case NL80211_IFTYPE_UNSPECIFIED: | 1263 | case NL80211_IFTYPE_UNSPECIFIED: |
1248 | case NUM_NL80211_IFTYPES: | 1264 | case NUM_NL80211_IFTYPES: |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 1b087fff93e7..39cfe8f10ad2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -207,76 +207,10 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
207 | u32 changed) | 207 | u32 changed) |
208 | { | 208 | { |
209 | struct ieee80211_local *local = sdata->local; | 209 | struct ieee80211_local *local = sdata->local; |
210 | static const u8 zero[ETH_ALEN] = { 0 }; | ||
211 | 210 | ||
212 | if (!changed) | 211 | if (!changed) |
213 | return; | 212 | return; |
214 | 213 | ||
215 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
216 | sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; | ||
217 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
218 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; | ||
219 | else if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
220 | sdata->vif.bss_conf.bssid = sdata->vif.addr; | ||
221 | else if (sdata->vif.type == NL80211_IFTYPE_WDS) | ||
222 | sdata->vif.bss_conf.bssid = NULL; | ||
223 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
224 | sdata->vif.bss_conf.bssid = zero; | ||
225 | } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { | ||
226 | sdata->vif.bss_conf.bssid = sdata->vif.addr; | ||
227 | WARN_ONCE(changed & ~(BSS_CHANGED_IDLE), | ||
228 | "P2P Device BSS changed %#x", changed); | ||
229 | } else { | ||
230 | WARN_ON(1); | ||
231 | return; | ||
232 | } | ||
233 | |||
234 | switch (sdata->vif.type) { | ||
235 | case NL80211_IFTYPE_AP: | ||
236 | case NL80211_IFTYPE_ADHOC: | ||
237 | case NL80211_IFTYPE_WDS: | ||
238 | case NL80211_IFTYPE_MESH_POINT: | ||
239 | break; | ||
240 | default: | ||
241 | /* do not warn to simplify caller in scan.c */ | ||
242 | changed &= ~BSS_CHANGED_BEACON_ENABLED; | ||
243 | if (WARN_ON(changed & BSS_CHANGED_BEACON)) | ||
244 | return; | ||
245 | break; | ||
246 | } | ||
247 | |||
248 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | ||
249 | if (local->quiescing || !ieee80211_sdata_running(sdata) || | ||
250 | test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) { | ||
251 | sdata->vif.bss_conf.enable_beacon = false; | ||
252 | } else { | ||
253 | /* | ||
254 | * Beacon should be enabled, but AP mode must | ||
255 | * check whether there is a beacon configured. | ||
256 | */ | ||
257 | switch (sdata->vif.type) { | ||
258 | case NL80211_IFTYPE_AP: | ||
259 | sdata->vif.bss_conf.enable_beacon = | ||
260 | !!sdata->u.ap.beacon; | ||
261 | break; | ||
262 | case NL80211_IFTYPE_ADHOC: | ||
263 | sdata->vif.bss_conf.enable_beacon = | ||
264 | !!sdata->u.ibss.presp; | ||
265 | break; | ||
266 | #ifdef CONFIG_MAC80211_MESH | ||
267 | case NL80211_IFTYPE_MESH_POINT: | ||
268 | sdata->vif.bss_conf.enable_beacon = | ||
269 | !!sdata->u.mesh.mesh_id_len; | ||
270 | break; | ||
271 | #endif | ||
272 | default: | ||
273 | /* not reached */ | ||
274 | WARN_ON(1); | ||
275 | break; | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | |||
280 | drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); | 214 | drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); |
281 | } | 215 | } |
282 | 216 | ||
@@ -537,6 +471,7 @@ static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { | |||
537 | 471 | ||
538 | .cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | 472 | .cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | |
539 | IEEE80211_HT_CAP_MAX_AMSDU | | 473 | IEEE80211_HT_CAP_MAX_AMSDU | |
474 | IEEE80211_HT_CAP_SGI_20 | | ||
540 | IEEE80211_HT_CAP_SGI_40), | 475 | IEEE80211_HT_CAP_SGI_40), |
541 | .mcs = { | 476 | .mcs = { |
542 | .rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff, | 477 | .rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff, |
@@ -606,7 +541,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
606 | wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | | 541 | wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | |
607 | NL80211_FEATURE_SAE | | 542 | NL80211_FEATURE_SAE | |
608 | NL80211_FEATURE_HT_IBSS | | 543 | NL80211_FEATURE_HT_IBSS | |
609 | NL80211_FEATURE_VIF_TXPOWER; | 544 | NL80211_FEATURE_VIF_TXPOWER | |
545 | NL80211_FEATURE_FULL_AP_CLIENT_STATE; | ||
610 | 546 | ||
611 | if (!ops->hw_scan) | 547 | if (!ops->hw_scan) |
612 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | | 548 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 649ad513547f..694e27376afa 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -20,16 +20,11 @@ | |||
20 | int mesh_allocated; | 20 | int mesh_allocated; |
21 | static struct kmem_cache *rm_cache; | 21 | static struct kmem_cache *rm_cache; |
22 | 22 | ||
23 | #ifdef CONFIG_MAC80211_MESH | ||
24 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) | 23 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) |
25 | { | 24 | { |
26 | return (mgmt->u.action.u.mesh_action.action_code == | 25 | return (mgmt->u.action.u.mesh_action.action_code == |
27 | WLAN_MESH_ACTION_HWMP_PATH_SELECTION); | 26 | WLAN_MESH_ACTION_HWMP_PATH_SELECTION); |
28 | } | 27 | } |
29 | #else | ||
30 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) | ||
31 | { return false; } | ||
32 | #endif | ||
33 | 28 | ||
34 | void ieee80211s_init(void) | 29 | void ieee80211s_init(void) |
35 | { | 30 | { |
@@ -607,6 +602,12 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
607 | { | 602 | { |
608 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 603 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
609 | struct ieee80211_local *local = sdata->local; | 604 | struct ieee80211_local *local = sdata->local; |
605 | u32 changed = BSS_CHANGED_BEACON | | ||
606 | BSS_CHANGED_BEACON_ENABLED | | ||
607 | BSS_CHANGED_HT | | ||
608 | BSS_CHANGED_BASIC_RATES | | ||
609 | BSS_CHANGED_BEACON_INT; | ||
610 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
610 | 611 | ||
611 | local->fif_other_bss++; | 612 | local->fif_other_bss++; |
612 | /* mesh ifaces must set allmulti to forward mcast traffic */ | 613 | /* mesh ifaces must set allmulti to forward mcast traffic */ |
@@ -624,15 +625,16 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
624 | ieee80211_queue_work(&local->hw, &sdata->work); | 625 | ieee80211_queue_work(&local->hw, &sdata->work); |
625 | sdata->vif.bss_conf.ht_operation_mode = | 626 | sdata->vif.bss_conf.ht_operation_mode = |
626 | ifmsh->mshcfg.ht_opmode; | 627 | ifmsh->mshcfg.ht_opmode; |
627 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; | 628 | sdata->vif.bss_conf.enable_beacon = true; |
628 | sdata->vif.bss_conf.basic_rates = | 629 | sdata->vif.bss_conf.basic_rates = |
629 | ieee80211_mandatory_rates(sdata->local, | 630 | ieee80211_mandatory_rates(local, band); |
630 | ieee80211_get_sdata_band(sdata)); | 631 | |
631 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | | 632 | if (band == IEEE80211_BAND_5GHZ) { |
632 | BSS_CHANGED_BEACON_ENABLED | | 633 | sdata->vif.bss_conf.use_short_slot = true; |
633 | BSS_CHANGED_HT | | 634 | changed |= BSS_CHANGED_ERP_SLOT; |
634 | BSS_CHANGED_BASIC_RATES | | 635 | } |
635 | BSS_CHANGED_BEACON_INT); | 636 | |
637 | ieee80211_bss_info_change_notify(sdata, changed); | ||
636 | 638 | ||
637 | netif_carrier_on(sdata->dev); | 639 | netif_carrier_on(sdata->dev); |
638 | } | 640 | } |
@@ -646,10 +648,12 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
646 | 648 | ||
647 | /* stop the beacon */ | 649 | /* stop the beacon */ |
648 | ifmsh->mesh_id_len = 0; | 650 | ifmsh->mesh_id_len = 0; |
651 | sdata->vif.bss_conf.enable_beacon = false; | ||
652 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | ||
649 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 653 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
650 | 654 | ||
651 | /* flush STAs and mpaths on this iface */ | 655 | /* flush STAs and mpaths on this iface */ |
652 | sta_info_flush(sdata->local, sdata); | 656 | sta_info_flush(sdata); |
653 | mesh_path_flush_by_iface(sdata); | 657 | mesh_path_flush_by_iface(sdata); |
654 | 658 | ||
655 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); | 659 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); |
@@ -805,6 +809,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | |||
805 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | 809 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) |
806 | { | 810 | { |
807 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 811 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
812 | static u8 zero_addr[ETH_ALEN] = {}; | ||
808 | 813 | ||
809 | setup_timer(&ifmsh->housekeeping_timer, | 814 | setup_timer(&ifmsh->housekeeping_timer, |
810 | ieee80211_mesh_housekeeping_timer, | 815 | ieee80211_mesh_housekeeping_timer, |
@@ -830,4 +835,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
830 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); | 835 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); |
831 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); | 836 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); |
832 | spin_lock_init(&ifmsh->sync_offset_lock); | 837 | spin_lock_init(&ifmsh->sync_offset_lock); |
838 | |||
839 | sdata->vif.bss_conf.bssid = zero_addr; | ||
833 | } | 840 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 84c28c6101cd..aff301544c7f 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -191,8 +191,6 @@ struct mesh_rmc { | |||
191 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) | 191 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) |
192 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | 192 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) |
193 | 193 | ||
194 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ | ||
195 | |||
196 | #define MESH_PATH_EXPIRE (600 * HZ) | 194 | #define MESH_PATH_EXPIRE (600 * HZ) |
197 | 195 | ||
198 | /* Default maximum number of plinks per interface */ | 196 | /* Default maximum number of plinks per interface */ |
@@ -307,6 +305,20 @@ extern int mesh_paths_generation; | |||
307 | #ifdef CONFIG_MAC80211_MESH | 305 | #ifdef CONFIG_MAC80211_MESH |
308 | extern int mesh_allocated; | 306 | extern int mesh_allocated; |
309 | 307 | ||
308 | static inline | ||
309 | u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) | ||
310 | { | ||
311 | atomic_inc(&sdata->u.mesh.estab_plinks); | ||
312 | return mesh_accept_plinks_update(sdata); | ||
313 | } | ||
314 | |||
315 | static inline | ||
316 | u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) | ||
317 | { | ||
318 | atomic_dec(&sdata->u.mesh.estab_plinks); | ||
319 | return mesh_accept_plinks_update(sdata); | ||
320 | } | ||
321 | |||
310 | static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) | 322 | static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) |
311 | { | 323 | { |
312 | return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks - | 324 | return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks - |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 47aeee2d8db1..6b4603a90031 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -215,16 +215,19 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, | |||
215 | skb->priority = 7; | 215 | skb->priority = 7; |
216 | 216 | ||
217 | info->control.vif = &sdata->vif; | 217 | info->control.vif = &sdata->vif; |
218 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
218 | ieee80211_set_qos_hdr(sdata, skb); | 219 | ieee80211_set_qos_hdr(sdata, skb); |
219 | } | 220 | } |
220 | 221 | ||
221 | /** | 222 | /** |
222 | * mesh_send_path error - Sends a PERR mesh management frame | 223 | * mesh_path_error_tx - Sends a PERR mesh management frame |
223 | * | 224 | * |
225 | * @ttl: allowed remaining hops | ||
224 | * @target: broken destination | 226 | * @target: broken destination |
225 | * @target_sn: SN of the broken destination | 227 | * @target_sn: SN of the broken destination |
226 | * @target_rcode: reason code for this PERR | 228 | * @target_rcode: reason code for this PERR |
227 | * @ra: node this frame is addressed to | 229 | * @ra: node this frame is addressed to |
230 | * @sdata: local mesh subif | ||
228 | * | 231 | * |
229 | * Note: This function may be called with driver locks taken that the driver | 232 | * Note: This function may be called with driver locks taken that the driver |
230 | * also acquires in the TX path. To avoid a deadlock we don't transmit the | 233 | * also acquires in the TX path. To avoid a deadlock we don't transmit the |
@@ -246,11 +249,13 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
246 | return -EAGAIN; | 249 | return -EAGAIN; |
247 | 250 | ||
248 | skb = dev_alloc_skb(local->tx_headroom + | 251 | skb = dev_alloc_skb(local->tx_headroom + |
252 | IEEE80211_ENCRYPT_HEADROOM + | ||
253 | IEEE80211_ENCRYPT_TAILROOM + | ||
249 | hdr_len + | 254 | hdr_len + |
250 | 2 + 15 /* PERR IE */); | 255 | 2 + 15 /* PERR IE */); |
251 | if (!skb) | 256 | if (!skb) |
252 | return -1; | 257 | return -1; |
253 | skb_reserve(skb, local->tx_headroom); | 258 | skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM); |
254 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); | 259 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); |
255 | memset(mgmt, 0, hdr_len); | 260 | memset(mgmt, 0, hdr_len); |
256 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 261 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
@@ -350,6 +355,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, | |||
350 | * @sdata: local mesh subif | 355 | * @sdata: local mesh subif |
351 | * @mgmt: mesh management frame | 356 | * @mgmt: mesh management frame |
352 | * @hwmp_ie: hwmp information element (PREP or PREQ) | 357 | * @hwmp_ie: hwmp information element (PREP or PREQ) |
358 | * @action: type of hwmp ie | ||
353 | * | 359 | * |
354 | * This function updates the path routing information to the originator and the | 360 | * This function updates the path routing information to the originator and the |
355 | * transmitter of a HWMP PREQ or PREP frame. | 361 | * transmitter of a HWMP PREQ or PREP frame. |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 4b274e9c91a5..9e0416696a83 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -41,20 +41,6 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
41 | enum ieee80211_self_protected_actioncode action, | 41 | enum ieee80211_self_protected_actioncode action, |
42 | u8 *da, __le16 llid, __le16 plid, __le16 reason); | 42 | u8 *da, __le16 llid, __le16 plid, __le16 reason); |
43 | 43 | ||
44 | static inline | ||
45 | u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) | ||
46 | { | ||
47 | atomic_inc(&sdata->u.mesh.estab_plinks); | ||
48 | return mesh_accept_plinks_update(sdata); | ||
49 | } | ||
50 | |||
51 | static inline | ||
52 | u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) | ||
53 | { | ||
54 | atomic_dec(&sdata->u.mesh.estab_plinks); | ||
55 | return mesh_accept_plinks_update(sdata); | ||
56 | } | ||
57 | |||
58 | /** | 44 | /** |
59 | * mesh_plink_fsm_restart - restart a mesh peer link finite state machine | 45 | * mesh_plink_fsm_restart - restart a mesh peer link finite state machine |
60 | * | 46 | * |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a3552929a21d..e930175771ff 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -199,11 +199,11 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata, | |||
199 | case NL80211_CHAN_WIDTH_40: | 199 | case NL80211_CHAN_WIDTH_40: |
200 | if (sdata->vif.bss_conf.chandef.chan->center_freq > | 200 | if (sdata->vif.bss_conf.chandef.chan->center_freq > |
201 | sdata->vif.bss_conf.chandef.center_freq1 && | 201 | sdata->vif.bss_conf.chandef.center_freq1 && |
202 | chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | 202 | chan->flags & IEEE80211_CHAN_NO_HT40MINUS) |
203 | disable_40 = true; | 203 | disable_40 = true; |
204 | if (sdata->vif.bss_conf.chandef.chan->center_freq < | 204 | if (sdata->vif.bss_conf.chandef.chan->center_freq < |
205 | sdata->vif.bss_conf.chandef.center_freq1 && | 205 | sdata->vif.bss_conf.chandef.center_freq1 && |
206 | chan->flags & IEEE80211_CHAN_NO_HT40MINUS) | 206 | chan->flags & IEEE80211_CHAN_NO_HT40PLUS) |
207 | disable_40 = true; | 207 | disable_40 = true; |
208 | break; | 208 | break; |
209 | default: | 209 | default: |
@@ -341,11 +341,13 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | |||
341 | 341 | ||
342 | static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | 342 | static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, |
343 | struct sk_buff *skb, | 343 | struct sk_buff *skb, |
344 | struct ieee80211_supported_band *sband) | 344 | struct ieee80211_supported_band *sband, |
345 | struct ieee80211_vht_cap *ap_vht_cap) | ||
345 | { | 346 | { |
346 | u8 *pos; | 347 | u8 *pos; |
347 | u32 cap; | 348 | u32 cap; |
348 | struct ieee80211_sta_vht_cap vht_cap; | 349 | struct ieee80211_sta_vht_cap vht_cap; |
350 | int i; | ||
349 | 351 | ||
350 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); | 352 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); |
351 | 353 | ||
@@ -364,6 +366,42 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
364 | cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | 366 | cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; |
365 | } | 367 | } |
366 | 368 | ||
369 | /* | ||
370 | * Some APs apparently get confused if our capabilities are better | ||
371 | * than theirs, so restrict what we advertise in the assoc request. | ||
372 | */ | ||
373 | if (!(ap_vht_cap->vht_cap_info & | ||
374 | cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE))) | ||
375 | cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; | ||
376 | |||
377 | if (!(ap_vht_cap->vht_cap_info & | ||
378 | cpu_to_le32(IEEE80211_VHT_CAP_TXSTBC))) | ||
379 | cap &= ~(IEEE80211_VHT_CAP_RXSTBC_1 | | ||
380 | IEEE80211_VHT_CAP_RXSTBC_3 | | ||
381 | IEEE80211_VHT_CAP_RXSTBC_4); | ||
382 | |||
383 | for (i = 0; i < 8; i++) { | ||
384 | int shift = i * 2; | ||
385 | u16 mask = IEEE80211_VHT_MCS_NOT_SUPPORTED << shift; | ||
386 | u16 ap_mcs, our_mcs; | ||
387 | |||
388 | ap_mcs = (le16_to_cpu(ap_vht_cap->supp_mcs.tx_mcs_map) & | ||
389 | mask) >> shift; | ||
390 | our_mcs = (le16_to_cpu(vht_cap.vht_mcs.rx_mcs_map) & | ||
391 | mask) >> shift; | ||
392 | |||
393 | switch (ap_mcs) { | ||
394 | default: | ||
395 | if (our_mcs <= ap_mcs) | ||
396 | break; | ||
397 | /* fall through */ | ||
398 | case IEEE80211_VHT_MCS_NOT_SUPPORTED: | ||
399 | vht_cap.vht_mcs.rx_mcs_map &= cpu_to_le16(~mask); | ||
400 | vht_cap.vht_mcs.rx_mcs_map |= | ||
401 | cpu_to_le16(ap_mcs << shift); | ||
402 | } | ||
403 | } | ||
404 | |||
367 | /* reserve and fill IE */ | 405 | /* reserve and fill IE */ |
368 | pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); | 406 | pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); |
369 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); | 407 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); |
@@ -562,7 +600,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
562 | sband, chan, sdata->smps_mode); | 600 | sband, chan, sdata->smps_mode); |
563 | 601 | ||
564 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) | 602 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) |
565 | ieee80211_add_vht_ie(sdata, skb, sband); | 603 | ieee80211_add_vht_ie(sdata, skb, sband, |
604 | &assoc_data->ap_vht_cap); | ||
566 | 605 | ||
567 | /* if present, add any custom non-vendor IEs that go after HT */ | 606 | /* if present, add any custom non-vendor IEs that go after HT */ |
568 | if (assoc_data->ie_len && assoc_data->ie) { | 607 | if (assoc_data->ie_len && assoc_data->ie) { |
@@ -1486,7 +1525,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1486 | sta = sta_info_get(sdata, ifmgd->bssid); | 1525 | sta = sta_info_get(sdata, ifmgd->bssid); |
1487 | if (sta) { | 1526 | if (sta) { |
1488 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | 1527 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); |
1489 | ieee80211_sta_tear_down_BA_sessions(sta, false); | 1528 | ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA); |
1490 | } | 1529 | } |
1491 | mutex_unlock(&local->sta_mtx); | 1530 | mutex_unlock(&local->sta_mtx); |
1492 | 1531 | ||
@@ -1521,7 +1560,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1521 | memset(ifmgd->bssid, 0, ETH_ALEN); | 1560 | memset(ifmgd->bssid, 0, ETH_ALEN); |
1522 | 1561 | ||
1523 | /* remove AP and TDLS peers */ | 1562 | /* remove AP and TDLS peers */ |
1524 | sta_info_flush(local, sdata); | 1563 | sta_info_flush_defer(sdata); |
1525 | 1564 | ||
1526 | /* finally reset all BSS / config parameters */ | 1565 | /* finally reset all BSS / config parameters */ |
1527 | changed |= ieee80211_reset_erp_info(sdata); | 1566 | changed |= ieee80211_reset_erp_info(sdata); |
@@ -2369,8 +2408,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2369 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 2408 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
2370 | struct ieee80211_mgmt *mgmt, size_t len, | 2409 | struct ieee80211_mgmt *mgmt, size_t len, |
2371 | struct ieee80211_rx_status *rx_status, | 2410 | struct ieee80211_rx_status *rx_status, |
2372 | struct ieee802_11_elems *elems, | 2411 | struct ieee802_11_elems *elems) |
2373 | bool beacon) | ||
2374 | { | 2412 | { |
2375 | struct ieee80211_local *local = sdata->local; | 2413 | struct ieee80211_local *local = sdata->local; |
2376 | int freq; | 2414 | int freq; |
@@ -2404,7 +2442,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2404 | return; | 2442 | return; |
2405 | 2443 | ||
2406 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, | 2444 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
2407 | channel, beacon); | 2445 | channel); |
2408 | if (bss) | 2446 | if (bss) |
2409 | ieee80211_rx_bss_put(local, bss); | 2447 | ieee80211_rx_bss_put(local, bss); |
2410 | 2448 | ||
@@ -2447,7 +2485,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
2447 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, | 2485 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, |
2448 | &elems); | 2486 | &elems); |
2449 | 2487 | ||
2450 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); | 2488 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); |
2451 | 2489 | ||
2452 | if (ifmgd->associated && | 2490 | if (ifmgd->associated && |
2453 | ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) | 2491 | ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) |
@@ -2528,8 +2566,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2528 | ieee802_11_parse_elems(mgmt->u.beacon.variable, | 2566 | ieee802_11_parse_elems(mgmt->u.beacon.variable, |
2529 | len - baselen, &elems); | 2567 | len - baselen, &elems); |
2530 | 2568 | ||
2531 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, | 2569 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); |
2532 | false); | ||
2533 | ifmgd->assoc_data->have_beacon = true; | 2570 | ifmgd->assoc_data->have_beacon = true; |
2534 | ifmgd->assoc_data->sent_assoc = false; | 2571 | ifmgd->assoc_data->sent_assoc = false; |
2535 | /* continue assoc process */ | 2572 | /* continue assoc process */ |
@@ -2682,8 +2719,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2682 | ifmgd->beacon_crc = ncrc; | 2719 | ifmgd->beacon_crc = ncrc; |
2683 | ifmgd->beacon_crc_valid = true; | 2720 | ifmgd->beacon_crc_valid = true; |
2684 | 2721 | ||
2685 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, | 2722 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); |
2686 | true); | ||
2687 | 2723 | ||
2688 | if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | 2724 | if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, |
2689 | elems.wmm_param_len)) | 2725 | elems.wmm_param_len)) |
@@ -3756,7 +3792,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3756 | struct ieee80211_bss *bss = (void *)req->bss->priv; | 3792 | struct ieee80211_bss *bss = (void *)req->bss->priv; |
3757 | struct ieee80211_mgd_assoc_data *assoc_data; | 3793 | struct ieee80211_mgd_assoc_data *assoc_data; |
3758 | struct ieee80211_supported_band *sband; | 3794 | struct ieee80211_supported_band *sband; |
3759 | const u8 *ssidie, *ht_ie; | 3795 | const u8 *ssidie, *ht_ie, *vht_ie; |
3760 | int i, err; | 3796 | int i, err; |
3761 | 3797 | ||
3762 | assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); | 3798 | assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); |
@@ -3875,6 +3911,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3875 | ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; | 3911 | ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; |
3876 | else | 3912 | else |
3877 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; | 3913 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
3914 | vht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_VHT_CAPABILITY); | ||
3915 | if (vht_ie && vht_ie[1] >= sizeof(struct ieee80211_vht_cap)) | ||
3916 | memcpy(&assoc_data->ap_vht_cap, vht_ie + 2, | ||
3917 | sizeof(struct ieee80211_vht_cap)); | ||
3918 | else | ||
3919 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
3878 | rcu_read_unlock(); | 3920 | rcu_read_unlock(); |
3879 | 3921 | ||
3880 | if (bss->wmm_used && bss->uapsd_supported && | 3922 | if (bss->wmm_used && bss->uapsd_supported && |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index a5379aea7d09..82baf5b6ecf4 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -102,8 +102,7 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | |||
102 | ieee80211_sta_reset_conn_monitor(sdata); | 102 | ieee80211_sta_reset_conn_monitor(sdata); |
103 | } | 103 | } |
104 | 104 | ||
105 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | 105 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) |
106 | bool offchannel_ps_enable) | ||
107 | { | 106 | { |
108 | struct ieee80211_sub_if_data *sdata; | 107 | struct ieee80211_sub_if_data *sdata; |
109 | 108 | ||
@@ -126,16 +125,17 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | |||
126 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | 125 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); |
127 | 126 | ||
128 | /* Check to see if we should disable beaconing. */ | 127 | /* Check to see if we should disable beaconing. */ |
129 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 128 | if (sdata->vif.bss_conf.enable_beacon) { |
130 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | 129 | set_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, |
131 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | 130 | &sdata->state); |
131 | sdata->vif.bss_conf.enable_beacon = false; | ||
132 | ieee80211_bss_info_change_notify( | 132 | ieee80211_bss_info_change_notify( |
133 | sdata, BSS_CHANGED_BEACON_ENABLED); | 133 | sdata, BSS_CHANGED_BEACON_ENABLED); |
134 | } | ||
134 | 135 | ||
135 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | 136 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { |
136 | netif_tx_stop_all_queues(sdata->dev); | 137 | netif_tx_stop_all_queues(sdata->dev); |
137 | if (offchannel_ps_enable && | 138 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
138 | (sdata->vif.type == NL80211_IFTYPE_STATION) && | ||
139 | sdata->u.mgd.associated) | 139 | sdata->u.mgd.associated) |
140 | ieee80211_offchannel_ps_enable(sdata); | 140 | ieee80211_offchannel_ps_enable(sdata); |
141 | } | 141 | } |
@@ -143,8 +143,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | |||
143 | mutex_unlock(&local->iflist_mtx); | 143 | mutex_unlock(&local->iflist_mtx); |
144 | } | 144 | } |
145 | 145 | ||
146 | void ieee80211_offchannel_return(struct ieee80211_local *local, | 146 | void ieee80211_offchannel_return(struct ieee80211_local *local) |
147 | bool offchannel_ps_disable) | ||
148 | { | 147 | { |
149 | struct ieee80211_sub_if_data *sdata; | 148 | struct ieee80211_sub_if_data *sdata; |
150 | 149 | ||
@@ -163,11 +162,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
163 | continue; | 162 | continue; |
164 | 163 | ||
165 | /* Tell AP we're back */ | 164 | /* Tell AP we're back */ |
166 | if (offchannel_ps_disable && | 165 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
167 | sdata->vif.type == NL80211_IFTYPE_STATION) { | 166 | sdata->u.mgd.associated) |
168 | if (sdata->u.mgd.associated) | 167 | ieee80211_offchannel_ps_disable(sdata); |
169 | ieee80211_offchannel_ps_disable(sdata); | ||
170 | } | ||
171 | 168 | ||
172 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | 169 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { |
173 | /* | 170 | /* |
@@ -183,11 +180,12 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
183 | netif_tx_wake_all_queues(sdata->dev); | 180 | netif_tx_wake_all_queues(sdata->dev); |
184 | } | 181 | } |
185 | 182 | ||
186 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 183 | if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, |
187 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | 184 | &sdata->state)) { |
188 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | 185 | sdata->vif.bss_conf.enable_beacon = true; |
189 | ieee80211_bss_info_change_notify( | 186 | ieee80211_bss_info_change_notify( |
190 | sdata, BSS_CHANGED_BEACON_ENABLED); | 187 | sdata, BSS_CHANGED_BEACON_ENABLED); |
188 | } | ||
191 | } | 189 | } |
192 | mutex_unlock(&local->iflist_mtx); | 190 | mutex_unlock(&local->iflist_mtx); |
193 | } | 191 | } |
@@ -385,7 +383,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
385 | local->tmp_channel = NULL; | 383 | local->tmp_channel = NULL; |
386 | ieee80211_hw_config(local, 0); | 384 | ieee80211_hw_config(local, 0); |
387 | 385 | ||
388 | ieee80211_offchannel_return(local, true); | 386 | ieee80211_offchannel_return(local); |
389 | } | 387 | } |
390 | 388 | ||
391 | ieee80211_recalc_idle(local); | 389 | ieee80211_recalc_idle(local); |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 79a48f37d409..e45b83610e85 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -7,25 +7,23 @@ | |||
7 | #include "led.h" | 7 | #include "led.h" |
8 | 8 | ||
9 | /* return value indicates whether the driver should be further notified */ | 9 | /* return value indicates whether the driver should be further notified */ |
10 | static bool ieee80211_quiesce(struct ieee80211_sub_if_data *sdata) | 10 | static void ieee80211_quiesce(struct ieee80211_sub_if_data *sdata) |
11 | { | 11 | { |
12 | switch (sdata->vif.type) { | 12 | switch (sdata->vif.type) { |
13 | case NL80211_IFTYPE_STATION: | 13 | case NL80211_IFTYPE_STATION: |
14 | ieee80211_sta_quiesce(sdata); | 14 | ieee80211_sta_quiesce(sdata); |
15 | return true; | 15 | break; |
16 | case NL80211_IFTYPE_ADHOC: | 16 | case NL80211_IFTYPE_ADHOC: |
17 | ieee80211_ibss_quiesce(sdata); | 17 | ieee80211_ibss_quiesce(sdata); |
18 | return true; | 18 | break; |
19 | case NL80211_IFTYPE_MESH_POINT: | 19 | case NL80211_IFTYPE_MESH_POINT: |
20 | ieee80211_mesh_quiesce(sdata); | 20 | ieee80211_mesh_quiesce(sdata); |
21 | return true; | 21 | break; |
22 | case NL80211_IFTYPE_AP_VLAN: | ||
23 | case NL80211_IFTYPE_MONITOR: | ||
24 | /* don't tell driver about this */ | ||
25 | return false; | ||
26 | default: | 22 | default: |
27 | return true; | 23 | break; |
28 | } | 24 | } |
25 | |||
26 | cancel_work_sync(&sdata->work); | ||
29 | } | 27 | } |
30 | 28 | ||
31 | int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | 29 | int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) |
@@ -44,7 +42,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
44 | mutex_lock(&local->sta_mtx); | 42 | mutex_lock(&local->sta_mtx); |
45 | list_for_each_entry(sta, &local->sta_list, list) { | 43 | list_for_each_entry(sta, &local->sta_list, list) { |
46 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | 44 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); |
47 | ieee80211_sta_tear_down_BA_sessions(sta, true); | 45 | ieee80211_sta_tear_down_BA_sessions( |
46 | sta, AGG_STOP_LOCAL_REQUEST); | ||
48 | } | 47 | } |
49 | mutex_unlock(&local->sta_mtx); | 48 | mutex_unlock(&local->sta_mtx); |
50 | } | 49 | } |
@@ -94,10 +93,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
94 | WARN_ON(err != 1); | 93 | WARN_ON(err != 1); |
95 | local->wowlan = false; | 94 | local->wowlan = false; |
96 | } else { | 95 | } else { |
97 | list_for_each_entry(sdata, &local->interfaces, list) { | 96 | list_for_each_entry(sdata, &local->interfaces, list) |
98 | cancel_work_sync(&sdata->work); | 97 | if (ieee80211_sdata_running(sdata)) |
99 | ieee80211_quiesce(sdata); | 98 | ieee80211_quiesce(sdata); |
100 | } | ||
101 | goto suspend; | 99 | goto suspend; |
102 | } | 100 | } |
103 | } | 101 | } |
@@ -124,17 +122,43 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
124 | 122 | ||
125 | /* remove all interfaces */ | 123 | /* remove all interfaces */ |
126 | list_for_each_entry(sdata, &local->interfaces, list) { | 124 | list_for_each_entry(sdata, &local->interfaces, list) { |
127 | cancel_work_sync(&sdata->work); | 125 | static u8 zero_addr[ETH_ALEN] = {}; |
126 | u32 changed = 0; | ||
128 | 127 | ||
129 | if (!ieee80211_quiesce(sdata)) | 128 | if (!ieee80211_sdata_running(sdata)) |
130 | continue; | 129 | continue; |
131 | 130 | ||
132 | if (!ieee80211_sdata_running(sdata)) | 131 | switch (sdata->vif.type) { |
132 | case NL80211_IFTYPE_AP_VLAN: | ||
133 | case NL80211_IFTYPE_MONITOR: | ||
134 | /* skip these */ | ||
133 | continue; | 135 | continue; |
136 | case NL80211_IFTYPE_STATION: | ||
137 | if (sdata->vif.bss_conf.assoc) | ||
138 | changed = BSS_CHANGED_ASSOC | | ||
139 | BSS_CHANGED_BSSID | | ||
140 | BSS_CHANGED_IDLE; | ||
141 | break; | ||
142 | case NL80211_IFTYPE_AP: | ||
143 | case NL80211_IFTYPE_ADHOC: | ||
144 | case NL80211_IFTYPE_MESH_POINT: | ||
145 | if (sdata->vif.bss_conf.enable_beacon) | ||
146 | changed = BSS_CHANGED_BEACON_ENABLED; | ||
147 | break; | ||
148 | default: | ||
149 | break; | ||
150 | } | ||
151 | |||
152 | ieee80211_quiesce(sdata); | ||
153 | |||
154 | sdata->suspend_bss_conf = sdata->vif.bss_conf; | ||
155 | memset(&sdata->vif.bss_conf, 0, sizeof(sdata->vif.bss_conf)); | ||
156 | sdata->vif.bss_conf.idle = true; | ||
157 | if (sdata->suspend_bss_conf.bssid) | ||
158 | sdata->vif.bss_conf.bssid = zero_addr; | ||
134 | 159 | ||
135 | /* disable beaconing */ | 160 | /* disable beaconing or remove association */ |
136 | ieee80211_bss_info_change_notify(sdata, | 161 | ieee80211_bss_info_change_notify(sdata, changed); |
137 | BSS_CHANGED_BEACON_ENABLED); | ||
138 | 162 | ||
139 | if (sdata->vif.type == NL80211_IFTYPE_AP && | 163 | if (sdata->vif.type == NL80211_IFTYPE_AP && |
140 | rcu_access_pointer(sdata->u.ap.beacon)) | 164 | rcu_access_pointer(sdata->u.ap.beacon)) |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 580704eba8b8..a19089565c4b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2353,7 +2353,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2353 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | 2353 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
2354 | break; | 2354 | break; |
2355 | 2355 | ||
2356 | /* verify action & smps_control are present */ | 2356 | /* verify action & smps_control/chanwidth are present */ |
2357 | if (len < IEEE80211_MIN_ACTION_SIZE + 2) | 2357 | if (len < IEEE80211_MIN_ACTION_SIZE + 2) |
2358 | goto invalid; | 2358 | goto invalid; |
2359 | 2359 | ||
@@ -2392,6 +2392,35 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2392 | IEEE80211_RC_SMPS_CHANGED); | 2392 | IEEE80211_RC_SMPS_CHANGED); |
2393 | goto handled; | 2393 | goto handled; |
2394 | } | 2394 | } |
2395 | case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { | ||
2396 | struct ieee80211_supported_band *sband; | ||
2397 | u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; | ||
2398 | bool old_40mhz, new_40mhz; | ||
2399 | |||
2400 | /* If it doesn't support 40 MHz it can't change ... */ | ||
2401 | if (!rx->sta->supports_40mhz) | ||
2402 | goto handled; | ||
2403 | |||
2404 | old_40mhz = rx->sta->sta.ht_cap.cap & | ||
2405 | IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
2406 | new_40mhz = chanwidth == IEEE80211_HT_CHANWIDTH_ANY; | ||
2407 | |||
2408 | if (old_40mhz == new_40mhz) | ||
2409 | goto handled; | ||
2410 | |||
2411 | if (new_40mhz) | ||
2412 | rx->sta->sta.ht_cap.cap |= | ||
2413 | IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
2414 | else | ||
2415 | rx->sta->sta.ht_cap.cap &= | ||
2416 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
2417 | |||
2418 | sband = rx->local->hw.wiphy->bands[status->band]; | ||
2419 | |||
2420 | rate_control_rate_update(local, sband, rx->sta, | ||
2421 | IEEE80211_RC_BW_CHANGED); | ||
2422 | goto handled; | ||
2423 | } | ||
2395 | default: | 2424 | default: |
2396 | goto invalid; | 2425 | goto invalid; |
2397 | } | 2426 | } |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index d59fc6818b1c..607684c47d55 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -65,12 +65,11 @@ static bool is_uapsd_supported(struct ieee802_11_elems *elems) | |||
65 | struct ieee80211_bss * | 65 | struct ieee80211_bss * |
66 | ieee80211_bss_info_update(struct ieee80211_local *local, | 66 | ieee80211_bss_info_update(struct ieee80211_local *local, |
67 | struct ieee80211_rx_status *rx_status, | 67 | struct ieee80211_rx_status *rx_status, |
68 | struct ieee80211_mgmt *mgmt, | 68 | struct ieee80211_mgmt *mgmt, size_t len, |
69 | size_t len, | ||
70 | struct ieee802_11_elems *elems, | 69 | struct ieee802_11_elems *elems, |
71 | struct ieee80211_channel *channel, | 70 | struct ieee80211_channel *channel) |
72 | bool beacon) | ||
73 | { | 71 | { |
72 | bool beacon = ieee80211_is_beacon(mgmt->frame_control); | ||
74 | struct cfg80211_bss *cbss; | 73 | struct cfg80211_bss *cbss; |
75 | struct ieee80211_bss *bss; | 74 | struct ieee80211_bss *bss; |
76 | int clen, srlen; | 75 | int clen, srlen; |
@@ -203,7 +202,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
203 | 202 | ||
204 | bss = ieee80211_bss_info_update(local, rx_status, | 203 | bss = ieee80211_bss_info_update(local, rx_status, |
205 | mgmt, skb->len, &elems, | 204 | mgmt, skb->len, &elems, |
206 | channel, beacon); | 205 | channel); |
207 | if (bss) | 206 | if (bss) |
208 | ieee80211_rx_bss_put(local, bss); | 207 | ieee80211_rx_bss_put(local, bss); |
209 | } | 208 | } |
@@ -292,7 +291,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
292 | if (!was_hw_scan) { | 291 | if (!was_hw_scan) { |
293 | ieee80211_configure_filter(local); | 292 | ieee80211_configure_filter(local); |
294 | drv_sw_scan_complete(local); | 293 | drv_sw_scan_complete(local); |
295 | ieee80211_offchannel_return(local, true); | 294 | ieee80211_offchannel_return(local); |
296 | } | 295 | } |
297 | 296 | ||
298 | ieee80211_recalc_idle(local); | 297 | ieee80211_recalc_idle(local); |
@@ -341,7 +340,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
341 | local->next_scan_state = SCAN_DECISION; | 340 | local->next_scan_state = SCAN_DECISION; |
342 | local->scan_channel_idx = 0; | 341 | local->scan_channel_idx = 0; |
343 | 342 | ||
344 | ieee80211_offchannel_stop_vifs(local, true); | 343 | ieee80211_offchannel_stop_vifs(local); |
345 | 344 | ||
346 | ieee80211_configure_filter(local); | 345 | ieee80211_configure_filter(local); |
347 | 346 | ||
@@ -678,12 +677,8 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, | |||
678 | local->scan_channel = NULL; | 677 | local->scan_channel = NULL; |
679 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 678 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
680 | 679 | ||
681 | /* | 680 | /* disable PS */ |
682 | * Re-enable vifs and beaconing. Leave PS | 681 | ieee80211_offchannel_return(local); |
683 | * in off-channel state..will put that back | ||
684 | * on-channel at the end of scanning. | ||
685 | */ | ||
686 | ieee80211_offchannel_return(local, false); | ||
687 | 682 | ||
688 | *next_delay = HZ / 5; | 683 | *next_delay = HZ / 5; |
689 | /* afterwards, resume scan & go to next channel */ | 684 | /* afterwards, resume scan & go to next channel */ |
@@ -693,8 +688,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, | |||
693 | static void ieee80211_scan_state_resume(struct ieee80211_local *local, | 688 | static void ieee80211_scan_state_resume(struct ieee80211_local *local, |
694 | unsigned long *next_delay) | 689 | unsigned long *next_delay) |
695 | { | 690 | { |
696 | /* PS already is in off-channel mode */ | 691 | ieee80211_offchannel_stop_vifs(local); |
697 | ieee80211_offchannel_stop_vifs(local, false); | ||
698 | 692 | ||
699 | if (local->ops->flush) { | 693 | if (local->ops->flush) { |
700 | drv_flush(local, false); | 694 | drv_flush(local, false); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ca9fde198188..9d864ed5f3da 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -104,6 +104,16 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
104 | * neither mac80211 nor the driver can reference this | 104 | * neither mac80211 nor the driver can reference this |
105 | * sta struct any more except by still existing timers | 105 | * sta struct any more except by still existing timers |
106 | * associated with this station that we clean up below. | 106 | * associated with this station that we clean up below. |
107 | * | ||
108 | * Note though that this still uses the sdata and even | ||
109 | * calls the driver in AP and mesh mode, so interfaces | ||
110 | * of those types mush use call sta_info_flush_cleanup() | ||
111 | * (typically via sta_info_flush()) before deconfiguring | ||
112 | * the driver. | ||
113 | * | ||
114 | * In station mode, nothing happens here so it doesn't | ||
115 | * have to (and doesn't) do that, this is intentional to | ||
116 | * speed up roaming. | ||
107 | */ | 117 | */ |
108 | 118 | ||
109 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { | 119 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { |
@@ -774,7 +784,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
774 | * will be sufficient. | 784 | * will be sufficient. |
775 | */ | 785 | */ |
776 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | 786 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); |
777 | ieee80211_sta_tear_down_BA_sessions(sta, false); | 787 | ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA); |
778 | 788 | ||
779 | ret = sta_info_hash_del(local, sta); | 789 | ret = sta_info_hash_del(local, sta); |
780 | if (ret) | 790 | if (ret) |
@@ -885,20 +895,12 @@ void sta_info_init(struct ieee80211_local *local) | |||
885 | void sta_info_stop(struct ieee80211_local *local) | 895 | void sta_info_stop(struct ieee80211_local *local) |
886 | { | 896 | { |
887 | del_timer_sync(&local->sta_cleanup); | 897 | del_timer_sync(&local->sta_cleanup); |
888 | sta_info_flush(local, NULL); | ||
889 | } | 898 | } |
890 | 899 | ||
891 | /** | 900 | |
892 | * sta_info_flush - flush matching STA entries from the STA table | 901 | int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata) |
893 | * | ||
894 | * Returns the number of removed STA entries. | ||
895 | * | ||
896 | * @local: local interface data | ||
897 | * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs | ||
898 | */ | ||
899 | int sta_info_flush(struct ieee80211_local *local, | ||
900 | struct ieee80211_sub_if_data *sdata) | ||
901 | { | 902 | { |
903 | struct ieee80211_local *local = sdata->local; | ||
902 | struct sta_info *sta, *tmp; | 904 | struct sta_info *sta, *tmp; |
903 | int ret = 0; | 905 | int ret = 0; |
904 | 906 | ||
@@ -906,30 +908,22 @@ int sta_info_flush(struct ieee80211_local *local, | |||
906 | 908 | ||
907 | mutex_lock(&local->sta_mtx); | 909 | mutex_lock(&local->sta_mtx); |
908 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | 910 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { |
909 | if (!sdata || sdata == sta->sdata) { | 911 | if (sdata == sta->sdata) { |
910 | WARN_ON(__sta_info_destroy(sta)); | 912 | WARN_ON(__sta_info_destroy(sta)); |
911 | ret++; | 913 | ret++; |
912 | } | 914 | } |
913 | } | 915 | } |
914 | mutex_unlock(&local->sta_mtx); | 916 | mutex_unlock(&local->sta_mtx); |
915 | 917 | ||
916 | rcu_barrier(); | ||
917 | |||
918 | if (sdata) { | ||
919 | ieee80211_cleanup_sdata_stas(sdata); | ||
920 | cancel_work_sync(&sdata->cleanup_stations_wk); | ||
921 | } else { | ||
922 | mutex_lock(&local->iflist_mtx); | ||
923 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
924 | ieee80211_cleanup_sdata_stas(sdata); | ||
925 | cancel_work_sync(&sdata->cleanup_stations_wk); | ||
926 | } | ||
927 | mutex_unlock(&local->iflist_mtx); | ||
928 | } | ||
929 | |||
930 | return ret; | 918 | return ret; |
931 | } | 919 | } |
932 | 920 | ||
921 | void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata) | ||
922 | { | ||
923 | ieee80211_cleanup_sdata_stas(sdata); | ||
924 | cancel_work_sync(&sdata->cleanup_stations_wk); | ||
925 | } | ||
926 | |||
933 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | 927 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, |
934 | unsigned long exp_time) | 928 | unsigned long exp_time) |
935 | { | 929 | { |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 37c1889afd3a..af7d78aa5523 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -92,6 +92,13 @@ enum ieee80211_sta_info_flags { | |||
92 | #define HT_AGG_STATE_WANT_START 4 | 92 | #define HT_AGG_STATE_WANT_START 4 |
93 | #define HT_AGG_STATE_WANT_STOP 5 | 93 | #define HT_AGG_STATE_WANT_STOP 5 |
94 | 94 | ||
95 | enum ieee80211_agg_stop_reason { | ||
96 | AGG_STOP_DECLINED, | ||
97 | AGG_STOP_LOCAL_REQUEST, | ||
98 | AGG_STOP_PEER_REQUEST, | ||
99 | AGG_STOP_DESTROY_STA, | ||
100 | }; | ||
101 | |||
95 | /** | 102 | /** |
96 | * struct tid_ampdu_tx - TID aggregation information (Tx). | 103 | * struct tid_ampdu_tx - TID aggregation information (Tx). |
97 | * | 104 | * |
@@ -548,8 +555,39 @@ void sta_info_recalc_tim(struct sta_info *sta); | |||
548 | 555 | ||
549 | void sta_info_init(struct ieee80211_local *local); | 556 | void sta_info_init(struct ieee80211_local *local); |
550 | void sta_info_stop(struct ieee80211_local *local); | 557 | void sta_info_stop(struct ieee80211_local *local); |
551 | int sta_info_flush(struct ieee80211_local *local, | 558 | int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata); |
552 | struct ieee80211_sub_if_data *sdata); | 559 | |
560 | /** | ||
561 | * sta_info_flush_cleanup - flush the sta_info cleanup queue | ||
562 | * @sdata: the interface | ||
563 | * | ||
564 | * Flushes the sta_info cleanup queue for a given interface; | ||
565 | * this is necessary before the interface is removed or, for | ||
566 | * AP/mesh interfaces, before it is deconfigured. | ||
567 | * | ||
568 | * Note an rcu_barrier() must precede the function, after all | ||
569 | * stations have been flushed/removed to ensure the call_rcu() | ||
570 | * calls that add stations to the cleanup queue have completed. | ||
571 | */ | ||
572 | void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata); | ||
573 | |||
574 | /** | ||
575 | * sta_info_flush - flush matching STA entries from the STA table | ||
576 | * | ||
577 | * Returns the number of removed STA entries. | ||
578 | * | ||
579 | * @sdata: sdata to remove all stations from | ||
580 | */ | ||
581 | static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata) | ||
582 | { | ||
583 | int ret = sta_info_flush_defer(sdata); | ||
584 | |||
585 | rcu_barrier(); | ||
586 | sta_info_flush_cleanup(sdata); | ||
587 | |||
588 | return ret; | ||
589 | } | ||
590 | |||
553 | void sta_set_rate_info_tx(struct sta_info *sta, | 591 | void sta_set_rate_info_tx(struct sta_info *sta, |
554 | const struct ieee80211_tx_rate *rate, | 592 | const struct ieee80211_tx_rate *rate, |
555 | struct rate_info *rinfo); | 593 | struct rate_info *rinfo); |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index a8270b441a6f..41861b91daa3 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -28,21 +28,27 @@ | |||
28 | #define VIF_PR_FMT " vif:%s(%d%s)" | 28 | #define VIF_PR_FMT " vif:%s(%d%s)" |
29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" | 29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" |
30 | 30 | ||
31 | #define CHANCTX_ENTRY __field(u32, control_freq) \ | 31 | #define CHANDEF_ENTRY __field(u32, control_freq) \ |
32 | __field(u32, chan_width) \ | 32 | __field(u32, chan_width) \ |
33 | __field(u32, center_freq1) \ | 33 | __field(u32, center_freq1) \ |
34 | __field(u32, center_freq2) \ | 34 | __field(u32, center_freq2) |
35 | #define CHANDEF_ASSIGN(c) \ | ||
36 | __entry->control_freq = (c)->chan->center_freq; \ | ||
37 | __entry->chan_width = (c)->width; \ | ||
38 | __entry->center_freq1 = (c)->center_freq1; \ | ||
39 | __entry->center_freq1 = (c)->center_freq2; | ||
40 | #define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz" | ||
41 | #define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \ | ||
42 | __entry->center_freq1, __entry->center_freq2 | ||
43 | |||
44 | #define CHANCTX_ENTRY CHANDEF_ENTRY \ | ||
35 | __field(u8, rx_chains_static) \ | 45 | __field(u8, rx_chains_static) \ |
36 | __field(u8, rx_chains_dynamic) | 46 | __field(u8, rx_chains_dynamic) |
37 | #define CHANCTX_ASSIGN __entry->control_freq = ctx->conf.def.chan->center_freq;\ | 47 | #define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \ |
38 | __entry->chan_width = ctx->conf.def.width; \ | ||
39 | __entry->center_freq1 = ctx->conf.def.center_freq1; \ | ||
40 | __entry->center_freq2 = ctx->conf.def.center_freq2; \ | ||
41 | __entry->rx_chains_static = ctx->conf.rx_chains_static; \ | 48 | __entry->rx_chains_static = ctx->conf.rx_chains_static; \ |
42 | __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic | 49 | __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic |
43 | #define CHANCTX_PR_FMT " control:%d MHz width:%d center: %d/%d MHz chains:%d/%d" | 50 | #define CHANCTX_PR_FMT CHANDEF_PR_FMT " chains:%d/%d" |
44 | #define CHANCTX_PR_ARG __entry->control_freq, __entry->chan_width, \ | 51 | #define CHANCTX_PR_ARG CHANDEF_PR_ARG, \ |
45 | __entry->center_freq1, __entry->center_freq2, \ | ||
46 | __entry->rx_chains_static, __entry->rx_chains_dynamic | 52 | __entry->rx_chains_static, __entry->rx_chains_dynamic |
47 | 53 | ||
48 | 54 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e9eadc40c09c..f32d68186dbc 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1673,10 +1673,13 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1673 | chanctx_conf = | 1673 | chanctx_conf = |
1674 | rcu_dereference(tmp_sdata->vif.chanctx_conf); | 1674 | rcu_dereference(tmp_sdata->vif.chanctx_conf); |
1675 | } | 1675 | } |
1676 | if (!chanctx_conf) | ||
1677 | goto fail_rcu; | ||
1678 | 1676 | ||
1679 | chan = chanctx_conf->def.chan; | 1677 | if (chanctx_conf) |
1678 | chan = chanctx_conf->def.chan; | ||
1679 | else if (!local->use_chanctx) | ||
1680 | chan = local->_oper_channel; | ||
1681 | else | ||
1682 | goto fail_rcu; | ||
1680 | 1683 | ||
1681 | /* | 1684 | /* |
1682 | * Frame injection is not allowed if beaconing is not allowed | 1685 | * Frame injection is not allowed if beaconing is not allowed |
@@ -2261,9 +2264,8 @@ void ieee80211_tx_pending(unsigned long data) | |||
2261 | 2264 | ||
2262 | /* functions for drivers to get certain frames */ | 2265 | /* functions for drivers to get certain frames */ |
2263 | 2266 | ||
2264 | static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | 2267 | static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, |
2265 | struct ps_data *ps, | 2268 | struct ps_data *ps, struct sk_buff *skb) |
2266 | struct sk_buff *skb) | ||
2267 | { | 2269 | { |
2268 | u8 *pos, *tim; | 2270 | u8 *pos, *tim; |
2269 | int aid0 = 0; | 2271 | int aid0 = 0; |
@@ -2325,6 +2327,31 @@ static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | |||
2325 | } | 2327 | } |
2326 | } | 2328 | } |
2327 | 2329 | ||
2330 | static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | ||
2331 | struct ps_data *ps, struct sk_buff *skb) | ||
2332 | { | ||
2333 | struct ieee80211_local *local = sdata->local; | ||
2334 | |||
2335 | /* | ||
2336 | * Not very nice, but we want to allow the driver to call | ||
2337 | * ieee80211_beacon_get() as a response to the set_tim() | ||
2338 | * callback. That, however, is already invoked under the | ||
2339 | * sta_lock to guarantee consistent and race-free update | ||
2340 | * of the tim bitmap in mac80211 and the driver. | ||
2341 | */ | ||
2342 | if (local->tim_in_locked_section) { | ||
2343 | __ieee80211_beacon_add_tim(sdata, ps, skb); | ||
2344 | } else { | ||
2345 | unsigned long flags; | ||
2346 | |||
2347 | spin_lock_irqsave(&local->tim_lock, flags); | ||
2348 | __ieee80211_beacon_add_tim(sdata, ps, skb); | ||
2349 | spin_unlock_irqrestore(&local->tim_lock, flags); | ||
2350 | } | ||
2351 | |||
2352 | return 0; | ||
2353 | } | ||
2354 | |||
2328 | struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | 2355 | struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, |
2329 | struct ieee80211_vif *vif, | 2356 | struct ieee80211_vif *vif, |
2330 | u16 *tim_offset, u16 *tim_length) | 2357 | u16 *tim_offset, u16 *tim_length) |
@@ -2369,22 +2396,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2369 | memcpy(skb_put(skb, beacon->head_len), beacon->head, | 2396 | memcpy(skb_put(skb, beacon->head_len), beacon->head, |
2370 | beacon->head_len); | 2397 | beacon->head_len); |
2371 | 2398 | ||
2372 | /* | 2399 | ieee80211_beacon_add_tim(sdata, &ap->ps, skb); |
2373 | * Not very nice, but we want to allow the driver to call | ||
2374 | * ieee80211_beacon_get() as a response to the set_tim() | ||
2375 | * callback. That, however, is already invoked under the | ||
2376 | * sta_lock to guarantee consistent and race-free update | ||
2377 | * of the tim bitmap in mac80211 and the driver. | ||
2378 | */ | ||
2379 | if (local->tim_in_locked_section) { | ||
2380 | ieee80211_beacon_add_tim(sdata, &ap->ps, skb); | ||
2381 | } else { | ||
2382 | unsigned long flags; | ||
2383 | |||
2384 | spin_lock_irqsave(&local->tim_lock, flags); | ||
2385 | ieee80211_beacon_add_tim(sdata, &ap->ps, skb); | ||
2386 | spin_unlock_irqrestore(&local->tim_lock, flags); | ||
2387 | } | ||
2388 | 2400 | ||
2389 | if (tim_offset) | 2401 | if (tim_offset) |
2390 | *tim_offset = beacon->head_len; | 2402 | *tim_offset = beacon->head_len; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index f11e8c540db4..7519018ff71a 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1358,6 +1358,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1358 | struct ieee80211_chanctx *ctx; | 1358 | struct ieee80211_chanctx *ctx; |
1359 | struct sta_info *sta; | 1359 | struct sta_info *sta; |
1360 | int res, i; | 1360 | int res, i; |
1361 | bool reconfig_due_to_wowlan = false; | ||
1361 | 1362 | ||
1362 | #ifdef CONFIG_PM | 1363 | #ifdef CONFIG_PM |
1363 | if (local->suspended) | 1364 | if (local->suspended) |
@@ -1377,6 +1378,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1377 | * res is 1, which means the driver requested | 1378 | * res is 1, which means the driver requested |
1378 | * to go through a regular reset on wakeup. | 1379 | * to go through a regular reset on wakeup. |
1379 | */ | 1380 | */ |
1381 | reconfig_due_to_wowlan = true; | ||
1380 | } | 1382 | } |
1381 | #endif | 1383 | #endif |
1382 | /* everything else happens only if HW was up & running */ | 1384 | /* everything else happens only if HW was up & running */ |
@@ -1526,6 +1528,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1526 | BSS_CHANGED_IDLE | | 1528 | BSS_CHANGED_IDLE | |
1527 | BSS_CHANGED_TXPOWER; | 1529 | BSS_CHANGED_TXPOWER; |
1528 | 1530 | ||
1531 | #ifdef CONFIG_PM | ||
1532 | if (local->resuming && !reconfig_due_to_wowlan) | ||
1533 | sdata->vif.bss_conf = sdata->suspend_bss_conf; | ||
1534 | #endif | ||
1535 | |||
1529 | switch (sdata->vif.type) { | 1536 | switch (sdata->vif.type) { |
1530 | case NL80211_IFTYPE_STATION: | 1537 | case NL80211_IFTYPE_STATION: |
1531 | changed |= BSS_CHANGED_ASSOC | | 1538 | changed |= BSS_CHANGED_ASSOC | |
@@ -1550,9 +1557,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1550 | 1557 | ||
1551 | /* fall through */ | 1558 | /* fall through */ |
1552 | case NL80211_IFTYPE_MESH_POINT: | 1559 | case NL80211_IFTYPE_MESH_POINT: |
1553 | changed |= BSS_CHANGED_BEACON | | 1560 | if (sdata->vif.bss_conf.enable_beacon) { |
1554 | BSS_CHANGED_BEACON_ENABLED; | 1561 | changed |= BSS_CHANGED_BEACON | |
1555 | ieee80211_bss_info_change_notify(sdata, changed); | 1562 | BSS_CHANGED_BEACON_ENABLED; |
1563 | ieee80211_bss_info_change_notify(sdata, changed); | ||
1564 | } | ||
1556 | break; | 1565 | break; |
1557 | case NL80211_IFTYPE_WDS: | 1566 | case NL80211_IFTYPE_WDS: |
1558 | break; | 1567 | break; |
@@ -1632,7 +1641,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1632 | mutex_lock(&local->sta_mtx); | 1641 | mutex_lock(&local->sta_mtx); |
1633 | 1642 | ||
1634 | list_for_each_entry(sta, &local->sta_list, list) { | 1643 | list_for_each_entry(sta, &local->sta_list, list) { |
1635 | ieee80211_sta_tear_down_BA_sessions(sta, true); | 1644 | ieee80211_sta_tear_down_BA_sessions( |
1645 | sta, AGG_STOP_LOCAL_REQUEST); | ||
1636 | clear_sta_flag(sta, WLAN_STA_BLOCK_BA); | 1646 | clear_sta_flag(sta, WLAN_STA_BLOCK_BA); |
1637 | } | 1647 | } |
1638 | 1648 | ||
@@ -1646,10 +1656,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1646 | * If this is for hw restart things are still running. | 1656 | * If this is for hw restart things are still running. |
1647 | * We may want to change that later, however. | 1657 | * We may want to change that later, however. |
1648 | */ | 1658 | */ |
1649 | if (!local->suspended) { | 1659 | if (!local->suspended || reconfig_due_to_wowlan) |
1650 | drv_restart_complete(local); | 1660 | drv_restart_complete(local); |
1661 | |||
1662 | if (!local->suspended) | ||
1651 | return 0; | 1663 | return 0; |
1652 | } | ||
1653 | 1664 | ||
1654 | #ifdef CONFIG_PM | 1665 | #ifdef CONFIG_PM |
1655 | /* first set suspended false, then resuming */ | 1666 | /* first set suspended false, then resuming */ |
@@ -1864,7 +1875,7 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1864 | } | 1875 | } |
1865 | 1876 | ||
1866 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | 1877 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, |
1867 | u32 cap) | 1878 | u32 cap) |
1868 | { | 1879 | { |
1869 | __le32 tmp; | 1880 | __le32 tmp; |
1870 | 1881 | ||
diff --git a/net/nfc/core.c b/net/nfc/core.c index aa64ea441676..25522e56d350 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -338,7 +338,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) | |||
338 | dev->active_target = target; | 338 | dev->active_target = target; |
339 | dev->rf_mode = NFC_RF_INITIATOR; | 339 | dev->rf_mode = NFC_RF_INITIATOR; |
340 | 340 | ||
341 | if (dev->ops->check_presence) | 341 | if (dev->ops->check_presence && !dev->shutting_down) |
342 | mod_timer(&dev->check_pres_timer, jiffies + | 342 | mod_timer(&dev->check_pres_timer, jiffies + |
343 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | 343 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); |
344 | } | 344 | } |
@@ -429,7 +429,7 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, | |||
429 | rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, | 429 | rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, |
430 | cb_context); | 430 | cb_context); |
431 | 431 | ||
432 | if (!rc && dev->ops->check_presence) | 432 | if (!rc && dev->ops->check_presence && !dev->shutting_down) |
433 | mod_timer(&dev->check_pres_timer, jiffies + | 433 | mod_timer(&dev->check_pres_timer, jiffies + |
434 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | 434 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); |
435 | } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) { | 435 | } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) { |
@@ -684,11 +684,6 @@ static void nfc_release(struct device *d) | |||
684 | 684 | ||
685 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); | 685 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); |
686 | 686 | ||
687 | if (dev->ops->check_presence) { | ||
688 | del_timer_sync(&dev->check_pres_timer); | ||
689 | cancel_work_sync(&dev->check_pres_work); | ||
690 | } | ||
691 | |||
692 | nfc_genl_data_exit(&dev->genl_data); | 687 | nfc_genl_data_exit(&dev->genl_data); |
693 | kfree(dev->targets); | 688 | kfree(dev->targets); |
694 | kfree(dev); | 689 | kfree(dev); |
@@ -706,15 +701,16 @@ static void nfc_check_pres_work(struct work_struct *work) | |||
706 | rc = dev->ops->check_presence(dev, dev->active_target); | 701 | rc = dev->ops->check_presence(dev, dev->active_target); |
707 | if (rc == -EOPNOTSUPP) | 702 | if (rc == -EOPNOTSUPP) |
708 | goto exit; | 703 | goto exit; |
709 | if (!rc) { | 704 | if (rc) { |
710 | mod_timer(&dev->check_pres_timer, jiffies + | ||
711 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
712 | } else { | ||
713 | u32 active_target_idx = dev->active_target->idx; | 705 | u32 active_target_idx = dev->active_target->idx; |
714 | device_unlock(&dev->dev); | 706 | device_unlock(&dev->dev); |
715 | nfc_target_lost(dev, active_target_idx); | 707 | nfc_target_lost(dev, active_target_idx); |
716 | return; | 708 | return; |
717 | } | 709 | } |
710 | |||
711 | if (!dev->shutting_down) | ||
712 | mod_timer(&dev->check_pres_timer, jiffies + | ||
713 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
718 | } | 714 | } |
719 | 715 | ||
720 | exit: | 716 | exit: |
@@ -761,6 +757,7 @@ struct nfc_dev *nfc_get_device(unsigned int idx) | |||
761 | */ | 757 | */ |
762 | struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | 758 | struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, |
763 | u32 supported_protocols, | 759 | u32 supported_protocols, |
760 | u32 supported_se, | ||
764 | int tx_headroom, int tx_tailroom) | 761 | int tx_headroom, int tx_tailroom) |
765 | { | 762 | { |
766 | struct nfc_dev *dev; | 763 | struct nfc_dev *dev; |
@@ -778,6 +775,8 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
778 | 775 | ||
779 | dev->ops = ops; | 776 | dev->ops = ops; |
780 | dev->supported_protocols = supported_protocols; | 777 | dev->supported_protocols = supported_protocols; |
778 | dev->supported_se = supported_se; | ||
779 | dev->active_se = NFC_SE_NONE; | ||
781 | dev->tx_headroom = tx_headroom; | 780 | dev->tx_headroom = tx_headroom; |
782 | dev->tx_tailroom = tx_tailroom; | 781 | dev->tx_tailroom = tx_tailroom; |
783 | 782 | ||
@@ -853,26 +852,27 @@ void nfc_unregister_device(struct nfc_dev *dev) | |||
853 | 852 | ||
854 | id = dev->idx; | 853 | id = dev->idx; |
855 | 854 | ||
856 | mutex_lock(&nfc_devlist_mutex); | 855 | if (dev->ops->check_presence) { |
857 | nfc_devlist_generation++; | 856 | device_lock(&dev->dev); |
858 | 857 | dev->shutting_down = true; | |
859 | /* lock to avoid unregistering a device while an operation | 858 | device_unlock(&dev->dev); |
860 | is in progress */ | 859 | del_timer_sync(&dev->check_pres_timer); |
861 | device_lock(&dev->dev); | 860 | cancel_work_sync(&dev->check_pres_work); |
862 | device_del(&dev->dev); | 861 | } |
863 | device_unlock(&dev->dev); | ||
864 | 862 | ||
865 | mutex_unlock(&nfc_devlist_mutex); | 863 | rc = nfc_genl_device_removed(dev); |
864 | if (rc) | ||
865 | pr_debug("The userspace won't be notified that the device %s " | ||
866 | "was removed\n", dev_name(&dev->dev)); | ||
866 | 867 | ||
867 | nfc_llcp_unregister_device(dev); | 868 | nfc_llcp_unregister_device(dev); |
868 | 869 | ||
869 | rc = nfc_genl_device_removed(dev); | 870 | mutex_lock(&nfc_devlist_mutex); |
870 | if (rc) | 871 | nfc_devlist_generation++; |
871 | pr_debug("The userspace won't be notified that the device %s was removed\n", | 872 | device_del(&dev->dev); |
872 | dev_name(&dev->dev)); | 873 | mutex_unlock(&nfc_devlist_mutex); |
873 | 874 | ||
874 | ida_simple_remove(&nfc_index_ida, id); | 875 | ida_simple_remove(&nfc_index_ida, id); |
875 | |||
876 | } | 876 | } |
877 | EXPORT_SYMBOL(nfc_unregister_device); | 877 | EXPORT_SYMBOL(nfc_unregister_device); |
878 | 878 | ||
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index 7d99410e6c1a..64f922be9281 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c | |||
@@ -280,14 +280,19 @@ static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe) | |||
280 | static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) | 280 | static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) |
281 | { | 281 | { |
282 | u8 param[2]; | 282 | u8 param[2]; |
283 | size_t param_len = 2; | ||
283 | 284 | ||
284 | /* TODO: Find out what the identity reference data is | 285 | /* TODO: Find out what the identity reference data is |
285 | * and fill param with it. HCI spec 6.1.3.5 */ | 286 | * and fill param with it. HCI spec 6.1.3.5 */ |
286 | 287 | ||
287 | pr_debug("\n"); | 288 | pr_debug("\n"); |
288 | 289 | ||
290 | if (test_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &hdev->quirks)) | ||
291 | param_len = 0; | ||
292 | |||
289 | return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, | 293 | return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, |
290 | NFC_HCI_ADM_CLEAR_ALL_PIPE, param, 2, NULL); | 294 | NFC_HCI_ADM_CLEAR_ALL_PIPE, param, param_len, |
295 | NULL); | ||
291 | } | 296 | } |
292 | 297 | ||
293 | int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate) | 298 | int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate) |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 7bea574d5934..91020b210d87 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -57,6 +57,8 @@ static void nfc_hci_msg_tx_work(struct work_struct *work) | |||
57 | int r = 0; | 57 | int r = 0; |
58 | 58 | ||
59 | mutex_lock(&hdev->msg_tx_mutex); | 59 | mutex_lock(&hdev->msg_tx_mutex); |
60 | if (hdev->shutting_down) | ||
61 | goto exit; | ||
60 | 62 | ||
61 | if (hdev->cmd_pending_msg) { | 63 | if (hdev->cmd_pending_msg) { |
62 | if (timer_pending(&hdev->cmd_timer) == 0) { | 64 | if (timer_pending(&hdev->cmd_timer) == 0) { |
@@ -295,6 +297,12 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | |||
295 | goto exit; | 297 | goto exit; |
296 | } | 298 | } |
297 | 299 | ||
300 | if (hdev->ops->event_received) { | ||
301 | r = hdev->ops->event_received(hdev, gate, event, skb); | ||
302 | if (r <= 0) | ||
303 | goto exit_noskb; | ||
304 | } | ||
305 | |||
298 | switch (event) { | 306 | switch (event) { |
299 | case NFC_HCI_EVT_TARGET_DISCOVERED: | 307 | case NFC_HCI_EVT_TARGET_DISCOVERED: |
300 | if (skb->len < 1) { /* no status data? */ | 308 | if (skb->len < 1) { /* no status data? */ |
@@ -320,17 +328,15 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | |||
320 | r = nfc_hci_target_discovered(hdev, gate); | 328 | r = nfc_hci_target_discovered(hdev, gate); |
321 | break; | 329 | break; |
322 | default: | 330 | default: |
323 | if (hdev->ops->event_received) { | 331 | pr_info("Discarded unknown event %x to gate %x\n", event, gate); |
324 | hdev->ops->event_received(hdev, gate, event, skb); | 332 | r = -EINVAL; |
325 | return; | ||
326 | } | ||
327 | |||
328 | break; | 333 | break; |
329 | } | 334 | } |
330 | 335 | ||
331 | exit: | 336 | exit: |
332 | kfree_skb(skb); | 337 | kfree_skb(skb); |
333 | 338 | ||
339 | exit_noskb: | ||
334 | if (r) { | 340 | if (r) { |
335 | /* TODO: There was an error dispatching the event, | 341 | /* TODO: There was an error dispatching the event, |
336 | * how to propagate up to nfc core? | 342 | * how to propagate up to nfc core? |
@@ -669,8 +675,10 @@ static int hci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | |||
669 | 675 | ||
670 | if (hdev->ops->tm_send) | 676 | if (hdev->ops->tm_send) |
671 | return hdev->ops->tm_send(hdev, skb); | 677 | return hdev->ops->tm_send(hdev, skb); |
672 | else | 678 | |
673 | return -ENOTSUPP; | 679 | kfree_skb(skb); |
680 | |||
681 | return -ENOTSUPP; | ||
674 | } | 682 | } |
675 | 683 | ||
676 | static int hci_check_presence(struct nfc_dev *nfc_dev, | 684 | static int hci_check_presence(struct nfc_dev *nfc_dev, |
@@ -787,7 +795,9 @@ static struct nfc_ops hci_nfc_ops = { | |||
787 | 795 | ||
788 | struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, | 796 | struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, |
789 | struct nfc_hci_init_data *init_data, | 797 | struct nfc_hci_init_data *init_data, |
798 | unsigned long quirks, | ||
790 | u32 protocols, | 799 | u32 protocols, |
800 | u32 supported_se, | ||
791 | const char *llc_name, | 801 | const char *llc_name, |
792 | int tx_headroom, | 802 | int tx_headroom, |
793 | int tx_tailroom, | 803 | int tx_tailroom, |
@@ -813,7 +823,7 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, | |||
813 | return NULL; | 823 | return NULL; |
814 | } | 824 | } |
815 | 825 | ||
816 | hdev->ndev = nfc_allocate_device(&hci_nfc_ops, protocols, | 826 | hdev->ndev = nfc_allocate_device(&hci_nfc_ops, protocols, supported_se, |
817 | tx_headroom + HCI_CMDS_HEADROOM, | 827 | tx_headroom + HCI_CMDS_HEADROOM, |
818 | tx_tailroom); | 828 | tx_tailroom); |
819 | if (!hdev->ndev) { | 829 | if (!hdev->ndev) { |
@@ -830,6 +840,8 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, | |||
830 | 840 | ||
831 | memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); | 841 | memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); |
832 | 842 | ||
843 | hdev->quirks = quirks; | ||
844 | |||
833 | return hdev; | 845 | return hdev; |
834 | } | 846 | } |
835 | EXPORT_SYMBOL(nfc_hci_allocate_device); | 847 | EXPORT_SYMBOL(nfc_hci_allocate_device); |
@@ -868,6 +880,28 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev) | |||
868 | { | 880 | { |
869 | struct hci_msg *msg, *n; | 881 | struct hci_msg *msg, *n; |
870 | 882 | ||
883 | mutex_lock(&hdev->msg_tx_mutex); | ||
884 | |||
885 | if (hdev->cmd_pending_msg) { | ||
886 | if (hdev->cmd_pending_msg->cb) | ||
887 | hdev->cmd_pending_msg->cb( | ||
888 | hdev->cmd_pending_msg->cb_context, | ||
889 | NULL, -ESHUTDOWN); | ||
890 | kfree(hdev->cmd_pending_msg); | ||
891 | hdev->cmd_pending_msg = NULL; | ||
892 | } | ||
893 | |||
894 | hdev->shutting_down = true; | ||
895 | |||
896 | mutex_unlock(&hdev->msg_tx_mutex); | ||
897 | |||
898 | del_timer_sync(&hdev->cmd_timer); | ||
899 | cancel_work_sync(&hdev->msg_tx_work); | ||
900 | |||
901 | cancel_work_sync(&hdev->msg_rx_work); | ||
902 | |||
903 | nfc_unregister_device(hdev->ndev); | ||
904 | |||
871 | skb_queue_purge(&hdev->rx_hcp_frags); | 905 | skb_queue_purge(&hdev->rx_hcp_frags); |
872 | skb_queue_purge(&hdev->msg_rx_queue); | 906 | skb_queue_purge(&hdev->msg_rx_queue); |
873 | 907 | ||
@@ -876,13 +910,6 @@ void nfc_hci_unregister_device(struct nfc_hci_dev *hdev) | |||
876 | skb_queue_purge(&msg->msg_frags); | 910 | skb_queue_purge(&msg->msg_frags); |
877 | kfree(msg); | 911 | kfree(msg); |
878 | } | 912 | } |
879 | |||
880 | del_timer_sync(&hdev->cmd_timer); | ||
881 | |||
882 | nfc_unregister_device(hdev->ndev); | ||
883 | |||
884 | cancel_work_sync(&hdev->msg_tx_work); | ||
885 | cancel_work_sync(&hdev->msg_rx_work); | ||
886 | } | 913 | } |
887 | EXPORT_SYMBOL(nfc_hci_unregister_device); | 914 | EXPORT_SYMBOL(nfc_hci_unregister_device); |
888 | 915 | ||
diff --git a/net/nfc/hci/hcp.c b/net/nfc/hci/hcp.c index bc308a7ca609..b6b4109f2343 100644 --- a/net/nfc/hci/hcp.c +++ b/net/nfc/hci/hcp.c | |||
@@ -105,6 +105,13 @@ int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe, | |||
105 | } | 105 | } |
106 | 106 | ||
107 | mutex_lock(&hdev->msg_tx_mutex); | 107 | mutex_lock(&hdev->msg_tx_mutex); |
108 | |||
109 | if (hdev->shutting_down) { | ||
110 | err = -ESHUTDOWN; | ||
111 | mutex_unlock(&hdev->msg_tx_mutex); | ||
112 | goto out_skb_err; | ||
113 | } | ||
114 | |||
108 | list_add_tail(&cmd->msg_l, &hdev->msg_tx_queue); | 115 | list_add_tail(&cmd->msg_l, &hdev->msg_tx_queue); |
109 | mutex_unlock(&hdev->msg_tx_mutex); | 116 | mutex_unlock(&hdev->msg_tx_mutex); |
110 | 117 | ||
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index df24be48d4da..c6bc3bd95052 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -304,6 +304,8 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) | |||
304 | 304 | ||
305 | skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); | 305 | skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); |
306 | 306 | ||
307 | __net_timestamp(skb); | ||
308 | |||
307 | nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX); | 309 | nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX); |
308 | 310 | ||
309 | return nfc_data_exchange(dev, local->target_idx, skb, | 311 | return nfc_data_exchange(dev, local->target_idx, skb, |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index ec43914c92a9..85bc75c38dea 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -54,7 +54,6 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock) | |||
54 | 54 | ||
55 | skb_queue_purge(&sock->tx_queue); | 55 | skb_queue_purge(&sock->tx_queue); |
56 | skb_queue_purge(&sock->tx_pending_queue); | 56 | skb_queue_purge(&sock->tx_pending_queue); |
57 | skb_queue_purge(&sock->tx_backlog_queue); | ||
58 | 57 | ||
59 | if (local == NULL) | 58 | if (local == NULL) |
60 | return; | 59 | return; |
@@ -668,6 +667,8 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
668 | if (ptype == LLCP_PDU_I) | 667 | if (ptype == LLCP_PDU_I) |
669 | copy_skb = skb_copy(skb, GFP_ATOMIC); | 668 | copy_skb = skb_copy(skb, GFP_ATOMIC); |
670 | 669 | ||
670 | __net_timestamp(skb); | ||
671 | |||
671 | nfc_llcp_send_to_raw_sock(local, skb, | 672 | nfc_llcp_send_to_raw_sock(local, skb, |
672 | NFC_LLCP_DIRECTION_TX); | 673 | NFC_LLCP_DIRECTION_TX); |
673 | 674 | ||
@@ -781,9 +782,15 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local, | |||
781 | 782 | ||
782 | /* There is no sequence with UI frames */ | 783 | /* There is no sequence with UI frames */ |
783 | skb_pull(skb, LLCP_HEADER_SIZE); | 784 | skb_pull(skb, LLCP_HEADER_SIZE); |
784 | if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { | 785 | if (!sock_queue_rcv_skb(&llcp_sock->sk, skb)) { |
785 | pr_err("receive queue is full\n"); | 786 | /* |
786 | skb_queue_head(&llcp_sock->tx_backlog_queue, skb); | 787 | * UI frames will be freed from the socket layer, so we |
788 | * need to keep them alive until someone receives them. | ||
789 | */ | ||
790 | skb_get(skb); | ||
791 | } else { | ||
792 | pr_err("Receive queue is full\n"); | ||
793 | kfree_skb(skb); | ||
787 | } | 794 | } |
788 | 795 | ||
789 | nfc_llcp_sock_put(llcp_sock); | 796 | nfc_llcp_sock_put(llcp_sock); |
@@ -976,9 +983,15 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
976 | pr_err("Received out of sequence I PDU\n"); | 983 | pr_err("Received out of sequence I PDU\n"); |
977 | 984 | ||
978 | skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE); | 985 | skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE); |
979 | if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { | 986 | if (!sock_queue_rcv_skb(&llcp_sock->sk, skb)) { |
980 | pr_err("receive queue is full\n"); | 987 | /* |
981 | skb_queue_head(&llcp_sock->tx_backlog_queue, skb); | 988 | * I frames will be freed from the socket layer, so we |
989 | * need to keep them alive until someone receives them. | ||
990 | */ | ||
991 | skb_get(skb); | ||
992 | } else { | ||
993 | pr_err("Receive queue is full\n"); | ||
994 | kfree_skb(skb); | ||
982 | } | 995 | } |
983 | } | 996 | } |
984 | 997 | ||
@@ -1245,6 +1258,8 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1245 | print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, | 1258 | print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, |
1246 | 16, 1, skb->data, skb->len, true); | 1259 | 16, 1, skb->data, skb->len, true); |
1247 | 1260 | ||
1261 | __net_timestamp(skb); | ||
1262 | |||
1248 | nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX); | 1263 | nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX); |
1249 | 1264 | ||
1250 | switch (ptype) { | 1265 | switch (ptype) { |
@@ -1296,6 +1311,13 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1296 | local->rx_pending = NULL; | 1311 | local->rx_pending = NULL; |
1297 | } | 1312 | } |
1298 | 1313 | ||
1314 | static void __nfc_llcp_recv(struct nfc_llcp_local *local, struct sk_buff *skb) | ||
1315 | { | ||
1316 | local->rx_pending = skb; | ||
1317 | del_timer(&local->link_timer); | ||
1318 | schedule_work(&local->rx_work); | ||
1319 | } | ||
1320 | |||
1299 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | 1321 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) |
1300 | { | 1322 | { |
1301 | struct nfc_llcp_local *local = (struct nfc_llcp_local *) data; | 1323 | struct nfc_llcp_local *local = (struct nfc_llcp_local *) data; |
@@ -1306,9 +1328,7 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | |||
1306 | return; | 1328 | return; |
1307 | } | 1329 | } |
1308 | 1330 | ||
1309 | local->rx_pending = skb_get(skb); | 1331 | __nfc_llcp_recv(local, skb); |
1310 | del_timer(&local->link_timer); | ||
1311 | schedule_work(&local->rx_work); | ||
1312 | } | 1332 | } |
1313 | 1333 | ||
1314 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) | 1334 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) |
@@ -1319,9 +1339,7 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) | |||
1319 | if (local == NULL) | 1339 | if (local == NULL) |
1320 | return -ENODEV; | 1340 | return -ENODEV; |
1321 | 1341 | ||
1322 | local->rx_pending = skb_get(skb); | 1342 | __nfc_llcp_recv(local, skb); |
1323 | del_timer(&local->link_timer); | ||
1324 | schedule_work(&local->rx_work); | ||
1325 | 1343 | ||
1326 | return 0; | 1344 | return 0; |
1327 | } | 1345 | } |
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index 0d62366f8cc3..0eae5c509504 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -121,7 +121,6 @@ struct nfc_llcp_sock { | |||
121 | 121 | ||
122 | struct sk_buff_head tx_queue; | 122 | struct sk_buff_head tx_queue; |
123 | struct sk_buff_head tx_pending_queue; | 123 | struct sk_buff_head tx_pending_queue; |
124 | struct sk_buff_head tx_backlog_queue; | ||
125 | 124 | ||
126 | struct list_head accept_queue; | 125 | struct list_head accept_queue; |
127 | struct sock *parent; | 126 | struct sock *parent; |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index fea22eb41b82..5332751943a9 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -672,25 +672,27 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
672 | copied = min_t(unsigned int, rlen, len); | 672 | copied = min_t(unsigned int, rlen, len); |
673 | 673 | ||
674 | cskb = skb; | 674 | cskb = skb; |
675 | if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) { | 675 | if (skb_copy_datagram_iovec(cskb, 0, msg->msg_iov, copied)) { |
676 | if (!(flags & MSG_PEEK)) | 676 | if (!(flags & MSG_PEEK)) |
677 | skb_queue_head(&sk->sk_receive_queue, skb); | 677 | skb_queue_head(&sk->sk_receive_queue, skb); |
678 | return -EFAULT; | 678 | return -EFAULT; |
679 | } | 679 | } |
680 | 680 | ||
681 | sock_recv_timestamp(msg, sk, skb); | ||
682 | |||
681 | if (sk->sk_type == SOCK_DGRAM && msg->msg_name) { | 683 | if (sk->sk_type == SOCK_DGRAM && msg->msg_name) { |
682 | struct nfc_llcp_ui_cb *ui_cb = nfc_llcp_ui_skb_cb(skb); | 684 | struct nfc_llcp_ui_cb *ui_cb = nfc_llcp_ui_skb_cb(skb); |
683 | struct sockaddr_nfc_llcp sockaddr; | 685 | struct sockaddr_nfc_llcp *sockaddr = |
686 | (struct sockaddr_nfc_llcp *) msg->msg_name; | ||
684 | 687 | ||
685 | pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); | 688 | msg->msg_namelen = sizeof(struct sockaddr_nfc_llcp); |
686 | 689 | ||
687 | sockaddr.sa_family = AF_NFC; | 690 | pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); |
688 | sockaddr.nfc_protocol = NFC_PROTO_NFC_DEP; | ||
689 | sockaddr.dsap = ui_cb->dsap; | ||
690 | sockaddr.ssap = ui_cb->ssap; | ||
691 | 691 | ||
692 | memcpy(msg->msg_name, &sockaddr, sizeof(sockaddr)); | 692 | sockaddr->sa_family = AF_NFC; |
693 | msg->msg_namelen = sizeof(sockaddr); | 693 | sockaddr->nfc_protocol = NFC_PROTO_NFC_DEP; |
694 | sockaddr->dsap = ui_cb->dsap; | ||
695 | sockaddr->ssap = ui_cb->ssap; | ||
694 | } | 696 | } |
695 | 697 | ||
696 | /* Mark read part of skb as used */ | 698 | /* Mark read part of skb as used */ |
@@ -806,7 +808,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
806 | llcp_sock->reserved_ssap = LLCP_SAP_MAX; | 808 | llcp_sock->reserved_ssap = LLCP_SAP_MAX; |
807 | skb_queue_head_init(&llcp_sock->tx_queue); | 809 | skb_queue_head_init(&llcp_sock->tx_queue); |
808 | skb_queue_head_init(&llcp_sock->tx_pending_queue); | 810 | skb_queue_head_init(&llcp_sock->tx_pending_queue); |
809 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); | ||
810 | INIT_LIST_HEAD(&llcp_sock->accept_queue); | 811 | INIT_LIST_HEAD(&llcp_sock->accept_queue); |
811 | 812 | ||
812 | if (sock != NULL) | 813 | if (sock != NULL) |
@@ -821,7 +822,6 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | |||
821 | 822 | ||
822 | skb_queue_purge(&sock->tx_queue); | 823 | skb_queue_purge(&sock->tx_queue); |
823 | skb_queue_purge(&sock->tx_pending_queue); | 824 | skb_queue_purge(&sock->tx_pending_queue); |
824 | skb_queue_purge(&sock->tx_backlog_queue); | ||
825 | 825 | ||
826 | list_del_init(&sock->accept_queue); | 826 | list_del_init(&sock->accept_queue); |
827 | 827 | ||
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 5f98dc1bf039..48ada0ec749e 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -658,6 +658,7 @@ static struct nfc_ops nci_nfc_ops = { | |||
658 | */ | 658 | */ |
659 | struct nci_dev *nci_allocate_device(struct nci_ops *ops, | 659 | struct nci_dev *nci_allocate_device(struct nci_ops *ops, |
660 | __u32 supported_protocols, | 660 | __u32 supported_protocols, |
661 | __u32 supported_se, | ||
661 | int tx_headroom, int tx_tailroom) | 662 | int tx_headroom, int tx_tailroom) |
662 | { | 663 | { |
663 | struct nci_dev *ndev; | 664 | struct nci_dev *ndev; |
@@ -680,6 +681,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, | |||
680 | 681 | ||
681 | ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, | 682 | ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, |
682 | supported_protocols, | 683 | supported_protocols, |
684 | supported_se, | ||
683 | tx_headroom + NCI_DATA_HDR_SIZE, | 685 | tx_headroom + NCI_DATA_HDR_SIZE, |
684 | tx_tailroom); | 686 | tx_tailroom); |
685 | if (!ndev->nfc_dev) | 687 | if (!ndev->nfc_dev) |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 3568ae16786d..504b883439f1 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -366,6 +366,7 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, | |||
366 | if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || | 366 | if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || |
367 | nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || | 367 | nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || |
368 | nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || | 368 | nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || |
369 | nla_put_u32(msg, NFC_ATTR_SE, dev->supported_se) || | ||
369 | nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up) || | 370 | nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up) || |
370 | nla_put_u8(msg, NFC_ATTR_RF_MODE, dev->rf_mode)) | 371 | nla_put_u8(msg, NFC_ATTR_RF_MODE, dev->rf_mode)) |
371 | goto nla_put_failure; | 372 | goto nla_put_failure; |
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index 324e8d851dc4..a4a14e8f55cc 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c | |||
@@ -46,3 +46,65 @@ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | |||
46 | 46 | ||
47 | return err; | 47 | return err; |
48 | } | 48 | } |
49 | |||
50 | void cfg80211_ch_switch_notify(struct net_device *dev, | ||
51 | struct cfg80211_chan_def *chandef) | ||
52 | { | ||
53 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
54 | struct wiphy *wiphy = wdev->wiphy; | ||
55 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
56 | |||
57 | trace_cfg80211_ch_switch_notify(dev, chandef); | ||
58 | |||
59 | wdev_lock(wdev); | ||
60 | |||
61 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
62 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) | ||
63 | goto out; | ||
64 | |||
65 | wdev->channel = chandef->chan; | ||
66 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); | ||
67 | out: | ||
68 | wdev_unlock(wdev); | ||
69 | return; | ||
70 | } | ||
71 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); | ||
72 | |||
73 | bool cfg80211_rx_spurious_frame(struct net_device *dev, | ||
74 | const u8 *addr, gfp_t gfp) | ||
75 | { | ||
76 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
77 | bool ret; | ||
78 | |||
79 | trace_cfg80211_rx_spurious_frame(dev, addr); | ||
80 | |||
81 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
82 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) { | ||
83 | trace_cfg80211_return_bool(false); | ||
84 | return false; | ||
85 | } | ||
86 | ret = nl80211_unexpected_frame(dev, addr, gfp); | ||
87 | trace_cfg80211_return_bool(ret); | ||
88 | return ret; | ||
89 | } | ||
90 | EXPORT_SYMBOL(cfg80211_rx_spurious_frame); | ||
91 | |||
92 | bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, | ||
93 | const u8 *addr, gfp_t gfp) | ||
94 | { | ||
95 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
96 | bool ret; | ||
97 | |||
98 | trace_cfg80211_rx_unexpected_4addr_frame(dev, addr); | ||
99 | |||
100 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
101 | wdev->iftype != NL80211_IFTYPE_P2P_GO && | ||
102 | wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { | ||
103 | trace_cfg80211_return_bool(false); | ||
104 | return false; | ||
105 | } | ||
106 | ret = nl80211_unexpected_4addr_frame(dev, addr, gfp); | ||
107 | trace_cfg80211_return_bool(ret); | ||
108 | return ret; | ||
109 | } | ||
110 | EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame); | ||
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index a7990bb16529..396373f3ec26 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -76,6 +76,10 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) | |||
76 | return false; | 76 | return false; |
77 | if (!chandef->center_freq2) | 77 | if (!chandef->center_freq2) |
78 | return false; | 78 | return false; |
79 | /* adjacent is not allowed -- that's a 160 MHz channel */ | ||
80 | if (chandef->center_freq1 - chandef->center_freq2 == 80 || | ||
81 | chandef->center_freq2 - chandef->center_freq1 == 80) | ||
82 | return false; | ||
79 | break; | 83 | break; |
80 | case NL80211_CHAN_WIDTH_80: | 84 | case NL80211_CHAN_WIDTH_80: |
81 | if (chandef->center_freq1 != control_freq + 30 && | 85 | if (chandef->center_freq1 != control_freq + 30 && |
diff --git a/net/wireless/core.c b/net/wireless/core.c index b677eab55b68..9245729694d2 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -57,9 +57,6 @@ struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) | |||
57 | { | 57 | { |
58 | struct cfg80211_registered_device *result = NULL, *rdev; | 58 | struct cfg80211_registered_device *result = NULL, *rdev; |
59 | 59 | ||
60 | if (!wiphy_idx_valid(wiphy_idx)) | ||
61 | return NULL; | ||
62 | |||
63 | assert_cfg80211_lock(); | 60 | assert_cfg80211_lock(); |
64 | 61 | ||
65 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | 62 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
@@ -74,10 +71,8 @@ struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) | |||
74 | 71 | ||
75 | int get_wiphy_idx(struct wiphy *wiphy) | 72 | int get_wiphy_idx(struct wiphy *wiphy) |
76 | { | 73 | { |
77 | struct cfg80211_registered_device *rdev; | 74 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
78 | if (!wiphy) | 75 | |
79 | return WIPHY_IDX_STALE; | ||
80 | rdev = wiphy_to_dev(wiphy); | ||
81 | return rdev->wiphy_idx; | 76 | return rdev->wiphy_idx; |
82 | } | 77 | } |
83 | 78 | ||
@@ -86,9 +81,6 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) | |||
86 | { | 81 | { |
87 | struct cfg80211_registered_device *rdev; | 82 | struct cfg80211_registered_device *rdev; |
88 | 83 | ||
89 | if (!wiphy_idx_valid(wiphy_idx)) | ||
90 | return NULL; | ||
91 | |||
92 | assert_cfg80211_lock(); | 84 | assert_cfg80211_lock(); |
93 | 85 | ||
94 | rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx); | 86 | rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx); |
@@ -309,7 +301,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
309 | 301 | ||
310 | rdev->wiphy_idx = wiphy_counter++; | 302 | rdev->wiphy_idx = wiphy_counter++; |
311 | 303 | ||
312 | if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) { | 304 | if (unlikely(rdev->wiphy_idx < 0)) { |
313 | wiphy_counter--; | 305 | wiphy_counter--; |
314 | mutex_unlock(&cfg80211_mutex); | 306 | mutex_unlock(&cfg80211_mutex); |
315 | /* ugh, wrapped! */ | 307 | /* ugh, wrapped! */ |
@@ -390,8 +382,11 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) | |||
390 | 382 | ||
391 | c = &wiphy->iface_combinations[i]; | 383 | c = &wiphy->iface_combinations[i]; |
392 | 384 | ||
393 | /* Combinations with just one interface aren't real */ | 385 | /* |
394 | if (WARN_ON(c->max_interfaces < 2)) | 386 | * Combinations with just one interface aren't real, |
387 | * however we make an exception for DFS. | ||
388 | */ | ||
389 | if (WARN_ON((c->max_interfaces < 2) && !c->radar_detect_widths)) | ||
395 | return -EINVAL; | 390 | return -EINVAL; |
396 | 391 | ||
397 | /* Need at least one channel */ | 392 | /* Need at least one channel */ |
@@ -406,6 +401,11 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) | |||
406 | CFG80211_MAX_NUM_DIFFERENT_CHANNELS)) | 401 | CFG80211_MAX_NUM_DIFFERENT_CHANNELS)) |
407 | return -EINVAL; | 402 | return -EINVAL; |
408 | 403 | ||
404 | /* DFS only works on one channel. */ | ||
405 | if (WARN_ON(c->radar_detect_widths && | ||
406 | (c->num_different_channels > 1))) | ||
407 | return -EINVAL; | ||
408 | |||
409 | if (WARN_ON(!c->n_limits)) | 409 | if (WARN_ON(!c->n_limits)) |
410 | return -EINVAL; | 410 | return -EINVAL; |
411 | 411 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index 3563097169cb..8396f7671c8d 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -18,6 +18,9 @@ | |||
18 | #include <net/cfg80211.h> | 18 | #include <net/cfg80211.h> |
19 | #include "reg.h" | 19 | #include "reg.h" |
20 | 20 | ||
21 | |||
22 | #define WIPHY_IDX_INVALID -1 | ||
23 | |||
21 | struct cfg80211_registered_device { | 24 | struct cfg80211_registered_device { |
22 | const struct cfg80211_ops *ops; | 25 | const struct cfg80211_ops *ops; |
23 | struct list_head list; | 26 | struct list_head list; |
@@ -86,7 +89,7 @@ struct cfg80211_registered_device { | |||
86 | 89 | ||
87 | /* must be last because of the way we do wiphy_priv(), | 90 | /* must be last because of the way we do wiphy_priv(), |
88 | * and it should at least be aligned to NETDEV_ALIGN */ | 91 | * and it should at least be aligned to NETDEV_ALIGN */ |
89 | struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); | 92 | struct wiphy wiphy __aligned(NETDEV_ALIGN); |
90 | }; | 93 | }; |
91 | 94 | ||
92 | static inline | 95 | static inline |
@@ -96,13 +99,6 @@ struct cfg80211_registered_device *wiphy_to_dev(struct wiphy *wiphy) | |||
96 | return container_of(wiphy, struct cfg80211_registered_device, wiphy); | 99 | return container_of(wiphy, struct cfg80211_registered_device, wiphy); |
97 | } | 100 | } |
98 | 101 | ||
99 | /* Note 0 is valid, hence phy0 */ | ||
100 | static inline | ||
101 | bool wiphy_idx_valid(int wiphy_idx) | ||
102 | { | ||
103 | return wiphy_idx >= 0; | ||
104 | } | ||
105 | |||
106 | static inline void | 102 | static inline void |
107 | cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) | 103 | cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) |
108 | { | 104 | { |
@@ -126,12 +122,6 @@ static inline void assert_cfg80211_lock(void) | |||
126 | lockdep_assert_held(&cfg80211_mutex); | 122 | lockdep_assert_held(&cfg80211_mutex); |
127 | } | 123 | } |
128 | 124 | ||
129 | /* | ||
130 | * You can use this to mark a wiphy_idx as not having an associated wiphy. | ||
131 | * It guarantees cfg80211_rdev_by_wiphy_idx(wiphy_idx) will return NULL | ||
132 | */ | ||
133 | #define WIPHY_IDX_STALE -1 | ||
134 | |||
135 | struct cfg80211_internal_bss { | 125 | struct cfg80211_internal_bss { |
136 | struct list_head list; | 126 | struct list_head list; |
137 | struct rb_node rbn; | 127 | struct rb_node rbn; |
@@ -435,7 +425,8 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
435 | struct wireless_dev *wdev, | 425 | struct wireless_dev *wdev, |
436 | enum nl80211_iftype iftype, | 426 | enum nl80211_iftype iftype, |
437 | struct ieee80211_channel *chan, | 427 | struct ieee80211_channel *chan, |
438 | enum cfg80211_chan_mode chanmode); | 428 | enum cfg80211_chan_mode chanmode, |
429 | u8 radar_detect); | ||
439 | 430 | ||
440 | static inline int | 431 | static inline int |
441 | cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | 432 | cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, |
@@ -443,7 +434,7 @@ cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
443 | enum nl80211_iftype iftype) | 434 | enum nl80211_iftype iftype) |
444 | { | 435 | { |
445 | return cfg80211_can_use_iftype_chan(rdev, wdev, iftype, NULL, | 436 | return cfg80211_can_use_iftype_chan(rdev, wdev, iftype, NULL, |
446 | CHAN_MODE_UNDEFINED); | 437 | CHAN_MODE_UNDEFINED, 0); |
447 | } | 438 | } |
448 | 439 | ||
449 | static inline int | 440 | static inline int |
@@ -460,7 +451,7 @@ cfg80211_can_use_chan(struct cfg80211_registered_device *rdev, | |||
460 | enum cfg80211_chan_mode chanmode) | 451 | enum cfg80211_chan_mode chanmode) |
461 | { | 452 | { |
462 | return cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | 453 | return cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, |
463 | chan, chanmode); | 454 | chan, chanmode, 0); |
464 | } | 455 | } |
465 | 456 | ||
466 | void | 457 | void |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index f9d6ce5cfabb..55957a284f6c 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -44,6 +44,10 @@ | |||
44 | 44 | ||
45 | #define MESH_SYNC_NEIGHBOR_OFFSET_MAX 50 | 45 | #define MESH_SYNC_NEIGHBOR_OFFSET_MAX 50 |
46 | 46 | ||
47 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units (=TUs) */ | ||
48 | #define MESH_DEFAULT_DTIM_PERIOD 2 | ||
49 | #define MESH_DEFAULT_AWAKE_WINDOW 10 /* in 1024 us units (=TUs) */ | ||
50 | |||
47 | const struct mesh_config default_mesh_config = { | 51 | const struct mesh_config default_mesh_config = { |
48 | .dot11MeshRetryTimeout = MESH_RET_T, | 52 | .dot11MeshRetryTimeout = MESH_RET_T, |
49 | .dot11MeshConfirmTimeout = MESH_CONF_T, | 53 | .dot11MeshConfirmTimeout = MESH_CONF_T, |
@@ -69,6 +73,8 @@ const struct mesh_config default_mesh_config = { | |||
69 | .dot11MeshHWMPactivePathToRootTimeout = MESH_PATH_TO_ROOT_TIMEOUT, | 73 | .dot11MeshHWMPactivePathToRootTimeout = MESH_PATH_TO_ROOT_TIMEOUT, |
70 | .dot11MeshHWMProotInterval = MESH_ROOT_INTERVAL, | 74 | .dot11MeshHWMProotInterval = MESH_ROOT_INTERVAL, |
71 | .dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL, | 75 | .dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL, |
76 | .power_mode = NL80211_MESH_POWER_ACTIVE, | ||
77 | .dot11MeshAwakeWindowDuration = MESH_DEFAULT_AWAKE_WINDOW, | ||
72 | }; | 78 | }; |
73 | 79 | ||
74 | const struct mesh_setup default_mesh_setup = { | 80 | const struct mesh_setup default_mesh_setup = { |
@@ -79,6 +85,8 @@ const struct mesh_setup default_mesh_setup = { | |||
79 | .ie = NULL, | 85 | .ie = NULL, |
80 | .ie_len = 0, | 86 | .ie_len = 0, |
81 | .is_secure = false, | 87 | .is_secure = false, |
88 | .beacon_interval = MESH_DEFAULT_BEACON_INTERVAL, | ||
89 | .dtim_period = MESH_DEFAULT_DTIM_PERIOD, | ||
82 | }; | 90 | }; |
83 | 91 | ||
84 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | 92 | int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 5e8123ee63fd..461e692cdfec 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -987,65 +987,3 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, | |||
987 | nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp); | 987 | nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp); |
988 | } | 988 | } |
989 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); | 989 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); |
990 | |||
991 | void cfg80211_ch_switch_notify(struct net_device *dev, | ||
992 | struct cfg80211_chan_def *chandef) | ||
993 | { | ||
994 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
995 | struct wiphy *wiphy = wdev->wiphy; | ||
996 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
997 | |||
998 | trace_cfg80211_ch_switch_notify(dev, chandef); | ||
999 | |||
1000 | wdev_lock(wdev); | ||
1001 | |||
1002 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
1003 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) | ||
1004 | goto out; | ||
1005 | |||
1006 | wdev->channel = chandef->chan; | ||
1007 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); | ||
1008 | out: | ||
1009 | wdev_unlock(wdev); | ||
1010 | return; | ||
1011 | } | ||
1012 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); | ||
1013 | |||
1014 | bool cfg80211_rx_spurious_frame(struct net_device *dev, | ||
1015 | const u8 *addr, gfp_t gfp) | ||
1016 | { | ||
1017 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
1018 | bool ret; | ||
1019 | |||
1020 | trace_cfg80211_rx_spurious_frame(dev, addr); | ||
1021 | |||
1022 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
1023 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) { | ||
1024 | trace_cfg80211_return_bool(false); | ||
1025 | return false; | ||
1026 | } | ||
1027 | ret = nl80211_unexpected_frame(dev, addr, gfp); | ||
1028 | trace_cfg80211_return_bool(ret); | ||
1029 | return ret; | ||
1030 | } | ||
1031 | EXPORT_SYMBOL(cfg80211_rx_spurious_frame); | ||
1032 | |||
1033 | bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, | ||
1034 | const u8 *addr, gfp_t gfp) | ||
1035 | { | ||
1036 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
1037 | bool ret; | ||
1038 | |||
1039 | trace_cfg80211_rx_unexpected_4addr_frame(dev, addr); | ||
1040 | |||
1041 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
1042 | wdev->iftype != NL80211_IFTYPE_P2P_GO && | ||
1043 | wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { | ||
1044 | trace_cfg80211_return_bool(false); | ||
1045 | return false; | ||
1046 | } | ||
1047 | ret = nl80211_unexpected_4addr_frame(dev, addr, gfp); | ||
1048 | trace_cfg80211_return_bool(ret); | ||
1049 | return ret; | ||
1050 | } | ||
1051 | EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame); | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f45706adaf34..33de80364c5c 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -856,6 +856,9 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, | |||
856 | nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, | 856 | nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, |
857 | c->max_interfaces)) | 857 | c->max_interfaces)) |
858 | goto nla_put_failure; | 858 | goto nla_put_failure; |
859 | if (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, | ||
860 | c->radar_detect_widths)) | ||
861 | goto nla_put_failure; | ||
859 | 862 | ||
860 | nla_nest_end(msg, nl_combi); | 863 | nla_nest_end(msg, nl_combi); |
861 | } | 864 | } |
@@ -2079,6 +2082,13 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2079 | !(rdev->wiphy.interface_modes & (1 << type))) | 2082 | !(rdev->wiphy.interface_modes & (1 << type))) |
2080 | return -EOPNOTSUPP; | 2083 | return -EOPNOTSUPP; |
2081 | 2084 | ||
2085 | if (type == NL80211_IFTYPE_P2P_DEVICE && info->attrs[NL80211_ATTR_MAC]) { | ||
2086 | nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC], | ||
2087 | ETH_ALEN); | ||
2088 | if (!is_valid_ether_addr(params.macaddr)) | ||
2089 | return -EADDRNOTAVAIL; | ||
2090 | } | ||
2091 | |||
2082 | if (info->attrs[NL80211_ATTR_4ADDR]) { | 2092 | if (info->attrs[NL80211_ATTR_4ADDR]) { |
2083 | params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); | 2093 | params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); |
2084 | err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type); | 2094 | err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type); |
@@ -3001,6 +3011,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | |||
3001 | nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS, | 3011 | nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS, |
3002 | sinfo->beacon_loss_count)) | 3012 | sinfo->beacon_loss_count)) |
3003 | goto nla_put_failure; | 3013 | goto nla_put_failure; |
3014 | if ((sinfo->filled & STATION_INFO_LOCAL_PM) && | ||
3015 | nla_put_u32(msg, NL80211_STA_INFO_LOCAL_PM, | ||
3016 | sinfo->local_pm)) | ||
3017 | goto nla_put_failure; | ||
3018 | if ((sinfo->filled & STATION_INFO_PEER_PM) && | ||
3019 | nla_put_u32(msg, NL80211_STA_INFO_PEER_PM, | ||
3020 | sinfo->peer_pm)) | ||
3021 | goto nla_put_failure; | ||
3022 | if ((sinfo->filled & STATION_INFO_NONPEER_PM) && | ||
3023 | nla_put_u32(msg, NL80211_STA_INFO_NONPEER_PM, | ||
3024 | sinfo->nonpeer_pm)) | ||
3025 | goto nla_put_failure; | ||
3004 | if (sinfo->filled & STATION_INFO_BSS_PARAM) { | 3026 | if (sinfo->filled & STATION_INFO_BSS_PARAM) { |
3005 | bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); | 3027 | bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); |
3006 | if (!bss_param) | 3028 | if (!bss_param) |
@@ -3188,13 +3210,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3188 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); | 3210 | nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); |
3189 | } | 3211 | } |
3190 | 3212 | ||
3191 | if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) | 3213 | if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL] || |
3192 | params.listen_interval = | 3214 | info->attrs[NL80211_ATTR_HT_CAPABILITY]) |
3193 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | 3215 | return -EINVAL; |
3194 | |||
3195 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | ||
3196 | params.ht_capa = | ||
3197 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | ||
3198 | 3216 | ||
3199 | if (!rdev->ops->change_station) | 3217 | if (!rdev->ops->change_station) |
3200 | return -EOPNOTSUPP; | 3218 | return -EOPNOTSUPP; |
@@ -3210,6 +3228,17 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3210 | params.plink_state = | 3228 | params.plink_state = |
3211 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); | 3229 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); |
3212 | 3230 | ||
3231 | if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) { | ||
3232 | enum nl80211_mesh_power_mode pm = nla_get_u32( | ||
3233 | info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]); | ||
3234 | |||
3235 | if (pm <= NL80211_MESH_POWER_UNKNOWN || | ||
3236 | pm > NL80211_MESH_POWER_MAX) | ||
3237 | return -EINVAL; | ||
3238 | |||
3239 | params.local_pm = pm; | ||
3240 | } | ||
3241 | |||
3213 | switch (dev->ieee80211_ptr->iftype) { | 3242 | switch (dev->ieee80211_ptr->iftype) { |
3214 | case NL80211_IFTYPE_AP: | 3243 | case NL80211_IFTYPE_AP: |
3215 | case NL80211_IFTYPE_AP_VLAN: | 3244 | case NL80211_IFTYPE_AP_VLAN: |
@@ -3217,6 +3246,8 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3217 | /* disallow mesh-specific things */ | 3246 | /* disallow mesh-specific things */ |
3218 | if (params.plink_action) | 3247 | if (params.plink_action) |
3219 | return -EINVAL; | 3248 | return -EINVAL; |
3249 | if (params.local_pm) | ||
3250 | return -EINVAL; | ||
3220 | 3251 | ||
3221 | /* TDLS can't be set, ... */ | 3252 | /* TDLS can't be set, ... */ |
3222 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | 3253 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) |
@@ -3231,11 +3262,25 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3231 | /* accept only the listed bits */ | 3262 | /* accept only the listed bits */ |
3232 | if (params.sta_flags_mask & | 3263 | if (params.sta_flags_mask & |
3233 | ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | | 3264 | ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | |
3265 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3266 | BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
3234 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | 3267 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | |
3235 | BIT(NL80211_STA_FLAG_WME) | | 3268 | BIT(NL80211_STA_FLAG_WME) | |
3236 | BIT(NL80211_STA_FLAG_MFP))) | 3269 | BIT(NL80211_STA_FLAG_MFP))) |
3237 | return -EINVAL; | 3270 | return -EINVAL; |
3238 | 3271 | ||
3272 | /* but authenticated/associated only if driver handles it */ | ||
3273 | if (!(rdev->wiphy.features & | ||
3274 | NL80211_FEATURE_FULL_AP_CLIENT_STATE) && | ||
3275 | params.sta_flags_mask & | ||
3276 | (BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3277 | BIT(NL80211_STA_FLAG_ASSOCIATED))) | ||
3278 | return -EINVAL; | ||
3279 | |||
3280 | /* reject other things that can't change */ | ||
3281 | if (params.supported_rates) | ||
3282 | return -EINVAL; | ||
3283 | |||
3239 | /* must be last in here for error handling */ | 3284 | /* must be last in here for error handling */ |
3240 | params.vlan = get_vlan(info, rdev); | 3285 | params.vlan = get_vlan(info, rdev); |
3241 | if (IS_ERR(params.vlan)) | 3286 | if (IS_ERR(params.vlan)) |
@@ -3255,9 +3300,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3255 | /* disallow things sta doesn't support */ | 3300 | /* disallow things sta doesn't support */ |
3256 | if (params.plink_action) | 3301 | if (params.plink_action) |
3257 | return -EINVAL; | 3302 | return -EINVAL; |
3258 | if (params.ht_capa) | 3303 | if (params.local_pm) |
3259 | return -EINVAL; | ||
3260 | if (params.listen_interval >= 0) | ||
3261 | return -EINVAL; | 3304 | return -EINVAL; |
3262 | /* reject any changes other than AUTHORIZED */ | 3305 | /* reject any changes other than AUTHORIZED */ |
3263 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) | 3306 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) |
@@ -3267,9 +3310,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
3267 | /* disallow things mesh doesn't support */ | 3310 | /* disallow things mesh doesn't support */ |
3268 | if (params.vlan) | 3311 | if (params.vlan) |
3269 | return -EINVAL; | 3312 | return -EINVAL; |
3270 | if (params.ht_capa) | 3313 | if (params.supported_rates) |
3271 | return -EINVAL; | ||
3272 | if (params.listen_interval >= 0) | ||
3273 | return -EINVAL; | 3314 | return -EINVAL; |
3274 | /* | 3315 | /* |
3275 | * No special handling for TDLS here -- the userspace | 3316 | * No special handling for TDLS here -- the userspace |
@@ -3393,17 +3434,31 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3393 | /* but don't bother the driver with it */ | 3434 | /* but don't bother the driver with it */ |
3394 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | 3435 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); |
3395 | 3436 | ||
3437 | /* allow authenticated/associated only if driver handles it */ | ||
3438 | if (!(rdev->wiphy.features & | ||
3439 | NL80211_FEATURE_FULL_AP_CLIENT_STATE) && | ||
3440 | params.sta_flags_mask & | ||
3441 | (BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
3442 | BIT(NL80211_STA_FLAG_ASSOCIATED))) | ||
3443 | return -EINVAL; | ||
3444 | |||
3396 | /* must be last in here for error handling */ | 3445 | /* must be last in here for error handling */ |
3397 | params.vlan = get_vlan(info, rdev); | 3446 | params.vlan = get_vlan(info, rdev); |
3398 | if (IS_ERR(params.vlan)) | 3447 | if (IS_ERR(params.vlan)) |
3399 | return PTR_ERR(params.vlan); | 3448 | return PTR_ERR(params.vlan); |
3400 | break; | 3449 | break; |
3401 | case NL80211_IFTYPE_MESH_POINT: | 3450 | case NL80211_IFTYPE_MESH_POINT: |
3451 | /* associated is disallowed */ | ||
3452 | if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) | ||
3453 | return -EINVAL; | ||
3402 | /* TDLS peers cannot be added */ | 3454 | /* TDLS peers cannot be added */ |
3403 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | 3455 | if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) |
3404 | return -EINVAL; | 3456 | return -EINVAL; |
3405 | break; | 3457 | break; |
3406 | case NL80211_IFTYPE_STATION: | 3458 | case NL80211_IFTYPE_STATION: |
3459 | /* associated is disallowed */ | ||
3460 | if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) | ||
3461 | return -EINVAL; | ||
3407 | /* Only TDLS peers can be added */ | 3462 | /* Only TDLS peers can be added */ |
3408 | if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | 3463 | if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) |
3409 | return -EINVAL; | 3464 | return -EINVAL; |
@@ -3787,12 +3842,8 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
3787 | * window between nl80211_init() and regulatory_init(), if that is | 3842 | * window between nl80211_init() and regulatory_init(), if that is |
3788 | * even possible. | 3843 | * even possible. |
3789 | */ | 3844 | */ |
3790 | mutex_lock(&cfg80211_mutex); | 3845 | if (unlikely(!rcu_access_pointer(cfg80211_regdomain))) |
3791 | if (unlikely(!cfg80211_regdomain)) { | ||
3792 | mutex_unlock(&cfg80211_mutex); | ||
3793 | return -EINPROGRESS; | 3846 | return -EINPROGRESS; |
3794 | } | ||
3795 | mutex_unlock(&cfg80211_mutex); | ||
3796 | 3847 | ||
3797 | if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) | 3848 | if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) |
3798 | return -EINVAL; | 3849 | return -EINVAL; |
@@ -3908,7 +3959,11 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, | |||
3908 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL, | 3959 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL, |
3909 | cur_params.dot11MeshHWMProotInterval) || | 3960 | cur_params.dot11MeshHWMProotInterval) || |
3910 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, | 3961 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, |
3911 | cur_params.dot11MeshHWMPconfirmationInterval)) | 3962 | cur_params.dot11MeshHWMPconfirmationInterval) || |
3963 | nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE, | ||
3964 | cur_params.power_mode) || | ||
3965 | nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW, | ||
3966 | cur_params.dot11MeshAwakeWindowDuration)) | ||
3912 | goto nla_put_failure; | 3967 | goto nla_put_failure; |
3913 | nla_nest_end(msg, pinfoattr); | 3968 | nla_nest_end(msg, pinfoattr); |
3914 | genlmsg_end(msg, hdr); | 3969 | genlmsg_end(msg, hdr); |
@@ -3947,6 +4002,8 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A | |||
3947 | [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 }, | 4002 | [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 }, |
3948 | [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 }, | 4003 | [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 }, |
3949 | [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 }, | 4004 | [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 }, |
4005 | [NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 }, | ||
4006 | [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 }, | ||
3950 | }; | 4007 | }; |
3951 | 4008 | ||
3952 | static const struct nla_policy | 4009 | static const struct nla_policy |
@@ -3967,13 +4024,15 @@ static int nl80211_parse_mesh_config(struct genl_info *info, | |||
3967 | struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1]; | 4024 | struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1]; |
3968 | u32 mask = 0; | 4025 | u32 mask = 0; |
3969 | 4026 | ||
3970 | #define FILL_IN_MESH_PARAM_IF_SET(table, cfg, param, mask, attr_num, nla_fn) \ | 4027 | #define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \ |
3971 | do {\ | 4028 | do { \ |
3972 | if (table[attr_num]) {\ | 4029 | if (tb[attr]) { \ |
3973 | cfg->param = nla_fn(table[attr_num]); \ | 4030 | if (fn(tb[attr]) < min || fn(tb[attr]) > max) \ |
3974 | mask |= (1 << (attr_num - 1)); \ | 4031 | return -EINVAL; \ |
3975 | } \ | 4032 | cfg->param = fn(tb[attr]); \ |
3976 | } while (0);\ | 4033 | mask |= (1 << (attr - 1)); \ |
4034 | } \ | ||
4035 | } while (0) | ||
3977 | 4036 | ||
3978 | 4037 | ||
3979 | if (!info->attrs[NL80211_ATTR_MESH_CONFIG]) | 4038 | if (!info->attrs[NL80211_ATTR_MESH_CONFIG]) |
@@ -3988,83 +4047,98 @@ do {\ | |||
3988 | BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32); | 4047 | BUILD_BUG_ON(NL80211_MESHCONF_ATTR_MAX > 32); |
3989 | 4048 | ||
3990 | /* Fill in the params struct */ | 4049 | /* Fill in the params struct */ |
3991 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, | 4050 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255, |
3992 | mask, NL80211_MESHCONF_RETRY_TIMEOUT, | 4051 | mask, NL80211_MESHCONF_RETRY_TIMEOUT, |
3993 | nla_get_u16); | 4052 | nla_get_u16); |
3994 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, | 4053 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255, |
3995 | mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, | 4054 | mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, |
3996 | nla_get_u16); | 4055 | nla_get_u16); |
3997 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, | 4056 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255, |
3998 | mask, NL80211_MESHCONF_HOLDING_TIMEOUT, | 4057 | mask, NL80211_MESHCONF_HOLDING_TIMEOUT, |
3999 | nla_get_u16); | 4058 | nla_get_u16); |
4000 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, | 4059 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255, |
4001 | mask, NL80211_MESHCONF_MAX_PEER_LINKS, | 4060 | mask, NL80211_MESHCONF_MAX_PEER_LINKS, |
4002 | nla_get_u16); | 4061 | nla_get_u16); |
4003 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, | 4062 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16, |
4004 | mask, NL80211_MESHCONF_MAX_RETRIES, | 4063 | mask, NL80211_MESHCONF_MAX_RETRIES, |
4005 | nla_get_u8); | 4064 | nla_get_u8); |
4006 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, | 4065 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255, |
4007 | mask, NL80211_MESHCONF_TTL, nla_get_u8); | 4066 | mask, NL80211_MESHCONF_TTL, nla_get_u8); |
4008 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, | 4067 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255, |
4009 | mask, NL80211_MESHCONF_ELEMENT_TTL, | 4068 | mask, NL80211_MESHCONF_ELEMENT_TTL, |
4010 | nla_get_u8); | 4069 | nla_get_u8); |
4011 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, | 4070 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 0, 1, |
4012 | mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, | 4071 | mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, |
4013 | nla_get_u8); | 4072 | nla_get_u8); |
4014 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor, mask, | 4073 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor, |
4074 | 1, 255, mask, | ||
4015 | NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, | 4075 | NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, |
4016 | nla_get_u32); | 4076 | nla_get_u32); |
4017 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, | 4077 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255, |
4018 | mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | 4078 | mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, |
4019 | nla_get_u8); | 4079 | nla_get_u8); |
4020 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, | 4080 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535, |
4021 | mask, NL80211_MESHCONF_PATH_REFRESH_TIME, | 4081 | mask, NL80211_MESHCONF_PATH_REFRESH_TIME, |
4022 | nla_get_u32); | 4082 | nla_get_u32); |
4023 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, | 4083 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535, |
4024 | mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, | 4084 | mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, |
4025 | nla_get_u16); | 4085 | nla_get_u16); |
4026 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout, mask, | 4086 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout, |
4087 | 1, 65535, mask, | ||
4027 | NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, | 4088 | NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, |
4028 | nla_get_u32); | 4089 | nla_get_u32); |
4029 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, | 4090 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, |
4030 | mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, | 4091 | 1, 65535, mask, |
4092 | NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, | ||
4031 | nla_get_u16); | 4093 | nla_get_u16); |
4032 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, | 4094 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, |
4033 | mask, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, | 4095 | 1, 65535, mask, |
4096 | NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, | ||
4034 | nla_get_u16); | 4097 | nla_get_u16); |
4035 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, | 4098 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, |
4036 | dot11MeshHWMPnetDiameterTraversalTime, mask, | 4099 | dot11MeshHWMPnetDiameterTraversalTime, |
4100 | 1, 65535, mask, | ||
4037 | NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, | 4101 | NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, |
4038 | nla_get_u16); | 4102 | nla_get_u16); |
4039 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, mask, | 4103 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4, |
4040 | NL80211_MESHCONF_HWMP_ROOTMODE, nla_get_u8); | 4104 | mask, NL80211_MESHCONF_HWMP_ROOTMODE, |
4041 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, mask, | 4105 | nla_get_u8); |
4042 | NL80211_MESHCONF_HWMP_RANN_INTERVAL, | 4106 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535, |
4107 | mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL, | ||
4043 | nla_get_u16); | 4108 | nla_get_u16); |
4044 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, | 4109 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, |
4045 | dot11MeshGateAnnouncementProtocol, mask, | 4110 | dot11MeshGateAnnouncementProtocol, 0, 1, |
4046 | NL80211_MESHCONF_GATE_ANNOUNCEMENTS, | 4111 | mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, |
4047 | nla_get_u8); | 4112 | nla_get_u8); |
4048 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, | 4113 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1, |
4049 | mask, NL80211_MESHCONF_FORWARDING, | 4114 | mask, NL80211_MESHCONF_FORWARDING, |
4050 | nla_get_u8); | 4115 | nla_get_u8); |
4051 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, | 4116 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, 1, 255, |
4052 | mask, NL80211_MESHCONF_RSSI_THRESHOLD, | 4117 | mask, NL80211_MESHCONF_RSSI_THRESHOLD, |
4053 | nla_get_u32); | 4118 | nla_get_u32); |
4054 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, | 4119 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16, |
4055 | mask, NL80211_MESHCONF_HT_OPMODE, | 4120 | mask, NL80211_MESHCONF_HT_OPMODE, |
4056 | nla_get_u16); | 4121 | nla_get_u16); |
4057 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout, | 4122 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout, |
4058 | mask, | 4123 | 1, 65535, mask, |
4059 | NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, | 4124 | NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, |
4060 | nla_get_u32); | 4125 | nla_get_u32); |
4061 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, | 4126 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, 1, 65535, |
4062 | mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL, | 4127 | mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL, |
4063 | nla_get_u16); | 4128 | nla_get_u16); |
4064 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, | 4129 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, |
4065 | dot11MeshHWMPconfirmationInterval, mask, | 4130 | dot11MeshHWMPconfirmationInterval, |
4131 | 1, 65535, mask, | ||
4066 | NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, | 4132 | NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, |
4067 | nla_get_u16); | 4133 | nla_get_u16); |
4134 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, | ||
4135 | NL80211_MESH_POWER_ACTIVE, | ||
4136 | NL80211_MESH_POWER_MAX, | ||
4137 | mask, NL80211_MESHCONF_POWER_MODE, | ||
4138 | nla_get_u32); | ||
4139 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, | ||
4140 | 0, 65535, mask, | ||
4141 | NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16); | ||
4068 | if (mask_out) | 4142 | if (mask_out) |
4069 | *mask_out = mask; | 4143 | *mask_out = mask; |
4070 | 4144 | ||
@@ -4152,6 +4226,7 @@ static int nl80211_update_mesh_config(struct sk_buff *skb, | |||
4152 | 4226 | ||
4153 | static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | 4227 | static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) |
4154 | { | 4228 | { |
4229 | const struct ieee80211_regdomain *regdom; | ||
4155 | struct sk_buff *msg; | 4230 | struct sk_buff *msg; |
4156 | void *hdr = NULL; | 4231 | void *hdr = NULL; |
4157 | struct nlattr *nl_reg_rules; | 4232 | struct nlattr *nl_reg_rules; |
@@ -4174,35 +4249,36 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
4174 | if (!hdr) | 4249 | if (!hdr) |
4175 | goto put_failure; | 4250 | goto put_failure; |
4176 | 4251 | ||
4177 | if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, | ||
4178 | cfg80211_regdomain->alpha2) || | ||
4179 | (cfg80211_regdomain->dfs_region && | ||
4180 | nla_put_u8(msg, NL80211_ATTR_DFS_REGION, | ||
4181 | cfg80211_regdomain->dfs_region))) | ||
4182 | goto nla_put_failure; | ||
4183 | |||
4184 | if (reg_last_request_cell_base() && | 4252 | if (reg_last_request_cell_base() && |
4185 | nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE, | 4253 | nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE, |
4186 | NL80211_USER_REG_HINT_CELL_BASE)) | 4254 | NL80211_USER_REG_HINT_CELL_BASE)) |
4187 | goto nla_put_failure; | 4255 | goto nla_put_failure; |
4188 | 4256 | ||
4257 | rcu_read_lock(); | ||
4258 | regdom = rcu_dereference(cfg80211_regdomain); | ||
4259 | |||
4260 | if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) || | ||
4261 | (regdom->dfs_region && | ||
4262 | nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region))) | ||
4263 | goto nla_put_failure_rcu; | ||
4264 | |||
4189 | nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); | 4265 | nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); |
4190 | if (!nl_reg_rules) | 4266 | if (!nl_reg_rules) |
4191 | goto nla_put_failure; | 4267 | goto nla_put_failure_rcu; |
4192 | 4268 | ||
4193 | for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) { | 4269 | for (i = 0; i < regdom->n_reg_rules; i++) { |
4194 | struct nlattr *nl_reg_rule; | 4270 | struct nlattr *nl_reg_rule; |
4195 | const struct ieee80211_reg_rule *reg_rule; | 4271 | const struct ieee80211_reg_rule *reg_rule; |
4196 | const struct ieee80211_freq_range *freq_range; | 4272 | const struct ieee80211_freq_range *freq_range; |
4197 | const struct ieee80211_power_rule *power_rule; | 4273 | const struct ieee80211_power_rule *power_rule; |
4198 | 4274 | ||
4199 | reg_rule = &cfg80211_regdomain->reg_rules[i]; | 4275 | reg_rule = ®dom->reg_rules[i]; |
4200 | freq_range = ®_rule->freq_range; | 4276 | freq_range = ®_rule->freq_range; |
4201 | power_rule = ®_rule->power_rule; | 4277 | power_rule = ®_rule->power_rule; |
4202 | 4278 | ||
4203 | nl_reg_rule = nla_nest_start(msg, i); | 4279 | nl_reg_rule = nla_nest_start(msg, i); |
4204 | if (!nl_reg_rule) | 4280 | if (!nl_reg_rule) |
4205 | goto nla_put_failure; | 4281 | goto nla_put_failure_rcu; |
4206 | 4282 | ||
4207 | if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS, | 4283 | if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS, |
4208 | reg_rule->flags) || | 4284 | reg_rule->flags) || |
@@ -4216,10 +4292,11 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
4216 | power_rule->max_antenna_gain) || | 4292 | power_rule->max_antenna_gain) || |
4217 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, | 4293 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, |
4218 | power_rule->max_eirp)) | 4294 | power_rule->max_eirp)) |
4219 | goto nla_put_failure; | 4295 | goto nla_put_failure_rcu; |
4220 | 4296 | ||
4221 | nla_nest_end(msg, nl_reg_rule); | 4297 | nla_nest_end(msg, nl_reg_rule); |
4222 | } | 4298 | } |
4299 | rcu_read_unlock(); | ||
4223 | 4300 | ||
4224 | nla_nest_end(msg, nl_reg_rules); | 4301 | nla_nest_end(msg, nl_reg_rules); |
4225 | 4302 | ||
@@ -4227,6 +4304,8 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
4227 | err = genlmsg_reply(msg, info); | 4304 | err = genlmsg_reply(msg, info); |
4228 | goto out; | 4305 | goto out; |
4229 | 4306 | ||
4307 | nla_put_failure_rcu: | ||
4308 | rcu_read_unlock(); | ||
4230 | nla_put_failure: | 4309 | nla_put_failure: |
4231 | genlmsg_cancel(msg, hdr); | 4310 | genlmsg_cancel(msg, hdr); |
4232 | put_failure: | 4311 | put_failure: |
@@ -4259,27 +4338,18 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
4259 | dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]); | 4338 | dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]); |
4260 | 4339 | ||
4261 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], | 4340 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], |
4262 | rem_reg_rules) { | 4341 | rem_reg_rules) { |
4263 | num_rules++; | 4342 | num_rules++; |
4264 | if (num_rules > NL80211_MAX_SUPP_REG_RULES) | 4343 | if (num_rules > NL80211_MAX_SUPP_REG_RULES) |
4265 | return -EINVAL; | 4344 | return -EINVAL; |
4266 | } | 4345 | } |
4267 | 4346 | ||
4268 | mutex_lock(&cfg80211_mutex); | ||
4269 | |||
4270 | if (!reg_is_valid_request(alpha2)) { | ||
4271 | r = -EINVAL; | ||
4272 | goto bad_reg; | ||
4273 | } | ||
4274 | |||
4275 | size_of_regd = sizeof(struct ieee80211_regdomain) + | 4347 | size_of_regd = sizeof(struct ieee80211_regdomain) + |
4276 | (num_rules * sizeof(struct ieee80211_reg_rule)); | 4348 | num_rules * sizeof(struct ieee80211_reg_rule); |
4277 | 4349 | ||
4278 | rd = kzalloc(size_of_regd, GFP_KERNEL); | 4350 | rd = kzalloc(size_of_regd, GFP_KERNEL); |
4279 | if (!rd) { | 4351 | if (!rd) |
4280 | r = -ENOMEM; | 4352 | return -ENOMEM; |
4281 | goto bad_reg; | ||
4282 | } | ||
4283 | 4353 | ||
4284 | rd->n_reg_rules = num_rules; | 4354 | rd->n_reg_rules = num_rules; |
4285 | rd->alpha2[0] = alpha2[0]; | 4355 | rd->alpha2[0] = alpha2[0]; |
@@ -4293,10 +4363,10 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
4293 | rd->dfs_region = dfs_region; | 4363 | rd->dfs_region = dfs_region; |
4294 | 4364 | ||
4295 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], | 4365 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], |
4296 | rem_reg_rules) { | 4366 | rem_reg_rules) { |
4297 | nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, | 4367 | nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, |
4298 | nla_data(nl_reg_rule), nla_len(nl_reg_rule), | 4368 | nla_data(nl_reg_rule), nla_len(nl_reg_rule), |
4299 | reg_rule_policy); | 4369 | reg_rule_policy); |
4300 | r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]); | 4370 | r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]); |
4301 | if (r) | 4371 | if (r) |
4302 | goto bad_reg; | 4372 | goto bad_reg; |
@@ -4309,16 +4379,14 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
4309 | } | 4379 | } |
4310 | } | 4380 | } |
4311 | 4381 | ||
4312 | BUG_ON(rule_idx != num_rules); | 4382 | mutex_lock(&cfg80211_mutex); |
4313 | 4383 | ||
4314 | r = set_regdom(rd); | 4384 | r = set_regdom(rd); |
4315 | 4385 | /* set_regdom took ownership */ | |
4386 | rd = NULL; | ||
4316 | mutex_unlock(&cfg80211_mutex); | 4387 | mutex_unlock(&cfg80211_mutex); |
4317 | 4388 | ||
4318 | return r; | ||
4319 | |||
4320 | bad_reg: | 4389 | bad_reg: |
4321 | mutex_unlock(&cfg80211_mutex); | ||
4322 | kfree(rd); | 4390 | kfree(rd); |
4323 | return r; | 4391 | return r; |
4324 | } | 4392 | } |
@@ -5867,6 +5935,15 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
5867 | connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 5935 | connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
5868 | } | 5936 | } |
5869 | 5937 | ||
5938 | if (info->attrs[NL80211_ATTR_USE_MFP]) { | ||
5939 | connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]); | ||
5940 | if (connect.mfp != NL80211_MFP_REQUIRED && | ||
5941 | connect.mfp != NL80211_MFP_NO) | ||
5942 | return -EINVAL; | ||
5943 | } else { | ||
5944 | connect.mfp = NL80211_MFP_NO; | ||
5945 | } | ||
5946 | |||
5870 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 5947 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
5871 | connect.channel = | 5948 | connect.channel = |
5872 | ieee80211_get_channel(wiphy, | 5949 | ieee80211_get_channel(wiphy, |
@@ -6652,6 +6729,21 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) | |||
6652 | nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]))) | 6729 | nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]))) |
6653 | return -EINVAL; | 6730 | return -EINVAL; |
6654 | 6731 | ||
6732 | if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) { | ||
6733 | setup.beacon_interval = | ||
6734 | nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); | ||
6735 | if (setup.beacon_interval < 10 || | ||
6736 | setup.beacon_interval > 10000) | ||
6737 | return -EINVAL; | ||
6738 | } | ||
6739 | |||
6740 | if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) { | ||
6741 | setup.dtim_period = | ||
6742 | nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); | ||
6743 | if (setup.dtim_period < 1 || setup.dtim_period > 100) | ||
6744 | return -EINVAL; | ||
6745 | } | ||
6746 | |||
6655 | if (info->attrs[NL80211_ATTR_MESH_SETUP]) { | 6747 | if (info->attrs[NL80211_ATTR_MESH_SETUP]) { |
6656 | /* parse additional setup parameters if given */ | 6748 | /* parse additional setup parameters if given */ |
6657 | err = nl80211_parse_mesh_setup(info, &setup); | 6749 | err = nl80211_parse_mesh_setup(info, &setup); |
@@ -8051,7 +8143,7 @@ void nl80211_send_reg_change_event(struct regulatory_request *request) | |||
8051 | goto nla_put_failure; | 8143 | goto nla_put_failure; |
8052 | } | 8144 | } |
8053 | 8145 | ||
8054 | if (wiphy_idx_valid(request->wiphy_idx) && | 8146 | if (request->wiphy_idx != WIPHY_IDX_INVALID && |
8055 | nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx)) | 8147 | nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx)) |
8056 | goto nla_put_failure; | 8148 | goto nla_put_failure; |
8057 | 8149 | ||
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 82c4fc7c994c..de02d633c212 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -48,7 +48,6 @@ | |||
48 | #include <linux/export.h> | 48 | #include <linux/export.h> |
49 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
50 | #include <linux/list.h> | 50 | #include <linux/list.h> |
51 | #include <linux/random.h> | ||
52 | #include <linux/ctype.h> | 51 | #include <linux/ctype.h> |
53 | #include <linux/nl80211.h> | 52 | #include <linux/nl80211.h> |
54 | #include <linux/platform_device.h> | 53 | #include <linux/platform_device.h> |
@@ -66,6 +65,13 @@ | |||
66 | #define REG_DBG_PRINT(args...) | 65 | #define REG_DBG_PRINT(args...) |
67 | #endif | 66 | #endif |
68 | 67 | ||
68 | enum reg_request_treatment { | ||
69 | REG_REQ_OK, | ||
70 | REG_REQ_IGNORE, | ||
71 | REG_REQ_INTERSECT, | ||
72 | REG_REQ_ALREADY_SET, | ||
73 | }; | ||
74 | |||
69 | static struct regulatory_request core_request_world = { | 75 | static struct regulatory_request core_request_world = { |
70 | .initiator = NL80211_REGDOM_SET_BY_CORE, | 76 | .initiator = NL80211_REGDOM_SET_BY_CORE, |
71 | .alpha2[0] = '0', | 77 | .alpha2[0] = '0', |
@@ -76,7 +82,8 @@ static struct regulatory_request core_request_world = { | |||
76 | }; | 82 | }; |
77 | 83 | ||
78 | /* Receipt of information from last regulatory request */ | 84 | /* Receipt of information from last regulatory request */ |
79 | static struct regulatory_request *last_request = &core_request_world; | 85 | static struct regulatory_request __rcu *last_request = |
86 | (void __rcu *)&core_request_world; | ||
80 | 87 | ||
81 | /* To trigger userspace events */ | 88 | /* To trigger userspace events */ |
82 | static struct platform_device *reg_pdev; | 89 | static struct platform_device *reg_pdev; |
@@ -88,16 +95,16 @@ static struct device_type reg_device_type = { | |||
88 | /* | 95 | /* |
89 | * Central wireless core regulatory domains, we only need two, | 96 | * Central wireless core regulatory domains, we only need two, |
90 | * the current one and a world regulatory domain in case we have no | 97 | * the current one and a world regulatory domain in case we have no |
91 | * information to give us an alpha2 | 98 | * information to give us an alpha2. |
92 | */ | 99 | */ |
93 | const struct ieee80211_regdomain *cfg80211_regdomain; | 100 | const struct ieee80211_regdomain __rcu *cfg80211_regdomain; |
94 | 101 | ||
95 | /* | 102 | /* |
96 | * Protects static reg.c components: | 103 | * Protects static reg.c components: |
97 | * - cfg80211_world_regdom | 104 | * - cfg80211_regdomain (if not used with RCU) |
98 | * - cfg80211_regdom | 105 | * - cfg80211_world_regdom |
99 | * - last_request | 106 | * - last_request (if not used with RCU) |
100 | * - reg_num_devs_support_basehint | 107 | * - reg_num_devs_support_basehint |
101 | */ | 108 | */ |
102 | static DEFINE_MUTEX(reg_mutex); | 109 | static DEFINE_MUTEX(reg_mutex); |
103 | 110 | ||
@@ -112,6 +119,31 @@ static inline void assert_reg_lock(void) | |||
112 | lockdep_assert_held(®_mutex); | 119 | lockdep_assert_held(®_mutex); |
113 | } | 120 | } |
114 | 121 | ||
122 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) | ||
123 | { | ||
124 | return rcu_dereference_protected(cfg80211_regdomain, | ||
125 | lockdep_is_held(®_mutex)); | ||
126 | } | ||
127 | |||
128 | static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy) | ||
129 | { | ||
130 | return rcu_dereference_protected(wiphy->regd, | ||
131 | lockdep_is_held(®_mutex)); | ||
132 | } | ||
133 | |||
134 | static void rcu_free_regdom(const struct ieee80211_regdomain *r) | ||
135 | { | ||
136 | if (!r) | ||
137 | return; | ||
138 | kfree_rcu((struct ieee80211_regdomain *)r, rcu_head); | ||
139 | } | ||
140 | |||
141 | static struct regulatory_request *get_last_request(void) | ||
142 | { | ||
143 | return rcu_dereference_check(last_request, | ||
144 | lockdep_is_held(®_mutex)); | ||
145 | } | ||
146 | |||
115 | /* Used to queue up regulatory hints */ | 147 | /* Used to queue up regulatory hints */ |
116 | static LIST_HEAD(reg_requests_list); | 148 | static LIST_HEAD(reg_requests_list); |
117 | static spinlock_t reg_requests_lock; | 149 | static spinlock_t reg_requests_lock; |
@@ -177,28 +209,37 @@ static char user_alpha2[2]; | |||
177 | module_param(ieee80211_regdom, charp, 0444); | 209 | module_param(ieee80211_regdom, charp, 0444); |
178 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | 210 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); |
179 | 211 | ||
180 | static void reset_regdomains(bool full_reset) | 212 | static void reset_regdomains(bool full_reset, |
213 | const struct ieee80211_regdomain *new_regdom) | ||
181 | { | 214 | { |
215 | const struct ieee80211_regdomain *r; | ||
216 | struct regulatory_request *lr; | ||
217 | |||
218 | assert_reg_lock(); | ||
219 | |||
220 | r = get_cfg80211_regdom(); | ||
221 | |||
182 | /* avoid freeing static information or freeing something twice */ | 222 | /* avoid freeing static information or freeing something twice */ |
183 | if (cfg80211_regdomain == cfg80211_world_regdom) | 223 | if (r == cfg80211_world_regdom) |
184 | cfg80211_regdomain = NULL; | 224 | r = NULL; |
185 | if (cfg80211_world_regdom == &world_regdom) | 225 | if (cfg80211_world_regdom == &world_regdom) |
186 | cfg80211_world_regdom = NULL; | 226 | cfg80211_world_regdom = NULL; |
187 | if (cfg80211_regdomain == &world_regdom) | 227 | if (r == &world_regdom) |
188 | cfg80211_regdomain = NULL; | 228 | r = NULL; |
189 | 229 | ||
190 | kfree(cfg80211_regdomain); | 230 | rcu_free_regdom(r); |
191 | kfree(cfg80211_world_regdom); | 231 | rcu_free_regdom(cfg80211_world_regdom); |
192 | 232 | ||
193 | cfg80211_world_regdom = &world_regdom; | 233 | cfg80211_world_regdom = &world_regdom; |
194 | cfg80211_regdomain = NULL; | 234 | rcu_assign_pointer(cfg80211_regdomain, new_regdom); |
195 | 235 | ||
196 | if (!full_reset) | 236 | if (!full_reset) |
197 | return; | 237 | return; |
198 | 238 | ||
199 | if (last_request != &core_request_world) | 239 | lr = get_last_request(); |
200 | kfree(last_request); | 240 | if (lr != &core_request_world && lr) |
201 | last_request = &core_request_world; | 241 | kfree_rcu(lr, rcu_head); |
242 | rcu_assign_pointer(last_request, &core_request_world); | ||
202 | } | 243 | } |
203 | 244 | ||
204 | /* | 245 | /* |
@@ -207,30 +248,29 @@ static void reset_regdomains(bool full_reset) | |||
207 | */ | 248 | */ |
208 | static void update_world_regdomain(const struct ieee80211_regdomain *rd) | 249 | static void update_world_regdomain(const struct ieee80211_regdomain *rd) |
209 | { | 250 | { |
210 | BUG_ON(!last_request); | 251 | struct regulatory_request *lr; |
252 | |||
253 | lr = get_last_request(); | ||
254 | |||
255 | WARN_ON(!lr); | ||
211 | 256 | ||
212 | reset_regdomains(false); | 257 | reset_regdomains(false, rd); |
213 | 258 | ||
214 | cfg80211_world_regdom = rd; | 259 | cfg80211_world_regdom = rd; |
215 | cfg80211_regdomain = rd; | ||
216 | } | 260 | } |
217 | 261 | ||
218 | bool is_world_regdom(const char *alpha2) | 262 | bool is_world_regdom(const char *alpha2) |
219 | { | 263 | { |
220 | if (!alpha2) | 264 | if (!alpha2) |
221 | return false; | 265 | return false; |
222 | if (alpha2[0] == '0' && alpha2[1] == '0') | 266 | return alpha2[0] == '0' && alpha2[1] == '0'; |
223 | return true; | ||
224 | return false; | ||
225 | } | 267 | } |
226 | 268 | ||
227 | static bool is_alpha2_set(const char *alpha2) | 269 | static bool is_alpha2_set(const char *alpha2) |
228 | { | 270 | { |
229 | if (!alpha2) | 271 | if (!alpha2) |
230 | return false; | 272 | return false; |
231 | if (alpha2[0] != 0 && alpha2[1] != 0) | 273 | return alpha2[0] && alpha2[1]; |
232 | return true; | ||
233 | return false; | ||
234 | } | 274 | } |
235 | 275 | ||
236 | static bool is_unknown_alpha2(const char *alpha2) | 276 | static bool is_unknown_alpha2(const char *alpha2) |
@@ -241,9 +281,7 @@ static bool is_unknown_alpha2(const char *alpha2) | |||
241 | * Special case where regulatory domain was built by driver | 281 | * Special case where regulatory domain was built by driver |
242 | * but a specific alpha2 cannot be determined | 282 | * but a specific alpha2 cannot be determined |
243 | */ | 283 | */ |
244 | if (alpha2[0] == '9' && alpha2[1] == '9') | 284 | return alpha2[0] == '9' && alpha2[1] == '9'; |
245 | return true; | ||
246 | return false; | ||
247 | } | 285 | } |
248 | 286 | ||
249 | static bool is_intersected_alpha2(const char *alpha2) | 287 | static bool is_intersected_alpha2(const char *alpha2) |
@@ -255,39 +293,30 @@ static bool is_intersected_alpha2(const char *alpha2) | |||
255 | * result of an intersection between two regulatory domain | 293 | * result of an intersection between two regulatory domain |
256 | * structures | 294 | * structures |
257 | */ | 295 | */ |
258 | if (alpha2[0] == '9' && alpha2[1] == '8') | 296 | return alpha2[0] == '9' && alpha2[1] == '8'; |
259 | return true; | ||
260 | return false; | ||
261 | } | 297 | } |
262 | 298 | ||
263 | static bool is_an_alpha2(const char *alpha2) | 299 | static bool is_an_alpha2(const char *alpha2) |
264 | { | 300 | { |
265 | if (!alpha2) | 301 | if (!alpha2) |
266 | return false; | 302 | return false; |
267 | if (isalpha(alpha2[0]) && isalpha(alpha2[1])) | 303 | return isalpha(alpha2[0]) && isalpha(alpha2[1]); |
268 | return true; | ||
269 | return false; | ||
270 | } | 304 | } |
271 | 305 | ||
272 | static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y) | 306 | static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y) |
273 | { | 307 | { |
274 | if (!alpha2_x || !alpha2_y) | 308 | if (!alpha2_x || !alpha2_y) |
275 | return false; | 309 | return false; |
276 | if (alpha2_x[0] == alpha2_y[0] && | 310 | return alpha2_x[0] == alpha2_y[0] && alpha2_x[1] == alpha2_y[1]; |
277 | alpha2_x[1] == alpha2_y[1]) | ||
278 | return true; | ||
279 | return false; | ||
280 | } | 311 | } |
281 | 312 | ||
282 | static bool regdom_changes(const char *alpha2) | 313 | static bool regdom_changes(const char *alpha2) |
283 | { | 314 | { |
284 | assert_cfg80211_lock(); | 315 | const struct ieee80211_regdomain *r = get_cfg80211_regdom(); |
285 | 316 | ||
286 | if (!cfg80211_regdomain) | 317 | if (!r) |
287 | return true; | 318 | return true; |
288 | if (alpha2_equal(cfg80211_regdomain->alpha2, alpha2)) | 319 | return !alpha2_equal(r->alpha2, alpha2); |
289 | return false; | ||
290 | return true; | ||
291 | } | 320 | } |
292 | 321 | ||
293 | /* | 322 | /* |
@@ -301,38 +330,36 @@ static bool is_user_regdom_saved(void) | |||
301 | return false; | 330 | return false; |
302 | 331 | ||
303 | /* This would indicate a mistake on the design */ | 332 | /* This would indicate a mistake on the design */ |
304 | if (WARN((!is_world_regdom(user_alpha2) && | 333 | if (WARN(!is_world_regdom(user_alpha2) && !is_an_alpha2(user_alpha2), |
305 | !is_an_alpha2(user_alpha2)), | ||
306 | "Unexpected user alpha2: %c%c\n", | 334 | "Unexpected user alpha2: %c%c\n", |
307 | user_alpha2[0], | 335 | user_alpha2[0], user_alpha2[1])) |
308 | user_alpha2[1])) | ||
309 | return false; | 336 | return false; |
310 | 337 | ||
311 | return true; | 338 | return true; |
312 | } | 339 | } |
313 | 340 | ||
314 | static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, | 341 | static const struct ieee80211_regdomain * |
315 | const struct ieee80211_regdomain *src_regd) | 342 | reg_copy_regd(const struct ieee80211_regdomain *src_regd) |
316 | { | 343 | { |
317 | struct ieee80211_regdomain *regd; | 344 | struct ieee80211_regdomain *regd; |
318 | int size_of_regd = 0; | 345 | int size_of_regd; |
319 | unsigned int i; | 346 | unsigned int i; |
320 | 347 | ||
321 | size_of_regd = sizeof(struct ieee80211_regdomain) + | 348 | size_of_regd = |
322 | ((src_regd->n_reg_rules + 1) * sizeof(struct ieee80211_reg_rule)); | 349 | sizeof(struct ieee80211_regdomain) + |
350 | src_regd->n_reg_rules * sizeof(struct ieee80211_reg_rule); | ||
323 | 351 | ||
324 | regd = kzalloc(size_of_regd, GFP_KERNEL); | 352 | regd = kzalloc(size_of_regd, GFP_KERNEL); |
325 | if (!regd) | 353 | if (!regd) |
326 | return -ENOMEM; | 354 | return ERR_PTR(-ENOMEM); |
327 | 355 | ||
328 | memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain)); | 356 | memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain)); |
329 | 357 | ||
330 | for (i = 0; i < src_regd->n_reg_rules; i++) | 358 | for (i = 0; i < src_regd->n_reg_rules; i++) |
331 | memcpy(®d->reg_rules[i], &src_regd->reg_rules[i], | 359 | memcpy(®d->reg_rules[i], &src_regd->reg_rules[i], |
332 | sizeof(struct ieee80211_reg_rule)); | 360 | sizeof(struct ieee80211_reg_rule)); |
333 | 361 | ||
334 | *dst_regd = regd; | 362 | return regd; |
335 | return 0; | ||
336 | } | 363 | } |
337 | 364 | ||
338 | #ifdef CONFIG_CFG80211_INTERNAL_REGDB | 365 | #ifdef CONFIG_CFG80211_INTERNAL_REGDB |
@@ -347,9 +374,8 @@ static DEFINE_MUTEX(reg_regdb_search_mutex); | |||
347 | static void reg_regdb_search(struct work_struct *work) | 374 | static void reg_regdb_search(struct work_struct *work) |
348 | { | 375 | { |
349 | struct reg_regdb_search_request *request; | 376 | struct reg_regdb_search_request *request; |
350 | const struct ieee80211_regdomain *curdom, *regdom; | 377 | const struct ieee80211_regdomain *curdom, *regdom = NULL; |
351 | int i, r; | 378 | int i; |
352 | bool set_reg = false; | ||
353 | 379 | ||
354 | mutex_lock(&cfg80211_mutex); | 380 | mutex_lock(&cfg80211_mutex); |
355 | 381 | ||
@@ -360,14 +386,11 @@ static void reg_regdb_search(struct work_struct *work) | |||
360 | list); | 386 | list); |
361 | list_del(&request->list); | 387 | list_del(&request->list); |
362 | 388 | ||
363 | for (i=0; i<reg_regdb_size; i++) { | 389 | for (i = 0; i < reg_regdb_size; i++) { |
364 | curdom = reg_regdb[i]; | 390 | curdom = reg_regdb[i]; |
365 | 391 | ||
366 | if (!memcmp(request->alpha2, curdom->alpha2, 2)) { | 392 | if (alpha2_equal(request->alpha2, curdom->alpha2)) { |
367 | r = reg_copy_regd(®dom, curdom); | 393 | regdom = reg_copy_regd(curdom); |
368 | if (r) | ||
369 | break; | ||
370 | set_reg = true; | ||
371 | break; | 394 | break; |
372 | } | 395 | } |
373 | } | 396 | } |
@@ -376,7 +399,7 @@ static void reg_regdb_search(struct work_struct *work) | |||
376 | } | 399 | } |
377 | mutex_unlock(®_regdb_search_mutex); | 400 | mutex_unlock(®_regdb_search_mutex); |
378 | 401 | ||
379 | if (set_reg) | 402 | if (!IS_ERR_OR_NULL(regdom)) |
380 | set_regdom(regdom); | 403 | set_regdom(regdom); |
381 | 404 | ||
382 | mutex_unlock(&cfg80211_mutex); | 405 | mutex_unlock(&cfg80211_mutex); |
@@ -434,15 +457,14 @@ static int call_crda(const char *alpha2) | |||
434 | return kobject_uevent(®_pdev->dev.kobj, KOBJ_CHANGE); | 457 | return kobject_uevent(®_pdev->dev.kobj, KOBJ_CHANGE); |
435 | } | 458 | } |
436 | 459 | ||
437 | /* Used by nl80211 before kmalloc'ing our regulatory domain */ | 460 | static bool reg_is_valid_request(const char *alpha2) |
438 | bool reg_is_valid_request(const char *alpha2) | ||
439 | { | 461 | { |
440 | assert_cfg80211_lock(); | 462 | struct regulatory_request *lr = get_last_request(); |
441 | 463 | ||
442 | if (!last_request) | 464 | if (!lr || lr->processed) |
443 | return false; | 465 | return false; |
444 | 466 | ||
445 | return alpha2_equal(last_request->alpha2, alpha2); | 467 | return alpha2_equal(lr->alpha2, alpha2); |
446 | } | 468 | } |
447 | 469 | ||
448 | /* Sanity check on a regulatory rule */ | 470 | /* Sanity check on a regulatory rule */ |
@@ -460,7 +482,7 @@ static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule) | |||
460 | freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz; | 482 | freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz; |
461 | 483 | ||
462 | if (freq_range->end_freq_khz <= freq_range->start_freq_khz || | 484 | if (freq_range->end_freq_khz <= freq_range->start_freq_khz || |
463 | freq_range->max_bandwidth_khz > freq_diff) | 485 | freq_range->max_bandwidth_khz > freq_diff) |
464 | return false; | 486 | return false; |
465 | 487 | ||
466 | return true; | 488 | return true; |
@@ -487,8 +509,7 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd) | |||
487 | } | 509 | } |
488 | 510 | ||
489 | static bool reg_does_bw_fit(const struct ieee80211_freq_range *freq_range, | 511 | static bool reg_does_bw_fit(const struct ieee80211_freq_range *freq_range, |
490 | u32 center_freq_khz, | 512 | u32 center_freq_khz, u32 bw_khz) |
491 | u32 bw_khz) | ||
492 | { | 513 | { |
493 | u32 start_freq_khz, end_freq_khz; | 514 | u32 start_freq_khz, end_freq_khz; |
494 | 515 | ||
@@ -518,7 +539,7 @@ static bool reg_does_bw_fit(const struct ieee80211_freq_range *freq_range, | |||
518 | * regulatory rule support for other "bands". | 539 | * regulatory rule support for other "bands". |
519 | **/ | 540 | **/ |
520 | static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range, | 541 | static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range, |
521 | u32 freq_khz) | 542 | u32 freq_khz) |
522 | { | 543 | { |
523 | #define ONE_GHZ_IN_KHZ 1000000 | 544 | #define ONE_GHZ_IN_KHZ 1000000 |
524 | /* | 545 | /* |
@@ -540,10 +561,9 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range, | |||
540 | * Helper for regdom_intersect(), this does the real | 561 | * Helper for regdom_intersect(), this does the real |
541 | * mathematical intersection fun | 562 | * mathematical intersection fun |
542 | */ | 563 | */ |
543 | static int reg_rules_intersect( | 564 | static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1, |
544 | const struct ieee80211_reg_rule *rule1, | 565 | const struct ieee80211_reg_rule *rule2, |
545 | const struct ieee80211_reg_rule *rule2, | 566 | struct ieee80211_reg_rule *intersected_rule) |
546 | struct ieee80211_reg_rule *intersected_rule) | ||
547 | { | 567 | { |
548 | const struct ieee80211_freq_range *freq_range1, *freq_range2; | 568 | const struct ieee80211_freq_range *freq_range1, *freq_range2; |
549 | struct ieee80211_freq_range *freq_range; | 569 | struct ieee80211_freq_range *freq_range; |
@@ -560,11 +580,11 @@ static int reg_rules_intersect( | |||
560 | power_rule = &intersected_rule->power_rule; | 580 | power_rule = &intersected_rule->power_rule; |
561 | 581 | ||
562 | freq_range->start_freq_khz = max(freq_range1->start_freq_khz, | 582 | freq_range->start_freq_khz = max(freq_range1->start_freq_khz, |
563 | freq_range2->start_freq_khz); | 583 | freq_range2->start_freq_khz); |
564 | freq_range->end_freq_khz = min(freq_range1->end_freq_khz, | 584 | freq_range->end_freq_khz = min(freq_range1->end_freq_khz, |
565 | freq_range2->end_freq_khz); | 585 | freq_range2->end_freq_khz); |
566 | freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz, | 586 | freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz, |
567 | freq_range2->max_bandwidth_khz); | 587 | freq_range2->max_bandwidth_khz); |
568 | 588 | ||
569 | freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz; | 589 | freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz; |
570 | if (freq_range->max_bandwidth_khz > freq_diff) | 590 | if (freq_range->max_bandwidth_khz > freq_diff) |
@@ -575,7 +595,7 @@ static int reg_rules_intersect( | |||
575 | power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain, | 595 | power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain, |
576 | power_rule2->max_antenna_gain); | 596 | power_rule2->max_antenna_gain); |
577 | 597 | ||
578 | intersected_rule->flags = (rule1->flags | rule2->flags); | 598 | intersected_rule->flags = rule1->flags | rule2->flags; |
579 | 599 | ||
580 | if (!is_valid_reg_rule(intersected_rule)) | 600 | if (!is_valid_reg_rule(intersected_rule)) |
581 | return -EINVAL; | 601 | return -EINVAL; |
@@ -596,9 +616,9 @@ static int reg_rules_intersect( | |||
596 | * resulting intersection of rules between rd1 and rd2. We will | 616 | * resulting intersection of rules between rd1 and rd2. We will |
597 | * kzalloc() this structure for you. | 617 | * kzalloc() this structure for you. |
598 | */ | 618 | */ |
599 | static struct ieee80211_regdomain *regdom_intersect( | 619 | static struct ieee80211_regdomain * |
600 | const struct ieee80211_regdomain *rd1, | 620 | regdom_intersect(const struct ieee80211_regdomain *rd1, |
601 | const struct ieee80211_regdomain *rd2) | 621 | const struct ieee80211_regdomain *rd2) |
602 | { | 622 | { |
603 | int r, size_of_regd; | 623 | int r, size_of_regd; |
604 | unsigned int x, y; | 624 | unsigned int x, y; |
@@ -607,12 +627,7 @@ static struct ieee80211_regdomain *regdom_intersect( | |||
607 | struct ieee80211_reg_rule *intersected_rule; | 627 | struct ieee80211_reg_rule *intersected_rule; |
608 | struct ieee80211_regdomain *rd; | 628 | struct ieee80211_regdomain *rd; |
609 | /* This is just a dummy holder to help us count */ | 629 | /* This is just a dummy holder to help us count */ |
610 | struct ieee80211_reg_rule irule; | 630 | struct ieee80211_reg_rule dummy_rule; |
611 | |||
612 | /* Uses the stack temporarily for counter arithmetic */ | ||
613 | intersected_rule = &irule; | ||
614 | |||
615 | memset(intersected_rule, 0, sizeof(struct ieee80211_reg_rule)); | ||
616 | 631 | ||
617 | if (!rd1 || !rd2) | 632 | if (!rd1 || !rd2) |
618 | return NULL; | 633 | return NULL; |
@@ -629,11 +644,8 @@ static struct ieee80211_regdomain *regdom_intersect( | |||
629 | rule1 = &rd1->reg_rules[x]; | 644 | rule1 = &rd1->reg_rules[x]; |
630 | for (y = 0; y < rd2->n_reg_rules; y++) { | 645 | for (y = 0; y < rd2->n_reg_rules; y++) { |
631 | rule2 = &rd2->reg_rules[y]; | 646 | rule2 = &rd2->reg_rules[y]; |
632 | if (!reg_rules_intersect(rule1, rule2, | 647 | if (!reg_rules_intersect(rule1, rule2, &dummy_rule)) |
633 | intersected_rule)) | ||
634 | num_rules++; | 648 | num_rules++; |
635 | memset(intersected_rule, 0, | ||
636 | sizeof(struct ieee80211_reg_rule)); | ||
637 | } | 649 | } |
638 | } | 650 | } |
639 | 651 | ||
@@ -641,15 +653,15 @@ static struct ieee80211_regdomain *regdom_intersect( | |||
641 | return NULL; | 653 | return NULL; |
642 | 654 | ||
643 | size_of_regd = sizeof(struct ieee80211_regdomain) + | 655 | size_of_regd = sizeof(struct ieee80211_regdomain) + |
644 | ((num_rules + 1) * sizeof(struct ieee80211_reg_rule)); | 656 | num_rules * sizeof(struct ieee80211_reg_rule); |
645 | 657 | ||
646 | rd = kzalloc(size_of_regd, GFP_KERNEL); | 658 | rd = kzalloc(size_of_regd, GFP_KERNEL); |
647 | if (!rd) | 659 | if (!rd) |
648 | return NULL; | 660 | return NULL; |
649 | 661 | ||
650 | for (x = 0; x < rd1->n_reg_rules; x++) { | 662 | for (x = 0; x < rd1->n_reg_rules && rule_idx < num_rules; x++) { |
651 | rule1 = &rd1->reg_rules[x]; | 663 | rule1 = &rd1->reg_rules[x]; |
652 | for (y = 0; y < rd2->n_reg_rules; y++) { | 664 | for (y = 0; y < rd2->n_reg_rules && rule_idx < num_rules; y++) { |
653 | rule2 = &rd2->reg_rules[y]; | 665 | rule2 = &rd2->reg_rules[y]; |
654 | /* | 666 | /* |
655 | * This time around instead of using the stack lets | 667 | * This time around instead of using the stack lets |
@@ -657,8 +669,7 @@ static struct ieee80211_regdomain *regdom_intersect( | |||
657 | * a memcpy() | 669 | * a memcpy() |
658 | */ | 670 | */ |
659 | intersected_rule = &rd->reg_rules[rule_idx]; | 671 | intersected_rule = &rd->reg_rules[rule_idx]; |
660 | r = reg_rules_intersect(rule1, rule2, | 672 | r = reg_rules_intersect(rule1, rule2, intersected_rule); |
661 | intersected_rule); | ||
662 | /* | 673 | /* |
663 | * No need to memset here the intersected rule here as | 674 | * No need to memset here the intersected rule here as |
664 | * we're not using the stack anymore | 675 | * we're not using the stack anymore |
@@ -699,34 +710,16 @@ static u32 map_regdom_flags(u32 rd_flags) | |||
699 | return channel_flags; | 710 | return channel_flags; |
700 | } | 711 | } |
701 | 712 | ||
702 | static int freq_reg_info_regd(struct wiphy *wiphy, | 713 | static const struct ieee80211_reg_rule * |
703 | u32 center_freq, | 714 | freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq, |
704 | u32 desired_bw_khz, | 715 | const struct ieee80211_regdomain *regd) |
705 | const struct ieee80211_reg_rule **reg_rule, | ||
706 | const struct ieee80211_regdomain *custom_regd) | ||
707 | { | 716 | { |
708 | int i; | 717 | int i; |
709 | bool band_rule_found = false; | 718 | bool band_rule_found = false; |
710 | const struct ieee80211_regdomain *regd; | ||
711 | bool bw_fits = false; | 719 | bool bw_fits = false; |
712 | 720 | ||
713 | if (!desired_bw_khz) | ||
714 | desired_bw_khz = MHZ_TO_KHZ(20); | ||
715 | |||
716 | regd = custom_regd ? custom_regd : cfg80211_regdomain; | ||
717 | |||
718 | /* | ||
719 | * Follow the driver's regulatory domain, if present, unless a country | ||
720 | * IE has been processed or a user wants to help complaince further | ||
721 | */ | ||
722 | if (!custom_regd && | ||
723 | last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
724 | last_request->initiator != NL80211_REGDOM_SET_BY_USER && | ||
725 | wiphy->regd) | ||
726 | regd = wiphy->regd; | ||
727 | |||
728 | if (!regd) | 721 | if (!regd) |
729 | return -EINVAL; | 722 | return ERR_PTR(-EINVAL); |
730 | 723 | ||
731 | for (i = 0; i < regd->n_reg_rules; i++) { | 724 | for (i = 0; i < regd->n_reg_rules; i++) { |
732 | const struct ieee80211_reg_rule *rr; | 725 | const struct ieee80211_reg_rule *rr; |
@@ -743,33 +736,36 @@ static int freq_reg_info_regd(struct wiphy *wiphy, | |||
743 | if (!band_rule_found) | 736 | if (!band_rule_found) |
744 | band_rule_found = freq_in_rule_band(fr, center_freq); | 737 | band_rule_found = freq_in_rule_band(fr, center_freq); |
745 | 738 | ||
746 | bw_fits = reg_does_bw_fit(fr, | 739 | bw_fits = reg_does_bw_fit(fr, center_freq, MHZ_TO_KHZ(20)); |
747 | center_freq, | ||
748 | desired_bw_khz); | ||
749 | 740 | ||
750 | if (band_rule_found && bw_fits) { | 741 | if (band_rule_found && bw_fits) |
751 | *reg_rule = rr; | 742 | return rr; |
752 | return 0; | ||
753 | } | ||
754 | } | 743 | } |
755 | 744 | ||
756 | if (!band_rule_found) | 745 | if (!band_rule_found) |
757 | return -ERANGE; | 746 | return ERR_PTR(-ERANGE); |
758 | 747 | ||
759 | return -EINVAL; | 748 | return ERR_PTR(-EINVAL); |
760 | } | 749 | } |
761 | 750 | ||
762 | int freq_reg_info(struct wiphy *wiphy, | 751 | const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy, |
763 | u32 center_freq, | 752 | u32 center_freq) |
764 | u32 desired_bw_khz, | ||
765 | const struct ieee80211_reg_rule **reg_rule) | ||
766 | { | 753 | { |
767 | assert_cfg80211_lock(); | 754 | const struct ieee80211_regdomain *regd; |
768 | return freq_reg_info_regd(wiphy, | 755 | struct regulatory_request *lr = get_last_request(); |
769 | center_freq, | 756 | |
770 | desired_bw_khz, | 757 | /* |
771 | reg_rule, | 758 | * Follow the driver's regulatory domain, if present, unless a country |
772 | NULL); | 759 | * IE has been processed or a user wants to help complaince further |
760 | */ | ||
761 | if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
762 | lr->initiator != NL80211_REGDOM_SET_BY_USER && | ||
763 | wiphy->regd) | ||
764 | regd = get_wiphy_regdom(wiphy); | ||
765 | else | ||
766 | regd = get_cfg80211_regdom(); | ||
767 | |||
768 | return freq_reg_info_regd(wiphy, center_freq, regd); | ||
773 | } | 769 | } |
774 | EXPORT_SYMBOL(freq_reg_info); | 770 | EXPORT_SYMBOL(freq_reg_info); |
775 | 771 | ||
@@ -792,7 +788,6 @@ static const char *reg_initiator_name(enum nl80211_reg_initiator initiator) | |||
792 | } | 788 | } |
793 | 789 | ||
794 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, | 790 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, |
795 | u32 desired_bw_khz, | ||
796 | const struct ieee80211_reg_rule *reg_rule) | 791 | const struct ieee80211_reg_rule *reg_rule) |
797 | { | 792 | { |
798 | const struct ieee80211_power_rule *power_rule; | 793 | const struct ieee80211_power_rule *power_rule; |
@@ -807,21 +802,16 @@ static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, | |||
807 | else | 802 | else |
808 | snprintf(max_antenna_gain, 32, "%d", power_rule->max_antenna_gain); | 803 | snprintf(max_antenna_gain, 32, "%d", power_rule->max_antenna_gain); |
809 | 804 | ||
810 | REG_DBG_PRINT("Updating information on frequency %d MHz " | 805 | REG_DBG_PRINT("Updating information on frequency %d MHz with regulatory rule:\n", |
811 | "for a %d MHz width channel with regulatory rule:\n", | 806 | chan->center_freq); |
812 | chan->center_freq, | ||
813 | KHZ_TO_MHZ(desired_bw_khz)); | ||
814 | 807 | ||
815 | REG_DBG_PRINT("%d KHz - %d KHz @ %d KHz), (%s mBi, %d mBm)\n", | 808 | REG_DBG_PRINT("%d KHz - %d KHz @ %d KHz), (%s mBi, %d mBm)\n", |
816 | freq_range->start_freq_khz, | 809 | freq_range->start_freq_khz, freq_range->end_freq_khz, |
817 | freq_range->end_freq_khz, | 810 | freq_range->max_bandwidth_khz, max_antenna_gain, |
818 | freq_range->max_bandwidth_khz, | ||
819 | max_antenna_gain, | ||
820 | power_rule->max_eirp); | 811 | power_rule->max_eirp); |
821 | } | 812 | } |
822 | #else | 813 | #else |
823 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, | 814 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, |
824 | u32 desired_bw_khz, | ||
825 | const struct ieee80211_reg_rule *reg_rule) | 815 | const struct ieee80211_reg_rule *reg_rule) |
826 | { | 816 | { |
827 | return; | 817 | return; |
@@ -831,43 +821,25 @@ static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, | |||
831 | /* | 821 | /* |
832 | * Note that right now we assume the desired channel bandwidth | 822 | * Note that right now we assume the desired channel bandwidth |
833 | * is always 20 MHz for each individual channel (HT40 uses 20 MHz | 823 | * is always 20 MHz for each individual channel (HT40 uses 20 MHz |
834 | * per channel, the primary and the extension channel). To support | 824 | * per channel, the primary and the extension channel). |
835 | * smaller custom bandwidths such as 5 MHz or 10 MHz we'll need a | ||
836 | * new ieee80211_channel.target_bw and re run the regulatory check | ||
837 | * on the wiphy with the target_bw specified. Then we can simply use | ||
838 | * that below for the desired_bw_khz below. | ||
839 | */ | 825 | */ |
840 | static void handle_channel(struct wiphy *wiphy, | 826 | static void handle_channel(struct wiphy *wiphy, |
841 | enum nl80211_reg_initiator initiator, | 827 | enum nl80211_reg_initiator initiator, |
842 | enum ieee80211_band band, | 828 | struct ieee80211_channel *chan) |
843 | unsigned int chan_idx) | ||
844 | { | 829 | { |
845 | int r; | ||
846 | u32 flags, bw_flags = 0; | 830 | u32 flags, bw_flags = 0; |
847 | u32 desired_bw_khz = MHZ_TO_KHZ(20); | ||
848 | const struct ieee80211_reg_rule *reg_rule = NULL; | 831 | const struct ieee80211_reg_rule *reg_rule = NULL; |
849 | const struct ieee80211_power_rule *power_rule = NULL; | 832 | const struct ieee80211_power_rule *power_rule = NULL; |
850 | const struct ieee80211_freq_range *freq_range = NULL; | 833 | const struct ieee80211_freq_range *freq_range = NULL; |
851 | struct ieee80211_supported_band *sband; | ||
852 | struct ieee80211_channel *chan; | ||
853 | struct wiphy *request_wiphy = NULL; | 834 | struct wiphy *request_wiphy = NULL; |
835 | struct regulatory_request *lr = get_last_request(); | ||
854 | 836 | ||
855 | assert_cfg80211_lock(); | 837 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); |
856 | |||
857 | request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); | ||
858 | |||
859 | sband = wiphy->bands[band]; | ||
860 | BUG_ON(chan_idx >= sband->n_channels); | ||
861 | chan = &sband->channels[chan_idx]; | ||
862 | 838 | ||
863 | flags = chan->orig_flags; | 839 | flags = chan->orig_flags; |
864 | 840 | ||
865 | r = freq_reg_info(wiphy, | 841 | reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq)); |
866 | MHZ_TO_KHZ(chan->center_freq), | 842 | if (IS_ERR(reg_rule)) { |
867 | desired_bw_khz, | ||
868 | ®_rule); | ||
869 | |||
870 | if (r) { | ||
871 | /* | 843 | /* |
872 | * We will disable all channels that do not match our | 844 | * We will disable all channels that do not match our |
873 | * received regulatory rule unless the hint is coming | 845 | * received regulatory rule unless the hint is coming |
@@ -879,7 +851,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
879 | * while 5 GHz is still supported. | 851 | * while 5 GHz is still supported. |
880 | */ | 852 | */ |
881 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && | 853 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && |
882 | r == -ERANGE) | 854 | PTR_ERR(reg_rule) == -ERANGE) |
883 | return; | 855 | return; |
884 | 856 | ||
885 | REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq); | 857 | REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq); |
@@ -887,7 +859,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
887 | return; | 859 | return; |
888 | } | 860 | } |
889 | 861 | ||
890 | chan_reg_rule_print_dbg(chan, desired_bw_khz, reg_rule); | 862 | chan_reg_rule_print_dbg(chan, reg_rule); |
891 | 863 | ||
892 | power_rule = ®_rule->power_rule; | 864 | power_rule = ®_rule->power_rule; |
893 | freq_range = ®_rule->freq_range; | 865 | freq_range = ®_rule->freq_range; |
@@ -895,7 +867,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
895 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) | 867 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) |
896 | bw_flags = IEEE80211_CHAN_NO_HT40; | 868 | bw_flags = IEEE80211_CHAN_NO_HT40; |
897 | 869 | ||
898 | if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && | 870 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
899 | request_wiphy && request_wiphy == wiphy && | 871 | request_wiphy && request_wiphy == wiphy && |
900 | request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { | 872 | request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { |
901 | /* | 873 | /* |
@@ -914,8 +886,9 @@ static void handle_channel(struct wiphy *wiphy, | |||
914 | 886 | ||
915 | chan->beacon_found = false; | 887 | chan->beacon_found = false; |
916 | chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); | 888 | chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); |
917 | chan->max_antenna_gain = min(chan->orig_mag, | 889 | chan->max_antenna_gain = |
918 | (int) MBI_TO_DBI(power_rule->max_antenna_gain)); | 890 | min_t(int, chan->orig_mag, |
891 | MBI_TO_DBI(power_rule->max_antenna_gain)); | ||
919 | chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); | 892 | chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); |
920 | if (chan->orig_mpwr) { | 893 | if (chan->orig_mpwr) { |
921 | /* | 894 | /* |
@@ -935,68 +908,65 @@ static void handle_channel(struct wiphy *wiphy, | |||
935 | } | 908 | } |
936 | 909 | ||
937 | static void handle_band(struct wiphy *wiphy, | 910 | static void handle_band(struct wiphy *wiphy, |
938 | enum ieee80211_band band, | 911 | enum nl80211_reg_initiator initiator, |
939 | enum nl80211_reg_initiator initiator) | 912 | struct ieee80211_supported_band *sband) |
940 | { | 913 | { |
941 | unsigned int i; | 914 | unsigned int i; |
942 | struct ieee80211_supported_band *sband; | ||
943 | 915 | ||
944 | BUG_ON(!wiphy->bands[band]); | 916 | if (!sband) |
945 | sband = wiphy->bands[band]; | 917 | return; |
946 | 918 | ||
947 | for (i = 0; i < sband->n_channels; i++) | 919 | for (i = 0; i < sband->n_channels; i++) |
948 | handle_channel(wiphy, initiator, band, i); | 920 | handle_channel(wiphy, initiator, &sband->channels[i]); |
949 | } | 921 | } |
950 | 922 | ||
951 | static bool reg_request_cell_base(struct regulatory_request *request) | 923 | static bool reg_request_cell_base(struct regulatory_request *request) |
952 | { | 924 | { |
953 | if (request->initiator != NL80211_REGDOM_SET_BY_USER) | 925 | if (request->initiator != NL80211_REGDOM_SET_BY_USER) |
954 | return false; | 926 | return false; |
955 | if (request->user_reg_hint_type != NL80211_USER_REG_HINT_CELL_BASE) | 927 | return request->user_reg_hint_type == NL80211_USER_REG_HINT_CELL_BASE; |
956 | return false; | ||
957 | return true; | ||
958 | } | 928 | } |
959 | 929 | ||
960 | bool reg_last_request_cell_base(void) | 930 | bool reg_last_request_cell_base(void) |
961 | { | 931 | { |
962 | bool val; | 932 | bool val; |
963 | assert_cfg80211_lock(); | ||
964 | 933 | ||
965 | mutex_lock(®_mutex); | 934 | mutex_lock(®_mutex); |
966 | val = reg_request_cell_base(last_request); | 935 | val = reg_request_cell_base(get_last_request()); |
967 | mutex_unlock(®_mutex); | 936 | mutex_unlock(®_mutex); |
937 | |||
968 | return val; | 938 | return val; |
969 | } | 939 | } |
970 | 940 | ||
971 | #ifdef CONFIG_CFG80211_CERTIFICATION_ONUS | 941 | #ifdef CONFIG_CFG80211_CERTIFICATION_ONUS |
972 | |||
973 | /* Core specific check */ | 942 | /* Core specific check */ |
974 | static int reg_ignore_cell_hint(struct regulatory_request *pending_request) | 943 | static enum reg_request_treatment |
944 | reg_ignore_cell_hint(struct regulatory_request *pending_request) | ||
975 | { | 945 | { |
946 | struct regulatory_request *lr = get_last_request(); | ||
947 | |||
976 | if (!reg_num_devs_support_basehint) | 948 | if (!reg_num_devs_support_basehint) |
977 | return -EOPNOTSUPP; | 949 | return REG_REQ_IGNORE; |
978 | 950 | ||
979 | if (reg_request_cell_base(last_request)) { | 951 | if (reg_request_cell_base(lr) && |
980 | if (!regdom_changes(pending_request->alpha2)) | 952 | !regdom_changes(pending_request->alpha2)) |
981 | return -EALREADY; | 953 | return REG_REQ_ALREADY_SET; |
982 | return 0; | 954 | |
983 | } | 955 | return REG_REQ_OK; |
984 | return 0; | ||
985 | } | 956 | } |
986 | 957 | ||
987 | /* Device specific check */ | 958 | /* Device specific check */ |
988 | static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy) | 959 | static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy) |
989 | { | 960 | { |
990 | if (!(wiphy->features & NL80211_FEATURE_CELL_BASE_REG_HINTS)) | 961 | return !(wiphy->features & NL80211_FEATURE_CELL_BASE_REG_HINTS); |
991 | return true; | ||
992 | return false; | ||
993 | } | 962 | } |
994 | #else | 963 | #else |
995 | static int reg_ignore_cell_hint(struct regulatory_request *pending_request) | 964 | static int reg_ignore_cell_hint(struct regulatory_request *pending_request) |
996 | { | 965 | { |
997 | return -EOPNOTSUPP; | 966 | return REG_REQ_IGNORE; |
998 | } | 967 | } |
999 | static int reg_dev_ignore_cell_hint(struct wiphy *wiphy) | 968 | |
969 | static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy) | ||
1000 | { | 970 | { |
1001 | return true; | 971 | return true; |
1002 | } | 972 | } |
@@ -1006,18 +976,17 @@ static int reg_dev_ignore_cell_hint(struct wiphy *wiphy) | |||
1006 | static bool ignore_reg_update(struct wiphy *wiphy, | 976 | static bool ignore_reg_update(struct wiphy *wiphy, |
1007 | enum nl80211_reg_initiator initiator) | 977 | enum nl80211_reg_initiator initiator) |
1008 | { | 978 | { |
1009 | if (!last_request) { | 979 | struct regulatory_request *lr = get_last_request(); |
1010 | REG_DBG_PRINT("Ignoring regulatory request %s since " | 980 | |
1011 | "last_request is not set\n", | 981 | if (!lr) { |
982 | REG_DBG_PRINT("Ignoring regulatory request %s since last_request is not set\n", | ||
1012 | reg_initiator_name(initiator)); | 983 | reg_initiator_name(initiator)); |
1013 | return true; | 984 | return true; |
1014 | } | 985 | } |
1015 | 986 | ||
1016 | if (initiator == NL80211_REGDOM_SET_BY_CORE && | 987 | if (initiator == NL80211_REGDOM_SET_BY_CORE && |
1017 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { | 988 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { |
1018 | REG_DBG_PRINT("Ignoring regulatory request %s " | 989 | REG_DBG_PRINT("Ignoring regulatory request %s since the driver uses its own custom regulatory domain\n", |
1019 | "since the driver uses its own custom " | ||
1020 | "regulatory domain\n", | ||
1021 | reg_initiator_name(initiator)); | 990 | reg_initiator_name(initiator)); |
1022 | return true; | 991 | return true; |
1023 | } | 992 | } |
@@ -1028,22 +997,35 @@ static bool ignore_reg_update(struct wiphy *wiphy, | |||
1028 | */ | 997 | */ |
1029 | if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd && | 998 | if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd && |
1030 | initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | 999 | initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && |
1031 | !is_world_regdom(last_request->alpha2)) { | 1000 | !is_world_regdom(lr->alpha2)) { |
1032 | REG_DBG_PRINT("Ignoring regulatory request %s " | 1001 | REG_DBG_PRINT("Ignoring regulatory request %s since the driver requires its own regulatory domain to be set first\n", |
1033 | "since the driver requires its own regulatory " | ||
1034 | "domain to be set first\n", | ||
1035 | reg_initiator_name(initiator)); | 1002 | reg_initiator_name(initiator)); |
1036 | return true; | 1003 | return true; |
1037 | } | 1004 | } |
1038 | 1005 | ||
1039 | if (reg_request_cell_base(last_request)) | 1006 | if (reg_request_cell_base(lr)) |
1040 | return reg_dev_ignore_cell_hint(wiphy); | 1007 | return reg_dev_ignore_cell_hint(wiphy); |
1041 | 1008 | ||
1042 | return false; | 1009 | return false; |
1043 | } | 1010 | } |
1044 | 1011 | ||
1045 | static void handle_reg_beacon(struct wiphy *wiphy, | 1012 | static bool reg_is_world_roaming(struct wiphy *wiphy) |
1046 | unsigned int chan_idx, | 1013 | { |
1014 | const struct ieee80211_regdomain *cr = get_cfg80211_regdom(); | ||
1015 | const struct ieee80211_regdomain *wr = get_wiphy_regdom(wiphy); | ||
1016 | struct regulatory_request *lr = get_last_request(); | ||
1017 | |||
1018 | if (is_world_regdom(cr->alpha2) || (wr && is_world_regdom(wr->alpha2))) | ||
1019 | return true; | ||
1020 | |||
1021 | if (lr && lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
1022 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) | ||
1023 | return true; | ||
1024 | |||
1025 | return false; | ||
1026 | } | ||
1027 | |||
1028 | static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx, | ||
1047 | struct reg_beacon *reg_beacon) | 1029 | struct reg_beacon *reg_beacon) |
1048 | { | 1030 | { |
1049 | struct ieee80211_supported_band *sband; | 1031 | struct ieee80211_supported_band *sband; |
@@ -1051,8 +1033,6 @@ static void handle_reg_beacon(struct wiphy *wiphy, | |||
1051 | bool channel_changed = false; | 1033 | bool channel_changed = false; |
1052 | struct ieee80211_channel chan_before; | 1034 | struct ieee80211_channel chan_before; |
1053 | 1035 | ||
1054 | assert_cfg80211_lock(); | ||
1055 | |||
1056 | sband = wiphy->bands[reg_beacon->chan.band]; | 1036 | sband = wiphy->bands[reg_beacon->chan.band]; |
1057 | chan = &sband->channels[chan_idx]; | 1037 | chan = &sband->channels[chan_idx]; |
1058 | 1038 | ||
@@ -1064,6 +1044,9 @@ static void handle_reg_beacon(struct wiphy *wiphy, | |||
1064 | 1044 | ||
1065 | chan->beacon_found = true; | 1045 | chan->beacon_found = true; |
1066 | 1046 | ||
1047 | if (!reg_is_world_roaming(wiphy)) | ||
1048 | return; | ||
1049 | |||
1067 | if (wiphy->flags & WIPHY_FLAG_DISABLE_BEACON_HINTS) | 1050 | if (wiphy->flags & WIPHY_FLAG_DISABLE_BEACON_HINTS) |
1068 | return; | 1051 | return; |
1069 | 1052 | ||
@@ -1094,8 +1077,6 @@ static void wiphy_update_new_beacon(struct wiphy *wiphy, | |||
1094 | unsigned int i; | 1077 | unsigned int i; |
1095 | struct ieee80211_supported_band *sband; | 1078 | struct ieee80211_supported_band *sband; |
1096 | 1079 | ||
1097 | assert_cfg80211_lock(); | ||
1098 | |||
1099 | if (!wiphy->bands[reg_beacon->chan.band]) | 1080 | if (!wiphy->bands[reg_beacon->chan.band]) |
1100 | return; | 1081 | return; |
1101 | 1082 | ||
@@ -1114,11 +1095,6 @@ static void wiphy_update_beacon_reg(struct wiphy *wiphy) | |||
1114 | struct ieee80211_supported_band *sband; | 1095 | struct ieee80211_supported_band *sband; |
1115 | struct reg_beacon *reg_beacon; | 1096 | struct reg_beacon *reg_beacon; |
1116 | 1097 | ||
1117 | assert_cfg80211_lock(); | ||
1118 | |||
1119 | if (list_empty(®_beacon_list)) | ||
1120 | return; | ||
1121 | |||
1122 | list_for_each_entry(reg_beacon, ®_beacon_list, list) { | 1098 | list_for_each_entry(reg_beacon, ®_beacon_list, list) { |
1123 | if (!wiphy->bands[reg_beacon->chan.band]) | 1099 | if (!wiphy->bands[reg_beacon->chan.band]) |
1124 | continue; | 1100 | continue; |
@@ -1128,18 +1104,6 @@ static void wiphy_update_beacon_reg(struct wiphy *wiphy) | |||
1128 | } | 1104 | } |
1129 | } | 1105 | } |
1130 | 1106 | ||
1131 | static bool reg_is_world_roaming(struct wiphy *wiphy) | ||
1132 | { | ||
1133 | if (is_world_regdom(cfg80211_regdomain->alpha2) || | ||
1134 | (wiphy->regd && is_world_regdom(wiphy->regd->alpha2))) | ||
1135 | return true; | ||
1136 | if (last_request && | ||
1137 | last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
1138 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) | ||
1139 | return true; | ||
1140 | return false; | ||
1141 | } | ||
1142 | |||
1143 | /* Reap the advantages of previously found beacons */ | 1107 | /* Reap the advantages of previously found beacons */ |
1144 | static void reg_process_beacons(struct wiphy *wiphy) | 1108 | static void reg_process_beacons(struct wiphy *wiphy) |
1145 | { | 1109 | { |
@@ -1149,39 +1113,29 @@ static void reg_process_beacons(struct wiphy *wiphy) | |||
1149 | */ | 1113 | */ |
1150 | if (!last_request) | 1114 | if (!last_request) |
1151 | return; | 1115 | return; |
1152 | if (!reg_is_world_roaming(wiphy)) | ||
1153 | return; | ||
1154 | wiphy_update_beacon_reg(wiphy); | 1116 | wiphy_update_beacon_reg(wiphy); |
1155 | } | 1117 | } |
1156 | 1118 | ||
1157 | static bool is_ht40_not_allowed(struct ieee80211_channel *chan) | 1119 | static bool is_ht40_allowed(struct ieee80211_channel *chan) |
1158 | { | 1120 | { |
1159 | if (!chan) | 1121 | if (!chan) |
1160 | return true; | 1122 | return false; |
1161 | if (chan->flags & IEEE80211_CHAN_DISABLED) | 1123 | if (chan->flags & IEEE80211_CHAN_DISABLED) |
1162 | return true; | 1124 | return false; |
1163 | /* This would happen when regulatory rules disallow HT40 completely */ | 1125 | /* This would happen when regulatory rules disallow HT40 completely */ |
1164 | if (IEEE80211_CHAN_NO_HT40 == (chan->flags & (IEEE80211_CHAN_NO_HT40))) | 1126 | if ((chan->flags & IEEE80211_CHAN_NO_HT40) == IEEE80211_CHAN_NO_HT40) |
1165 | return true; | 1127 | return false; |
1166 | return false; | 1128 | return true; |
1167 | } | 1129 | } |
1168 | 1130 | ||
1169 | static void reg_process_ht_flags_channel(struct wiphy *wiphy, | 1131 | static void reg_process_ht_flags_channel(struct wiphy *wiphy, |
1170 | enum ieee80211_band band, | 1132 | struct ieee80211_channel *channel) |
1171 | unsigned int chan_idx) | ||
1172 | { | 1133 | { |
1173 | struct ieee80211_supported_band *sband; | 1134 | struct ieee80211_supported_band *sband = wiphy->bands[channel->band]; |
1174 | struct ieee80211_channel *channel; | ||
1175 | struct ieee80211_channel *channel_before = NULL, *channel_after = NULL; | 1135 | struct ieee80211_channel *channel_before = NULL, *channel_after = NULL; |
1176 | unsigned int i; | 1136 | unsigned int i; |
1177 | 1137 | ||
1178 | assert_cfg80211_lock(); | 1138 | if (!is_ht40_allowed(channel)) { |
1179 | |||
1180 | sband = wiphy->bands[band]; | ||
1181 | BUG_ON(chan_idx >= sband->n_channels); | ||
1182 | channel = &sband->channels[chan_idx]; | ||
1183 | |||
1184 | if (is_ht40_not_allowed(channel)) { | ||
1185 | channel->flags |= IEEE80211_CHAN_NO_HT40; | 1139 | channel->flags |= IEEE80211_CHAN_NO_HT40; |
1186 | return; | 1140 | return; |
1187 | } | 1141 | } |
@@ -1192,6 +1146,7 @@ static void reg_process_ht_flags_channel(struct wiphy *wiphy, | |||
1192 | */ | 1146 | */ |
1193 | for (i = 0; i < sband->n_channels; i++) { | 1147 | for (i = 0; i < sband->n_channels; i++) { |
1194 | struct ieee80211_channel *c = &sband->channels[i]; | 1148 | struct ieee80211_channel *c = &sband->channels[i]; |
1149 | |||
1195 | if (c->center_freq == (channel->center_freq - 20)) | 1150 | if (c->center_freq == (channel->center_freq - 20)) |
1196 | channel_before = c; | 1151 | channel_before = c; |
1197 | if (c->center_freq == (channel->center_freq + 20)) | 1152 | if (c->center_freq == (channel->center_freq + 20)) |
@@ -1203,28 +1158,27 @@ static void reg_process_ht_flags_channel(struct wiphy *wiphy, | |||
1203 | * if that ever changes we also need to change the below logic | 1158 | * if that ever changes we also need to change the below logic |
1204 | * to include that as well. | 1159 | * to include that as well. |
1205 | */ | 1160 | */ |
1206 | if (is_ht40_not_allowed(channel_before)) | 1161 | if (!is_ht40_allowed(channel_before)) |
1207 | channel->flags |= IEEE80211_CHAN_NO_HT40MINUS; | 1162 | channel->flags |= IEEE80211_CHAN_NO_HT40MINUS; |
1208 | else | 1163 | else |
1209 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; | 1164 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; |
1210 | 1165 | ||
1211 | if (is_ht40_not_allowed(channel_after)) | 1166 | if (!is_ht40_allowed(channel_after)) |
1212 | channel->flags |= IEEE80211_CHAN_NO_HT40PLUS; | 1167 | channel->flags |= IEEE80211_CHAN_NO_HT40PLUS; |
1213 | else | 1168 | else |
1214 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; | 1169 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; |
1215 | } | 1170 | } |
1216 | 1171 | ||
1217 | static void reg_process_ht_flags_band(struct wiphy *wiphy, | 1172 | static void reg_process_ht_flags_band(struct wiphy *wiphy, |
1218 | enum ieee80211_band band) | 1173 | struct ieee80211_supported_band *sband) |
1219 | { | 1174 | { |
1220 | unsigned int i; | 1175 | unsigned int i; |
1221 | struct ieee80211_supported_band *sband; | ||
1222 | 1176 | ||
1223 | BUG_ON(!wiphy->bands[band]); | 1177 | if (!sband) |
1224 | sband = wiphy->bands[band]; | 1178 | return; |
1225 | 1179 | ||
1226 | for (i = 0; i < sband->n_channels; i++) | 1180 | for (i = 0; i < sband->n_channels; i++) |
1227 | reg_process_ht_flags_channel(wiphy, band, i); | 1181 | reg_process_ht_flags_channel(wiphy, &sband->channels[i]); |
1228 | } | 1182 | } |
1229 | 1183 | ||
1230 | static void reg_process_ht_flags(struct wiphy *wiphy) | 1184 | static void reg_process_ht_flags(struct wiphy *wiphy) |
@@ -1234,34 +1188,29 @@ static void reg_process_ht_flags(struct wiphy *wiphy) | |||
1234 | if (!wiphy) | 1188 | if (!wiphy) |
1235 | return; | 1189 | return; |
1236 | 1190 | ||
1237 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1191 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) |
1238 | if (wiphy->bands[band]) | 1192 | reg_process_ht_flags_band(wiphy, wiphy->bands[band]); |
1239 | reg_process_ht_flags_band(wiphy, band); | ||
1240 | } | ||
1241 | |||
1242 | } | 1193 | } |
1243 | 1194 | ||
1244 | static void wiphy_update_regulatory(struct wiphy *wiphy, | 1195 | static void wiphy_update_regulatory(struct wiphy *wiphy, |
1245 | enum nl80211_reg_initiator initiator) | 1196 | enum nl80211_reg_initiator initiator) |
1246 | { | 1197 | { |
1247 | enum ieee80211_band band; | 1198 | enum ieee80211_band band; |
1248 | 1199 | struct regulatory_request *lr = get_last_request(); | |
1249 | assert_reg_lock(); | ||
1250 | 1200 | ||
1251 | if (ignore_reg_update(wiphy, initiator)) | 1201 | if (ignore_reg_update(wiphy, initiator)) |
1252 | return; | 1202 | return; |
1253 | 1203 | ||
1254 | last_request->dfs_region = cfg80211_regdomain->dfs_region; | 1204 | lr->dfs_region = get_cfg80211_regdom()->dfs_region; |
1255 | 1205 | ||
1256 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1206 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) |
1257 | if (wiphy->bands[band]) | 1207 | handle_band(wiphy, initiator, wiphy->bands[band]); |
1258 | handle_band(wiphy, band, initiator); | ||
1259 | } | ||
1260 | 1208 | ||
1261 | reg_process_beacons(wiphy); | 1209 | reg_process_beacons(wiphy); |
1262 | reg_process_ht_flags(wiphy); | 1210 | reg_process_ht_flags(wiphy); |
1211 | |||
1263 | if (wiphy->reg_notifier) | 1212 | if (wiphy->reg_notifier) |
1264 | wiphy->reg_notifier(wiphy, last_request); | 1213 | wiphy->reg_notifier(wiphy, lr); |
1265 | } | 1214 | } |
1266 | 1215 | ||
1267 | static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) | 1216 | static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) |
@@ -1269,6 +1218,8 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) | |||
1269 | struct cfg80211_registered_device *rdev; | 1218 | struct cfg80211_registered_device *rdev; |
1270 | struct wiphy *wiphy; | 1219 | struct wiphy *wiphy; |
1271 | 1220 | ||
1221 | assert_cfg80211_lock(); | ||
1222 | |||
1272 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | 1223 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
1273 | wiphy = &rdev->wiphy; | 1224 | wiphy = &rdev->wiphy; |
1274 | wiphy_update_regulatory(wiphy, initiator); | 1225 | wiphy_update_regulatory(wiphy, initiator); |
@@ -1280,47 +1231,30 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) | |||
1280 | if (initiator == NL80211_REGDOM_SET_BY_CORE && | 1231 | if (initiator == NL80211_REGDOM_SET_BY_CORE && |
1281 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && | 1232 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && |
1282 | wiphy->reg_notifier) | 1233 | wiphy->reg_notifier) |
1283 | wiphy->reg_notifier(wiphy, last_request); | 1234 | wiphy->reg_notifier(wiphy, get_last_request()); |
1284 | } | 1235 | } |
1285 | } | 1236 | } |
1286 | 1237 | ||
1287 | static void handle_channel_custom(struct wiphy *wiphy, | 1238 | static void handle_channel_custom(struct wiphy *wiphy, |
1288 | enum ieee80211_band band, | 1239 | struct ieee80211_channel *chan, |
1289 | unsigned int chan_idx, | ||
1290 | const struct ieee80211_regdomain *regd) | 1240 | const struct ieee80211_regdomain *regd) |
1291 | { | 1241 | { |
1292 | int r; | ||
1293 | u32 desired_bw_khz = MHZ_TO_KHZ(20); | ||
1294 | u32 bw_flags = 0; | 1242 | u32 bw_flags = 0; |
1295 | const struct ieee80211_reg_rule *reg_rule = NULL; | 1243 | const struct ieee80211_reg_rule *reg_rule = NULL; |
1296 | const struct ieee80211_power_rule *power_rule = NULL; | 1244 | const struct ieee80211_power_rule *power_rule = NULL; |
1297 | const struct ieee80211_freq_range *freq_range = NULL; | 1245 | const struct ieee80211_freq_range *freq_range = NULL; |
1298 | struct ieee80211_supported_band *sband; | ||
1299 | struct ieee80211_channel *chan; | ||
1300 | |||
1301 | assert_reg_lock(); | ||
1302 | 1246 | ||
1303 | sband = wiphy->bands[band]; | 1247 | reg_rule = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), |
1304 | BUG_ON(chan_idx >= sband->n_channels); | 1248 | regd); |
1305 | chan = &sband->channels[chan_idx]; | ||
1306 | |||
1307 | r = freq_reg_info_regd(wiphy, | ||
1308 | MHZ_TO_KHZ(chan->center_freq), | ||
1309 | desired_bw_khz, | ||
1310 | ®_rule, | ||
1311 | regd); | ||
1312 | 1249 | ||
1313 | if (r) { | 1250 | if (IS_ERR(reg_rule)) { |
1314 | REG_DBG_PRINT("Disabling freq %d MHz as custom " | 1251 | REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n", |
1315 | "regd has no rule that fits a %d MHz " | 1252 | chan->center_freq); |
1316 | "wide channel\n", | ||
1317 | chan->center_freq, | ||
1318 | KHZ_TO_MHZ(desired_bw_khz)); | ||
1319 | chan->flags = IEEE80211_CHAN_DISABLED; | 1253 | chan->flags = IEEE80211_CHAN_DISABLED; |
1320 | return; | 1254 | return; |
1321 | } | 1255 | } |
1322 | 1256 | ||
1323 | chan_reg_rule_print_dbg(chan, desired_bw_khz, reg_rule); | 1257 | chan_reg_rule_print_dbg(chan, reg_rule); |
1324 | 1258 | ||
1325 | power_rule = ®_rule->power_rule; | 1259 | power_rule = ®_rule->power_rule; |
1326 | freq_range = ®_rule->freq_range; | 1260 | freq_range = ®_rule->freq_range; |
@@ -1334,17 +1268,17 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
1334 | (int) MBM_TO_DBM(power_rule->max_eirp); | 1268 | (int) MBM_TO_DBM(power_rule->max_eirp); |
1335 | } | 1269 | } |
1336 | 1270 | ||
1337 | static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, | 1271 | static void handle_band_custom(struct wiphy *wiphy, |
1272 | struct ieee80211_supported_band *sband, | ||
1338 | const struct ieee80211_regdomain *regd) | 1273 | const struct ieee80211_regdomain *regd) |
1339 | { | 1274 | { |
1340 | unsigned int i; | 1275 | unsigned int i; |
1341 | struct ieee80211_supported_band *sband; | ||
1342 | 1276 | ||
1343 | BUG_ON(!wiphy->bands[band]); | 1277 | if (!sband) |
1344 | sband = wiphy->bands[band]; | 1278 | return; |
1345 | 1279 | ||
1346 | for (i = 0; i < sband->n_channels; i++) | 1280 | for (i = 0; i < sband->n_channels; i++) |
1347 | handle_channel_custom(wiphy, band, i, regd); | 1281 | handle_channel_custom(wiphy, &sband->channels[i], regd); |
1348 | } | 1282 | } |
1349 | 1283 | ||
1350 | /* Used by drivers prior to wiphy registration */ | 1284 | /* Used by drivers prior to wiphy registration */ |
@@ -1354,60 +1288,50 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, | |||
1354 | enum ieee80211_band band; | 1288 | enum ieee80211_band band; |
1355 | unsigned int bands_set = 0; | 1289 | unsigned int bands_set = 0; |
1356 | 1290 | ||
1357 | mutex_lock(®_mutex); | ||
1358 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1291 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
1359 | if (!wiphy->bands[band]) | 1292 | if (!wiphy->bands[band]) |
1360 | continue; | 1293 | continue; |
1361 | handle_band_custom(wiphy, band, regd); | 1294 | handle_band_custom(wiphy, wiphy->bands[band], regd); |
1362 | bands_set++; | 1295 | bands_set++; |
1363 | } | 1296 | } |
1364 | mutex_unlock(®_mutex); | ||
1365 | 1297 | ||
1366 | /* | 1298 | /* |
1367 | * no point in calling this if it won't have any effect | 1299 | * no point in calling this if it won't have any effect |
1368 | * on your device's supportd bands. | 1300 | * on your device's supported bands. |
1369 | */ | 1301 | */ |
1370 | WARN_ON(!bands_set); | 1302 | WARN_ON(!bands_set); |
1371 | } | 1303 | } |
1372 | EXPORT_SYMBOL(wiphy_apply_custom_regulatory); | 1304 | EXPORT_SYMBOL(wiphy_apply_custom_regulatory); |
1373 | 1305 | ||
1374 | /* | ||
1375 | * Return value which can be used by ignore_request() to indicate | ||
1376 | * it has been determined we should intersect two regulatory domains | ||
1377 | */ | ||
1378 | #define REG_INTERSECT 1 | ||
1379 | |||
1380 | /* This has the logic which determines when a new request | 1306 | /* This has the logic which determines when a new request |
1381 | * should be ignored. */ | 1307 | * should be ignored. */ |
1382 | static int ignore_request(struct wiphy *wiphy, | 1308 | static enum reg_request_treatment |
1309 | get_reg_request_treatment(struct wiphy *wiphy, | ||
1383 | struct regulatory_request *pending_request) | 1310 | struct regulatory_request *pending_request) |
1384 | { | 1311 | { |
1385 | struct wiphy *last_wiphy = NULL; | 1312 | struct wiphy *last_wiphy = NULL; |
1386 | 1313 | struct regulatory_request *lr = get_last_request(); | |
1387 | assert_cfg80211_lock(); | ||
1388 | 1314 | ||
1389 | /* All initial requests are respected */ | 1315 | /* All initial requests are respected */ |
1390 | if (!last_request) | 1316 | if (!lr) |
1391 | return 0; | 1317 | return REG_REQ_OK; |
1392 | 1318 | ||
1393 | switch (pending_request->initiator) { | 1319 | switch (pending_request->initiator) { |
1394 | case NL80211_REGDOM_SET_BY_CORE: | 1320 | case NL80211_REGDOM_SET_BY_CORE: |
1395 | return 0; | 1321 | return REG_REQ_OK; |
1396 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 1322 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
1397 | 1323 | if (reg_request_cell_base(lr)) { | |
1398 | if (reg_request_cell_base(last_request)) { | ||
1399 | /* Trust a Cell base station over the AP's country IE */ | 1324 | /* Trust a Cell base station over the AP's country IE */ |
1400 | if (regdom_changes(pending_request->alpha2)) | 1325 | if (regdom_changes(pending_request->alpha2)) |
1401 | return -EOPNOTSUPP; | 1326 | return REG_REQ_IGNORE; |
1402 | return -EALREADY; | 1327 | return REG_REQ_ALREADY_SET; |
1403 | } | 1328 | } |
1404 | 1329 | ||
1405 | last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); | 1330 | last_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); |
1406 | 1331 | ||
1407 | if (unlikely(!is_an_alpha2(pending_request->alpha2))) | 1332 | if (unlikely(!is_an_alpha2(pending_request->alpha2))) |
1408 | return -EINVAL; | 1333 | return -EINVAL; |
1409 | if (last_request->initiator == | 1334 | if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
1410 | NL80211_REGDOM_SET_BY_COUNTRY_IE) { | ||
1411 | if (last_wiphy != wiphy) { | 1335 | if (last_wiphy != wiphy) { |
1412 | /* | 1336 | /* |
1413 | * Two cards with two APs claiming different | 1337 | * Two cards with two APs claiming different |
@@ -1416,23 +1340,23 @@ static int ignore_request(struct wiphy *wiphy, | |||
1416 | * to be correct. Reject second one for now. | 1340 | * to be correct. Reject second one for now. |
1417 | */ | 1341 | */ |
1418 | if (regdom_changes(pending_request->alpha2)) | 1342 | if (regdom_changes(pending_request->alpha2)) |
1419 | return -EOPNOTSUPP; | 1343 | return REG_REQ_IGNORE; |
1420 | return -EALREADY; | 1344 | return REG_REQ_ALREADY_SET; |
1421 | } | 1345 | } |
1422 | /* | 1346 | /* |
1423 | * Two consecutive Country IE hints on the same wiphy. | 1347 | * Two consecutive Country IE hints on the same wiphy. |
1424 | * This should be picked up early by the driver/stack | 1348 | * This should be picked up early by the driver/stack |
1425 | */ | 1349 | */ |
1426 | if (WARN_ON(regdom_changes(pending_request->alpha2))) | 1350 | if (WARN_ON(regdom_changes(pending_request->alpha2))) |
1427 | return 0; | 1351 | return REG_REQ_OK; |
1428 | return -EALREADY; | 1352 | return REG_REQ_ALREADY_SET; |
1429 | } | 1353 | } |
1430 | return 0; | 1354 | return 0; |
1431 | case NL80211_REGDOM_SET_BY_DRIVER: | 1355 | case NL80211_REGDOM_SET_BY_DRIVER: |
1432 | if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) { | 1356 | if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) { |
1433 | if (regdom_changes(pending_request->alpha2)) | 1357 | if (regdom_changes(pending_request->alpha2)) |
1434 | return 0; | 1358 | return REG_REQ_OK; |
1435 | return -EALREADY; | 1359 | return REG_REQ_ALREADY_SET; |
1436 | } | 1360 | } |
1437 | 1361 | ||
1438 | /* | 1362 | /* |
@@ -1440,59 +1364,59 @@ static int ignore_request(struct wiphy *wiphy, | |||
1440 | * back in or if you add a new device for which the previously | 1364 | * back in or if you add a new device for which the previously |
1441 | * loaded card also agrees on the regulatory domain. | 1365 | * loaded card also agrees on the regulatory domain. |
1442 | */ | 1366 | */ |
1443 | if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && | 1367 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
1444 | !regdom_changes(pending_request->alpha2)) | 1368 | !regdom_changes(pending_request->alpha2)) |
1445 | return -EALREADY; | 1369 | return REG_REQ_ALREADY_SET; |
1446 | 1370 | ||
1447 | return REG_INTERSECT; | 1371 | return REG_REQ_INTERSECT; |
1448 | case NL80211_REGDOM_SET_BY_USER: | 1372 | case NL80211_REGDOM_SET_BY_USER: |
1449 | if (reg_request_cell_base(pending_request)) | 1373 | if (reg_request_cell_base(pending_request)) |
1450 | return reg_ignore_cell_hint(pending_request); | 1374 | return reg_ignore_cell_hint(pending_request); |
1451 | 1375 | ||
1452 | if (reg_request_cell_base(last_request)) | 1376 | if (reg_request_cell_base(lr)) |
1453 | return -EOPNOTSUPP; | 1377 | return REG_REQ_IGNORE; |
1454 | 1378 | ||
1455 | if (last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) | 1379 | if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) |
1456 | return REG_INTERSECT; | 1380 | return REG_REQ_INTERSECT; |
1457 | /* | 1381 | /* |
1458 | * If the user knows better the user should set the regdom | 1382 | * If the user knows better the user should set the regdom |
1459 | * to their country before the IE is picked up | 1383 | * to their country before the IE is picked up |
1460 | */ | 1384 | */ |
1461 | if (last_request->initiator == NL80211_REGDOM_SET_BY_USER && | 1385 | if (lr->initiator == NL80211_REGDOM_SET_BY_USER && |
1462 | last_request->intersect) | 1386 | lr->intersect) |
1463 | return -EOPNOTSUPP; | 1387 | return REG_REQ_IGNORE; |
1464 | /* | 1388 | /* |
1465 | * Process user requests only after previous user/driver/core | 1389 | * Process user requests only after previous user/driver/core |
1466 | * requests have been processed | 1390 | * requests have been processed |
1467 | */ | 1391 | */ |
1468 | if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE || | 1392 | if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE || |
1469 | last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER || | 1393 | lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || |
1470 | last_request->initiator == NL80211_REGDOM_SET_BY_USER) { | 1394 | lr->initiator == NL80211_REGDOM_SET_BY_USER) && |
1471 | if (regdom_changes(last_request->alpha2)) | 1395 | regdom_changes(lr->alpha2)) |
1472 | return -EAGAIN; | 1396 | return REG_REQ_IGNORE; |
1473 | } | ||
1474 | 1397 | ||
1475 | if (!regdom_changes(pending_request->alpha2)) | 1398 | if (!regdom_changes(pending_request->alpha2)) |
1476 | return -EALREADY; | 1399 | return REG_REQ_ALREADY_SET; |
1477 | 1400 | ||
1478 | return 0; | 1401 | return REG_REQ_OK; |
1479 | } | 1402 | } |
1480 | 1403 | ||
1481 | return -EINVAL; | 1404 | return REG_REQ_IGNORE; |
1482 | } | 1405 | } |
1483 | 1406 | ||
1484 | static void reg_set_request_processed(void) | 1407 | static void reg_set_request_processed(void) |
1485 | { | 1408 | { |
1486 | bool need_more_processing = false; | 1409 | bool need_more_processing = false; |
1410 | struct regulatory_request *lr = get_last_request(); | ||
1487 | 1411 | ||
1488 | last_request->processed = true; | 1412 | lr->processed = true; |
1489 | 1413 | ||
1490 | spin_lock(®_requests_lock); | 1414 | spin_lock(®_requests_lock); |
1491 | if (!list_empty(®_requests_list)) | 1415 | if (!list_empty(®_requests_list)) |
1492 | need_more_processing = true; | 1416 | need_more_processing = true; |
1493 | spin_unlock(®_requests_lock); | 1417 | spin_unlock(®_requests_lock); |
1494 | 1418 | ||
1495 | if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) | 1419 | if (lr->initiator == NL80211_REGDOM_SET_BY_USER) |
1496 | cancel_delayed_work(®_timeout); | 1420 | cancel_delayed_work(®_timeout); |
1497 | 1421 | ||
1498 | if (need_more_processing) | 1422 | if (need_more_processing) |
@@ -1508,116 +1432,122 @@ static void reg_set_request_processed(void) | |||
1508 | * The Wireless subsystem can use this function to hint to the wireless core | 1432 | * The Wireless subsystem can use this function to hint to the wireless core |
1509 | * what it believes should be the current regulatory domain. | 1433 | * what it believes should be the current regulatory domain. |
1510 | * | 1434 | * |
1511 | * Returns zero if all went fine, %-EALREADY if a regulatory domain had | 1435 | * Returns one of the different reg request treatment values. |
1512 | * already been set or other standard error codes. | ||
1513 | * | 1436 | * |
1514 | * Caller must hold &cfg80211_mutex and ®_mutex | 1437 | * Caller must hold ®_mutex |
1515 | */ | 1438 | */ |
1516 | static int __regulatory_hint(struct wiphy *wiphy, | 1439 | static enum reg_request_treatment |
1517 | struct regulatory_request *pending_request) | 1440 | __regulatory_hint(struct wiphy *wiphy, |
1441 | struct regulatory_request *pending_request) | ||
1518 | { | 1442 | { |
1443 | const struct ieee80211_regdomain *regd; | ||
1519 | bool intersect = false; | 1444 | bool intersect = false; |
1520 | int r = 0; | 1445 | enum reg_request_treatment treatment; |
1521 | 1446 | struct regulatory_request *lr; | |
1522 | assert_cfg80211_lock(); | ||
1523 | 1447 | ||
1524 | r = ignore_request(wiphy, pending_request); | 1448 | treatment = get_reg_request_treatment(wiphy, pending_request); |
1525 | 1449 | ||
1526 | if (r == REG_INTERSECT) { | 1450 | switch (treatment) { |
1451 | case REG_REQ_INTERSECT: | ||
1527 | if (pending_request->initiator == | 1452 | if (pending_request->initiator == |
1528 | NL80211_REGDOM_SET_BY_DRIVER) { | 1453 | NL80211_REGDOM_SET_BY_DRIVER) { |
1529 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); | 1454 | regd = reg_copy_regd(get_cfg80211_regdom()); |
1530 | if (r) { | 1455 | if (IS_ERR(regd)) { |
1531 | kfree(pending_request); | 1456 | kfree(pending_request); |
1532 | return r; | 1457 | return PTR_ERR(regd); |
1533 | } | 1458 | } |
1459 | rcu_assign_pointer(wiphy->regd, regd); | ||
1534 | } | 1460 | } |
1535 | intersect = true; | 1461 | intersect = true; |
1536 | } else if (r) { | 1462 | break; |
1463 | case REG_REQ_OK: | ||
1464 | break; | ||
1465 | default: | ||
1537 | /* | 1466 | /* |
1538 | * If the regulatory domain being requested by the | 1467 | * If the regulatory domain being requested by the |
1539 | * driver has already been set just copy it to the | 1468 | * driver has already been set just copy it to the |
1540 | * wiphy | 1469 | * wiphy |
1541 | */ | 1470 | */ |
1542 | if (r == -EALREADY && | 1471 | if (treatment == REG_REQ_ALREADY_SET && |
1543 | pending_request->initiator == | 1472 | pending_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) { |
1544 | NL80211_REGDOM_SET_BY_DRIVER) { | 1473 | regd = reg_copy_regd(get_cfg80211_regdom()); |
1545 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); | 1474 | if (IS_ERR(regd)) { |
1546 | if (r) { | ||
1547 | kfree(pending_request); | 1475 | kfree(pending_request); |
1548 | return r; | 1476 | return REG_REQ_IGNORE; |
1549 | } | 1477 | } |
1550 | r = -EALREADY; | 1478 | treatment = REG_REQ_ALREADY_SET; |
1479 | rcu_assign_pointer(wiphy->regd, regd); | ||
1551 | goto new_request; | 1480 | goto new_request; |
1552 | } | 1481 | } |
1553 | kfree(pending_request); | 1482 | kfree(pending_request); |
1554 | return r; | 1483 | return treatment; |
1555 | } | 1484 | } |
1556 | 1485 | ||
1557 | new_request: | 1486 | new_request: |
1558 | if (last_request != &core_request_world) | 1487 | lr = get_last_request(); |
1559 | kfree(last_request); | 1488 | if (lr != &core_request_world && lr) |
1489 | kfree_rcu(lr, rcu_head); | ||
1560 | 1490 | ||
1561 | last_request = pending_request; | 1491 | pending_request->intersect = intersect; |
1562 | last_request->intersect = intersect; | 1492 | pending_request->processed = false; |
1493 | rcu_assign_pointer(last_request, pending_request); | ||
1494 | lr = pending_request; | ||
1563 | 1495 | ||
1564 | pending_request = NULL; | 1496 | pending_request = NULL; |
1565 | 1497 | ||
1566 | if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) { | 1498 | if (lr->initiator == NL80211_REGDOM_SET_BY_USER) { |
1567 | user_alpha2[0] = last_request->alpha2[0]; | 1499 | user_alpha2[0] = lr->alpha2[0]; |
1568 | user_alpha2[1] = last_request->alpha2[1]; | 1500 | user_alpha2[1] = lr->alpha2[1]; |
1569 | } | 1501 | } |
1570 | 1502 | ||
1571 | /* When r == REG_INTERSECT we do need to call CRDA */ | 1503 | /* When r == REG_REQ_INTERSECT we do need to call CRDA */ |
1572 | if (r < 0) { | 1504 | if (treatment != REG_REQ_OK && treatment != REG_REQ_INTERSECT) { |
1573 | /* | 1505 | /* |
1574 | * Since CRDA will not be called in this case as we already | 1506 | * Since CRDA will not be called in this case as we already |
1575 | * have applied the requested regulatory domain before we just | 1507 | * have applied the requested regulatory domain before we just |
1576 | * inform userspace we have processed the request | 1508 | * inform userspace we have processed the request |
1577 | */ | 1509 | */ |
1578 | if (r == -EALREADY) { | 1510 | if (treatment == REG_REQ_ALREADY_SET) { |
1579 | nl80211_send_reg_change_event(last_request); | 1511 | nl80211_send_reg_change_event(lr); |
1580 | reg_set_request_processed(); | 1512 | reg_set_request_processed(); |
1581 | } | 1513 | } |
1582 | return r; | 1514 | return treatment; |
1583 | } | 1515 | } |
1584 | 1516 | ||
1585 | return call_crda(last_request->alpha2); | 1517 | if (call_crda(lr->alpha2)) |
1518 | return REG_REQ_IGNORE; | ||
1519 | return REG_REQ_OK; | ||
1586 | } | 1520 | } |
1587 | 1521 | ||
1588 | /* This processes *all* regulatory hints */ | 1522 | /* This processes *all* regulatory hints */ |
1589 | static void reg_process_hint(struct regulatory_request *reg_request, | 1523 | static void reg_process_hint(struct regulatory_request *reg_request, |
1590 | enum nl80211_reg_initiator reg_initiator) | 1524 | enum nl80211_reg_initiator reg_initiator) |
1591 | { | 1525 | { |
1592 | int r = 0; | ||
1593 | struct wiphy *wiphy = NULL; | 1526 | struct wiphy *wiphy = NULL; |
1594 | 1527 | ||
1595 | BUG_ON(!reg_request->alpha2); | 1528 | if (WARN_ON(!reg_request->alpha2)) |
1529 | return; | ||
1596 | 1530 | ||
1597 | if (wiphy_idx_valid(reg_request->wiphy_idx)) | 1531 | if (reg_request->wiphy_idx != WIPHY_IDX_INVALID) |
1598 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); | 1532 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); |
1599 | 1533 | ||
1600 | if (reg_initiator == NL80211_REGDOM_SET_BY_DRIVER && | 1534 | if (reg_initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) { |
1601 | !wiphy) { | ||
1602 | kfree(reg_request); | 1535 | kfree(reg_request); |
1603 | return; | 1536 | return; |
1604 | } | 1537 | } |
1605 | 1538 | ||
1606 | r = __regulatory_hint(wiphy, reg_request); | 1539 | switch (__regulatory_hint(wiphy, reg_request)) { |
1607 | /* This is required so that the orig_* parameters are saved */ | 1540 | case REG_REQ_ALREADY_SET: |
1608 | if (r == -EALREADY && wiphy && | 1541 | /* This is required so that the orig_* parameters are saved */ |
1609 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { | 1542 | if (wiphy && wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) |
1610 | wiphy_update_regulatory(wiphy, reg_initiator); | 1543 | wiphy_update_regulatory(wiphy, reg_initiator); |
1611 | return; | 1544 | break; |
1545 | default: | ||
1546 | if (reg_initiator == NL80211_REGDOM_SET_BY_USER) | ||
1547 | schedule_delayed_work(®_timeout, | ||
1548 | msecs_to_jiffies(3142)); | ||
1549 | break; | ||
1612 | } | 1550 | } |
1613 | |||
1614 | /* | ||
1615 | * We only time out user hints, given that they should be the only | ||
1616 | * source of bogus requests. | ||
1617 | */ | ||
1618 | if (r != -EALREADY && | ||
1619 | reg_initiator == NL80211_REGDOM_SET_BY_USER) | ||
1620 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); | ||
1621 | } | 1551 | } |
1622 | 1552 | ||
1623 | /* | 1553 | /* |
@@ -1627,15 +1557,15 @@ static void reg_process_hint(struct regulatory_request *reg_request, | |||
1627 | */ | 1557 | */ |
1628 | static void reg_process_pending_hints(void) | 1558 | static void reg_process_pending_hints(void) |
1629 | { | 1559 | { |
1630 | struct regulatory_request *reg_request; | 1560 | struct regulatory_request *reg_request, *lr; |
1631 | 1561 | ||
1632 | mutex_lock(&cfg80211_mutex); | 1562 | mutex_lock(&cfg80211_mutex); |
1633 | mutex_lock(®_mutex); | 1563 | mutex_lock(®_mutex); |
1564 | lr = get_last_request(); | ||
1634 | 1565 | ||
1635 | /* When last_request->processed becomes true this will be rescheduled */ | 1566 | /* When last_request->processed becomes true this will be rescheduled */ |
1636 | if (last_request && !last_request->processed) { | 1567 | if (lr && !lr->processed) { |
1637 | REG_DBG_PRINT("Pending regulatory request, waiting " | 1568 | REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n"); |
1638 | "for it to be processed...\n"); | ||
1639 | goto out; | 1569 | goto out; |
1640 | } | 1570 | } |
1641 | 1571 | ||
@@ -1666,23 +1596,14 @@ static void reg_process_pending_beacon_hints(void) | |||
1666 | struct cfg80211_registered_device *rdev; | 1596 | struct cfg80211_registered_device *rdev; |
1667 | struct reg_beacon *pending_beacon, *tmp; | 1597 | struct reg_beacon *pending_beacon, *tmp; |
1668 | 1598 | ||
1669 | /* | ||
1670 | * No need to hold the reg_mutex here as we just touch wiphys | ||
1671 | * and do not read or access regulatory variables. | ||
1672 | */ | ||
1673 | mutex_lock(&cfg80211_mutex); | 1599 | mutex_lock(&cfg80211_mutex); |
1600 | mutex_lock(®_mutex); | ||
1674 | 1601 | ||
1675 | /* This goes through the _pending_ beacon list */ | 1602 | /* This goes through the _pending_ beacon list */ |
1676 | spin_lock_bh(®_pending_beacons_lock); | 1603 | spin_lock_bh(®_pending_beacons_lock); |
1677 | 1604 | ||
1678 | if (list_empty(®_pending_beacons)) { | ||
1679 | spin_unlock_bh(®_pending_beacons_lock); | ||
1680 | goto out; | ||
1681 | } | ||
1682 | |||
1683 | list_for_each_entry_safe(pending_beacon, tmp, | 1605 | list_for_each_entry_safe(pending_beacon, tmp, |
1684 | ®_pending_beacons, list) { | 1606 | ®_pending_beacons, list) { |
1685 | |||
1686 | list_del_init(&pending_beacon->list); | 1607 | list_del_init(&pending_beacon->list); |
1687 | 1608 | ||
1688 | /* Applies the beacon hint to current wiphys */ | 1609 | /* Applies the beacon hint to current wiphys */ |
@@ -1694,7 +1615,7 @@ static void reg_process_pending_beacon_hints(void) | |||
1694 | } | 1615 | } |
1695 | 1616 | ||
1696 | spin_unlock_bh(®_pending_beacons_lock); | 1617 | spin_unlock_bh(®_pending_beacons_lock); |
1697 | out: | 1618 | mutex_unlock(®_mutex); |
1698 | mutex_unlock(&cfg80211_mutex); | 1619 | mutex_unlock(&cfg80211_mutex); |
1699 | } | 1620 | } |
1700 | 1621 | ||
@@ -1706,10 +1627,8 @@ static void reg_todo(struct work_struct *work) | |||
1706 | 1627 | ||
1707 | static void queue_regulatory_request(struct regulatory_request *request) | 1628 | static void queue_regulatory_request(struct regulatory_request *request) |
1708 | { | 1629 | { |
1709 | if (isalpha(request->alpha2[0])) | 1630 | request->alpha2[0] = toupper(request->alpha2[0]); |
1710 | request->alpha2[0] = toupper(request->alpha2[0]); | 1631 | request->alpha2[1] = toupper(request->alpha2[1]); |
1711 | if (isalpha(request->alpha2[1])) | ||
1712 | request->alpha2[1] = toupper(request->alpha2[1]); | ||
1713 | 1632 | ||
1714 | spin_lock(®_requests_lock); | 1633 | spin_lock(®_requests_lock); |
1715 | list_add_tail(&request->list, ®_requests_list); | 1634 | list_add_tail(&request->list, ®_requests_list); |
@@ -1726,8 +1645,7 @@ static int regulatory_hint_core(const char *alpha2) | |||
1726 | { | 1645 | { |
1727 | struct regulatory_request *request; | 1646 | struct regulatory_request *request; |
1728 | 1647 | ||
1729 | request = kzalloc(sizeof(struct regulatory_request), | 1648 | request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); |
1730 | GFP_KERNEL); | ||
1731 | if (!request) | 1649 | if (!request) |
1732 | return -ENOMEM; | 1650 | return -ENOMEM; |
1733 | 1651 | ||
@@ -1746,13 +1664,14 @@ int regulatory_hint_user(const char *alpha2, | |||
1746 | { | 1664 | { |
1747 | struct regulatory_request *request; | 1665 | struct regulatory_request *request; |
1748 | 1666 | ||
1749 | BUG_ON(!alpha2); | 1667 | if (WARN_ON(!alpha2)) |
1668 | return -EINVAL; | ||
1750 | 1669 | ||
1751 | request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); | 1670 | request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); |
1752 | if (!request) | 1671 | if (!request) |
1753 | return -ENOMEM; | 1672 | return -ENOMEM; |
1754 | 1673 | ||
1755 | request->wiphy_idx = WIPHY_IDX_STALE; | 1674 | request->wiphy_idx = WIPHY_IDX_INVALID; |
1756 | request->alpha2[0] = alpha2[0]; | 1675 | request->alpha2[0] = alpha2[0]; |
1757 | request->alpha2[1] = alpha2[1]; | 1676 | request->alpha2[1] = alpha2[1]; |
1758 | request->initiator = NL80211_REGDOM_SET_BY_USER; | 1677 | request->initiator = NL80211_REGDOM_SET_BY_USER; |
@@ -1768,8 +1687,8 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
1768 | { | 1687 | { |
1769 | struct regulatory_request *request; | 1688 | struct regulatory_request *request; |
1770 | 1689 | ||
1771 | BUG_ON(!alpha2); | 1690 | if (WARN_ON(!alpha2 || !wiphy)) |
1772 | BUG_ON(!wiphy); | 1691 | return -EINVAL; |
1773 | 1692 | ||
1774 | request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); | 1693 | request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); |
1775 | if (!request) | 1694 | if (!request) |
@@ -1777,9 +1696,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
1777 | 1696 | ||
1778 | request->wiphy_idx = get_wiphy_idx(wiphy); | 1697 | request->wiphy_idx = get_wiphy_idx(wiphy); |
1779 | 1698 | ||
1780 | /* Must have registered wiphy first */ | ||
1781 | BUG_ON(!wiphy_idx_valid(request->wiphy_idx)); | ||
1782 | |||
1783 | request->alpha2[0] = alpha2[0]; | 1699 | request->alpha2[0] = alpha2[0]; |
1784 | request->alpha2[1] = alpha2[1]; | 1700 | request->alpha2[1] = alpha2[1]; |
1785 | request->initiator = NL80211_REGDOM_SET_BY_DRIVER; | 1701 | request->initiator = NL80211_REGDOM_SET_BY_DRIVER; |
@@ -1794,18 +1710,17 @@ EXPORT_SYMBOL(regulatory_hint); | |||
1794 | * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and | 1710 | * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and |
1795 | * therefore cannot iterate over the rdev list here. | 1711 | * therefore cannot iterate over the rdev list here. |
1796 | */ | 1712 | */ |
1797 | void regulatory_hint_11d(struct wiphy *wiphy, | 1713 | void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, |
1798 | enum ieee80211_band band, | 1714 | const u8 *country_ie, u8 country_ie_len) |
1799 | const u8 *country_ie, | ||
1800 | u8 country_ie_len) | ||
1801 | { | 1715 | { |
1802 | char alpha2[2]; | 1716 | char alpha2[2]; |
1803 | enum environment_cap env = ENVIRON_ANY; | 1717 | enum environment_cap env = ENVIRON_ANY; |
1804 | struct regulatory_request *request; | 1718 | struct regulatory_request *request, *lr; |
1805 | 1719 | ||
1806 | mutex_lock(®_mutex); | 1720 | mutex_lock(®_mutex); |
1721 | lr = get_last_request(); | ||
1807 | 1722 | ||
1808 | if (unlikely(!last_request)) | 1723 | if (unlikely(!lr)) |
1809 | goto out; | 1724 | goto out; |
1810 | 1725 | ||
1811 | /* IE len must be evenly divisible by 2 */ | 1726 | /* IE len must be evenly divisible by 2 */ |
@@ -1828,9 +1743,8 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
1828 | * We leave conflict resolution to the workqueue, where can hold | 1743 | * We leave conflict resolution to the workqueue, where can hold |
1829 | * cfg80211_mutex. | 1744 | * cfg80211_mutex. |
1830 | */ | 1745 | */ |
1831 | if (likely(last_request->initiator == | 1746 | if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && |
1832 | NL80211_REGDOM_SET_BY_COUNTRY_IE && | 1747 | lr->wiphy_idx != WIPHY_IDX_INVALID) |
1833 | wiphy_idx_valid(last_request->wiphy_idx))) | ||
1834 | goto out; | 1748 | goto out; |
1835 | 1749 | ||
1836 | request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); | 1750 | request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); |
@@ -1843,12 +1757,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
1843 | request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; | 1757 | request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; |
1844 | request->country_ie_env = env; | 1758 | request->country_ie_env = env; |
1845 | 1759 | ||
1846 | mutex_unlock(®_mutex); | ||
1847 | |||
1848 | queue_regulatory_request(request); | 1760 | queue_regulatory_request(request); |
1849 | |||
1850 | return; | ||
1851 | |||
1852 | out: | 1761 | out: |
1853 | mutex_unlock(®_mutex); | 1762 | mutex_unlock(®_mutex); |
1854 | } | 1763 | } |
@@ -1863,8 +1772,7 @@ static void restore_alpha2(char *alpha2, bool reset_user) | |||
1863 | if (is_user_regdom_saved()) { | 1772 | if (is_user_regdom_saved()) { |
1864 | /* Unless we're asked to ignore it and reset it */ | 1773 | /* Unless we're asked to ignore it and reset it */ |
1865 | if (reset_user) { | 1774 | if (reset_user) { |
1866 | REG_DBG_PRINT("Restoring regulatory settings " | 1775 | REG_DBG_PRINT("Restoring regulatory settings including user preference\n"); |
1867 | "including user preference\n"); | ||
1868 | user_alpha2[0] = '9'; | 1776 | user_alpha2[0] = '9'; |
1869 | user_alpha2[1] = '7'; | 1777 | user_alpha2[1] = '7'; |
1870 | 1778 | ||
@@ -1874,26 +1782,20 @@ static void restore_alpha2(char *alpha2, bool reset_user) | |||
1874 | * back as they were for a full restore. | 1782 | * back as they were for a full restore. |
1875 | */ | 1783 | */ |
1876 | if (!is_world_regdom(ieee80211_regdom)) { | 1784 | if (!is_world_regdom(ieee80211_regdom)) { |
1877 | REG_DBG_PRINT("Keeping preference on " | 1785 | REG_DBG_PRINT("Keeping preference on module parameter ieee80211_regdom: %c%c\n", |
1878 | "module parameter ieee80211_regdom: %c%c\n", | 1786 | ieee80211_regdom[0], ieee80211_regdom[1]); |
1879 | ieee80211_regdom[0], | ||
1880 | ieee80211_regdom[1]); | ||
1881 | alpha2[0] = ieee80211_regdom[0]; | 1787 | alpha2[0] = ieee80211_regdom[0]; |
1882 | alpha2[1] = ieee80211_regdom[1]; | 1788 | alpha2[1] = ieee80211_regdom[1]; |
1883 | } | 1789 | } |
1884 | } else { | 1790 | } else { |
1885 | REG_DBG_PRINT("Restoring regulatory settings " | 1791 | REG_DBG_PRINT("Restoring regulatory settings while preserving user preference for: %c%c\n", |
1886 | "while preserving user preference for: %c%c\n", | 1792 | user_alpha2[0], user_alpha2[1]); |
1887 | user_alpha2[0], | ||
1888 | user_alpha2[1]); | ||
1889 | alpha2[0] = user_alpha2[0]; | 1793 | alpha2[0] = user_alpha2[0]; |
1890 | alpha2[1] = user_alpha2[1]; | 1794 | alpha2[1] = user_alpha2[1]; |
1891 | } | 1795 | } |
1892 | } else if (!is_world_regdom(ieee80211_regdom)) { | 1796 | } else if (!is_world_regdom(ieee80211_regdom)) { |
1893 | REG_DBG_PRINT("Keeping preference on " | 1797 | REG_DBG_PRINT("Keeping preference on module parameter ieee80211_regdom: %c%c\n", |
1894 | "module parameter ieee80211_regdom: %c%c\n", | 1798 | ieee80211_regdom[0], ieee80211_regdom[1]); |
1895 | ieee80211_regdom[0], | ||
1896 | ieee80211_regdom[1]); | ||
1897 | alpha2[0] = ieee80211_regdom[0]; | 1799 | alpha2[0] = ieee80211_regdom[0]; |
1898 | alpha2[1] = ieee80211_regdom[1]; | 1800 | alpha2[1] = ieee80211_regdom[1]; |
1899 | } else | 1801 | } else |
@@ -1948,7 +1850,7 @@ static void restore_regulatory_settings(bool reset_user) | |||
1948 | mutex_lock(&cfg80211_mutex); | 1850 | mutex_lock(&cfg80211_mutex); |
1949 | mutex_lock(®_mutex); | 1851 | mutex_lock(®_mutex); |
1950 | 1852 | ||
1951 | reset_regdomains(true); | 1853 | reset_regdomains(true, &world_regdom); |
1952 | restore_alpha2(alpha2, reset_user); | 1854 | restore_alpha2(alpha2, reset_user); |
1953 | 1855 | ||
1954 | /* | 1856 | /* |
@@ -1958,49 +1860,35 @@ static void restore_regulatory_settings(bool reset_user) | |||
1958 | * settings. | 1860 | * settings. |
1959 | */ | 1861 | */ |
1960 | spin_lock(®_requests_lock); | 1862 | spin_lock(®_requests_lock); |
1961 | if (!list_empty(®_requests_list)) { | 1863 | list_for_each_entry_safe(reg_request, tmp, ®_requests_list, list) { |
1962 | list_for_each_entry_safe(reg_request, tmp, | 1864 | if (reg_request->initiator != NL80211_REGDOM_SET_BY_USER) |
1963 | ®_requests_list, list) { | 1865 | continue; |
1964 | if (reg_request->initiator != | 1866 | list_move_tail(®_request->list, &tmp_reg_req_list); |
1965 | NL80211_REGDOM_SET_BY_USER) | ||
1966 | continue; | ||
1967 | list_move_tail(®_request->list, &tmp_reg_req_list); | ||
1968 | } | ||
1969 | } | 1867 | } |
1970 | spin_unlock(®_requests_lock); | 1868 | spin_unlock(®_requests_lock); |
1971 | 1869 | ||
1972 | /* Clear beacon hints */ | 1870 | /* Clear beacon hints */ |
1973 | spin_lock_bh(®_pending_beacons_lock); | 1871 | spin_lock_bh(®_pending_beacons_lock); |
1974 | if (!list_empty(®_pending_beacons)) { | 1872 | list_for_each_entry_safe(reg_beacon, btmp, ®_pending_beacons, list) { |
1975 | list_for_each_entry_safe(reg_beacon, btmp, | 1873 | list_del(®_beacon->list); |
1976 | ®_pending_beacons, list) { | 1874 | kfree(reg_beacon); |
1977 | list_del(®_beacon->list); | ||
1978 | kfree(reg_beacon); | ||
1979 | } | ||
1980 | } | 1875 | } |
1981 | spin_unlock_bh(®_pending_beacons_lock); | 1876 | spin_unlock_bh(®_pending_beacons_lock); |
1982 | 1877 | ||
1983 | if (!list_empty(®_beacon_list)) { | 1878 | list_for_each_entry_safe(reg_beacon, btmp, ®_beacon_list, list) { |
1984 | list_for_each_entry_safe(reg_beacon, btmp, | 1879 | list_del(®_beacon->list); |
1985 | ®_beacon_list, list) { | 1880 | kfree(reg_beacon); |
1986 | list_del(®_beacon->list); | ||
1987 | kfree(reg_beacon); | ||
1988 | } | ||
1989 | } | 1881 | } |
1990 | 1882 | ||
1991 | /* First restore to the basic regulatory settings */ | 1883 | /* First restore to the basic regulatory settings */ |
1992 | cfg80211_regdomain = cfg80211_world_regdom; | 1884 | world_alpha2[0] = cfg80211_world_regdom->alpha2[0]; |
1993 | world_alpha2[0] = cfg80211_regdomain->alpha2[0]; | 1885 | world_alpha2[1] = cfg80211_world_regdom->alpha2[1]; |
1994 | world_alpha2[1] = cfg80211_regdomain->alpha2[1]; | ||
1995 | 1886 | ||
1996 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | 1887 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
1997 | if (rdev->wiphy.flags & WIPHY_FLAG_CUSTOM_REGULATORY) | 1888 | if (rdev->wiphy.flags & WIPHY_FLAG_CUSTOM_REGULATORY) |
1998 | restore_custom_reg_settings(&rdev->wiphy); | 1889 | restore_custom_reg_settings(&rdev->wiphy); |
1999 | } | 1890 | } |
2000 | 1891 | ||
2001 | mutex_unlock(®_mutex); | ||
2002 | mutex_unlock(&cfg80211_mutex); | ||
2003 | |||
2004 | regulatory_hint_core(world_alpha2); | 1892 | regulatory_hint_core(world_alpha2); |
2005 | 1893 | ||
2006 | /* | 1894 | /* |
@@ -2011,20 +1899,8 @@ static void restore_regulatory_settings(bool reset_user) | |||
2011 | if (is_an_alpha2(alpha2)) | 1899 | if (is_an_alpha2(alpha2)) |
2012 | regulatory_hint_user(user_alpha2, NL80211_USER_REG_HINT_USER); | 1900 | regulatory_hint_user(user_alpha2, NL80211_USER_REG_HINT_USER); |
2013 | 1901 | ||
2014 | if (list_empty(&tmp_reg_req_list)) | ||
2015 | return; | ||
2016 | |||
2017 | mutex_lock(&cfg80211_mutex); | ||
2018 | mutex_lock(®_mutex); | ||
2019 | |||
2020 | spin_lock(®_requests_lock); | 1902 | spin_lock(®_requests_lock); |
2021 | list_for_each_entry_safe(reg_request, tmp, &tmp_reg_req_list, list) { | 1903 | list_splice_tail_init(&tmp_reg_req_list, ®_requests_list); |
2022 | REG_DBG_PRINT("Adding request for country %c%c back " | ||
2023 | "into the queue\n", | ||
2024 | reg_request->alpha2[0], | ||
2025 | reg_request->alpha2[1]); | ||
2026 | list_move_tail(®_request->list, ®_requests_list); | ||
2027 | } | ||
2028 | spin_unlock(®_requests_lock); | 1904 | spin_unlock(®_requests_lock); |
2029 | 1905 | ||
2030 | mutex_unlock(®_mutex); | 1906 | mutex_unlock(®_mutex); |
@@ -2037,8 +1913,7 @@ static void restore_regulatory_settings(bool reset_user) | |||
2037 | 1913 | ||
2038 | void regulatory_hint_disconnect(void) | 1914 | void regulatory_hint_disconnect(void) |
2039 | { | 1915 | { |
2040 | REG_DBG_PRINT("All devices are disconnected, going to " | 1916 | REG_DBG_PRINT("All devices are disconnected, going to restore regulatory settings\n"); |
2041 | "restore regulatory settings\n"); | ||
2042 | restore_regulatory_settings(false); | 1917 | restore_regulatory_settings(false); |
2043 | } | 1918 | } |
2044 | 1919 | ||
@@ -2051,31 +1926,48 @@ static bool freq_is_chan_12_13_14(u16 freq) | |||
2051 | return false; | 1926 | return false; |
2052 | } | 1927 | } |
2053 | 1928 | ||
1929 | static bool pending_reg_beacon(struct ieee80211_channel *beacon_chan) | ||
1930 | { | ||
1931 | struct reg_beacon *pending_beacon; | ||
1932 | |||
1933 | list_for_each_entry(pending_beacon, ®_pending_beacons, list) | ||
1934 | if (beacon_chan->center_freq == | ||
1935 | pending_beacon->chan.center_freq) | ||
1936 | return true; | ||
1937 | return false; | ||
1938 | } | ||
1939 | |||
2054 | int regulatory_hint_found_beacon(struct wiphy *wiphy, | 1940 | int regulatory_hint_found_beacon(struct wiphy *wiphy, |
2055 | struct ieee80211_channel *beacon_chan, | 1941 | struct ieee80211_channel *beacon_chan, |
2056 | gfp_t gfp) | 1942 | gfp_t gfp) |
2057 | { | 1943 | { |
2058 | struct reg_beacon *reg_beacon; | 1944 | struct reg_beacon *reg_beacon; |
1945 | bool processing; | ||
2059 | 1946 | ||
2060 | if (likely((beacon_chan->beacon_found || | 1947 | if (beacon_chan->beacon_found || |
2061 | (beacon_chan->flags & IEEE80211_CHAN_RADAR) || | 1948 | beacon_chan->flags & IEEE80211_CHAN_RADAR || |
2062 | (beacon_chan->band == IEEE80211_BAND_2GHZ && | 1949 | (beacon_chan->band == IEEE80211_BAND_2GHZ && |
2063 | !freq_is_chan_12_13_14(beacon_chan->center_freq))))) | 1950 | !freq_is_chan_12_13_14(beacon_chan->center_freq))) |
1951 | return 0; | ||
1952 | |||
1953 | spin_lock_bh(®_pending_beacons_lock); | ||
1954 | processing = pending_reg_beacon(beacon_chan); | ||
1955 | spin_unlock_bh(®_pending_beacons_lock); | ||
1956 | |||
1957 | if (processing) | ||
2064 | return 0; | 1958 | return 0; |
2065 | 1959 | ||
2066 | reg_beacon = kzalloc(sizeof(struct reg_beacon), gfp); | 1960 | reg_beacon = kzalloc(sizeof(struct reg_beacon), gfp); |
2067 | if (!reg_beacon) | 1961 | if (!reg_beacon) |
2068 | return -ENOMEM; | 1962 | return -ENOMEM; |
2069 | 1963 | ||
2070 | REG_DBG_PRINT("Found new beacon on " | 1964 | REG_DBG_PRINT("Found new beacon on frequency: %d MHz (Ch %d) on %s\n", |
2071 | "frequency: %d MHz (Ch %d) on %s\n", | ||
2072 | beacon_chan->center_freq, | 1965 | beacon_chan->center_freq, |
2073 | ieee80211_frequency_to_channel(beacon_chan->center_freq), | 1966 | ieee80211_frequency_to_channel(beacon_chan->center_freq), |
2074 | wiphy_name(wiphy)); | 1967 | wiphy_name(wiphy)); |
2075 | 1968 | ||
2076 | memcpy(®_beacon->chan, beacon_chan, | 1969 | memcpy(®_beacon->chan, beacon_chan, |
2077 | sizeof(struct ieee80211_channel)); | 1970 | sizeof(struct ieee80211_channel)); |
2078 | |||
2079 | 1971 | ||
2080 | /* | 1972 | /* |
2081 | * Since we can be called from BH or and non-BH context | 1973 | * Since we can be called from BH or and non-BH context |
@@ -2155,21 +2047,19 @@ static void print_dfs_region(u8 dfs_region) | |||
2155 | pr_info(" DFS Master region JP"); | 2047 | pr_info(" DFS Master region JP"); |
2156 | break; | 2048 | break; |
2157 | default: | 2049 | default: |
2158 | pr_info(" DFS Master region Uknown"); | 2050 | pr_info(" DFS Master region Unknown"); |
2159 | break; | 2051 | break; |
2160 | } | 2052 | } |
2161 | } | 2053 | } |
2162 | 2054 | ||
2163 | static void print_regdomain(const struct ieee80211_regdomain *rd) | 2055 | static void print_regdomain(const struct ieee80211_regdomain *rd) |
2164 | { | 2056 | { |
2057 | struct regulatory_request *lr = get_last_request(); | ||
2165 | 2058 | ||
2166 | if (is_intersected_alpha2(rd->alpha2)) { | 2059 | if (is_intersected_alpha2(rd->alpha2)) { |
2167 | 2060 | if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { | |
2168 | if (last_request->initiator == | ||
2169 | NL80211_REGDOM_SET_BY_COUNTRY_IE) { | ||
2170 | struct cfg80211_registered_device *rdev; | 2061 | struct cfg80211_registered_device *rdev; |
2171 | rdev = cfg80211_rdev_by_wiphy_idx( | 2062 | rdev = cfg80211_rdev_by_wiphy_idx(lr->wiphy_idx); |
2172 | last_request->wiphy_idx); | ||
2173 | if (rdev) { | 2063 | if (rdev) { |
2174 | pr_info("Current regulatory domain updated by AP to: %c%c\n", | 2064 | pr_info("Current regulatory domain updated by AP to: %c%c\n", |
2175 | rdev->country_ie_alpha2[0], | 2065 | rdev->country_ie_alpha2[0], |
@@ -2178,22 +2068,21 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) | |||
2178 | pr_info("Current regulatory domain intersected:\n"); | 2068 | pr_info("Current regulatory domain intersected:\n"); |
2179 | } else | 2069 | } else |
2180 | pr_info("Current regulatory domain intersected:\n"); | 2070 | pr_info("Current regulatory domain intersected:\n"); |
2181 | } else if (is_world_regdom(rd->alpha2)) | 2071 | } else if (is_world_regdom(rd->alpha2)) { |
2182 | pr_info("World regulatory domain updated:\n"); | 2072 | pr_info("World regulatory domain updated:\n"); |
2183 | else { | 2073 | } else { |
2184 | if (is_unknown_alpha2(rd->alpha2)) | 2074 | if (is_unknown_alpha2(rd->alpha2)) |
2185 | pr_info("Regulatory domain changed to driver built-in settings (unknown country)\n"); | 2075 | pr_info("Regulatory domain changed to driver built-in settings (unknown country)\n"); |
2186 | else { | 2076 | else { |
2187 | if (reg_request_cell_base(last_request)) | 2077 | if (reg_request_cell_base(lr)) |
2188 | pr_info("Regulatory domain changed " | 2078 | pr_info("Regulatory domain changed to country: %c%c by Cell Station\n", |
2189 | "to country: %c%c by Cell Station\n", | ||
2190 | rd->alpha2[0], rd->alpha2[1]); | 2079 | rd->alpha2[0], rd->alpha2[1]); |
2191 | else | 2080 | else |
2192 | pr_info("Regulatory domain changed " | 2081 | pr_info("Regulatory domain changed to country: %c%c\n", |
2193 | "to country: %c%c\n", | ||
2194 | rd->alpha2[0], rd->alpha2[1]); | 2082 | rd->alpha2[0], rd->alpha2[1]); |
2195 | } | 2083 | } |
2196 | } | 2084 | } |
2085 | |||
2197 | print_dfs_region(rd->dfs_region); | 2086 | print_dfs_region(rd->dfs_region); |
2198 | print_rd_rules(rd); | 2087 | print_rd_rules(rd); |
2199 | } | 2088 | } |
@@ -2207,22 +2096,23 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd) | |||
2207 | /* Takes ownership of rd only if it doesn't fail */ | 2096 | /* Takes ownership of rd only if it doesn't fail */ |
2208 | static int __set_regdom(const struct ieee80211_regdomain *rd) | 2097 | static int __set_regdom(const struct ieee80211_regdomain *rd) |
2209 | { | 2098 | { |
2099 | const struct ieee80211_regdomain *regd; | ||
2210 | const struct ieee80211_regdomain *intersected_rd = NULL; | 2100 | const struct ieee80211_regdomain *intersected_rd = NULL; |
2211 | struct wiphy *request_wiphy; | 2101 | struct wiphy *request_wiphy; |
2102 | struct regulatory_request *lr = get_last_request(); | ||
2103 | |||
2212 | /* Some basic sanity checks first */ | 2104 | /* Some basic sanity checks first */ |
2213 | 2105 | ||
2106 | if (!reg_is_valid_request(rd->alpha2)) | ||
2107 | return -EINVAL; | ||
2108 | |||
2214 | if (is_world_regdom(rd->alpha2)) { | 2109 | if (is_world_regdom(rd->alpha2)) { |
2215 | if (WARN_ON(!reg_is_valid_request(rd->alpha2))) | ||
2216 | return -EINVAL; | ||
2217 | update_world_regdomain(rd); | 2110 | update_world_regdomain(rd); |
2218 | return 0; | 2111 | return 0; |
2219 | } | 2112 | } |
2220 | 2113 | ||
2221 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && | 2114 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && |
2222 | !is_unknown_alpha2(rd->alpha2)) | 2115 | !is_unknown_alpha2(rd->alpha2)) |
2223 | return -EINVAL; | ||
2224 | |||
2225 | if (!last_request) | ||
2226 | return -EINVAL; | 2116 | return -EINVAL; |
2227 | 2117 | ||
2228 | /* | 2118 | /* |
@@ -2230,7 +2120,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
2230 | * rd is non static (it means CRDA was present and was used last) | 2120 | * rd is non static (it means CRDA was present and was used last) |
2231 | * and the pending request came in from a country IE | 2121 | * and the pending request came in from a country IE |
2232 | */ | 2122 | */ |
2233 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { | 2123 | if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
2234 | /* | 2124 | /* |
2235 | * If someone else asked us to change the rd lets only bother | 2125 | * If someone else asked us to change the rd lets only bother |
2236 | * checking if the alpha2 changes if CRDA was already called | 2126 | * checking if the alpha2 changes if CRDA was already called |
@@ -2246,29 +2136,23 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
2246 | * internal EEPROM data | 2136 | * internal EEPROM data |
2247 | */ | 2137 | */ |
2248 | 2138 | ||
2249 | if (WARN_ON(!reg_is_valid_request(rd->alpha2))) | ||
2250 | return -EINVAL; | ||
2251 | |||
2252 | if (!is_valid_rd(rd)) { | 2139 | if (!is_valid_rd(rd)) { |
2253 | pr_err("Invalid regulatory domain detected:\n"); | 2140 | pr_err("Invalid regulatory domain detected:\n"); |
2254 | print_regdomain_info(rd); | 2141 | print_regdomain_info(rd); |
2255 | return -EINVAL; | 2142 | return -EINVAL; |
2256 | } | 2143 | } |
2257 | 2144 | ||
2258 | request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); | 2145 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); |
2259 | if (!request_wiphy && | 2146 | if (!request_wiphy && |
2260 | (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER || | 2147 | (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || |
2261 | last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) { | 2148 | lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) { |
2262 | schedule_delayed_work(®_timeout, 0); | 2149 | schedule_delayed_work(®_timeout, 0); |
2263 | return -ENODEV; | 2150 | return -ENODEV; |
2264 | } | 2151 | } |
2265 | 2152 | ||
2266 | if (!last_request->intersect) { | 2153 | if (!lr->intersect) { |
2267 | int r; | 2154 | if (lr->initiator != NL80211_REGDOM_SET_BY_DRIVER) { |
2268 | 2155 | reset_regdomains(false, rd); | |
2269 | if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) { | ||
2270 | reset_regdomains(false); | ||
2271 | cfg80211_regdomain = rd; | ||
2272 | return 0; | 2156 | return 0; |
2273 | } | 2157 | } |
2274 | 2158 | ||
@@ -2284,20 +2168,19 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
2284 | if (request_wiphy->regd) | 2168 | if (request_wiphy->regd) |
2285 | return -EALREADY; | 2169 | return -EALREADY; |
2286 | 2170 | ||
2287 | r = reg_copy_regd(&request_wiphy->regd, rd); | 2171 | regd = reg_copy_regd(rd); |
2288 | if (r) | 2172 | if (IS_ERR(regd)) |
2289 | return r; | 2173 | return PTR_ERR(regd); |
2290 | 2174 | ||
2291 | reset_regdomains(false); | 2175 | rcu_assign_pointer(request_wiphy->regd, regd); |
2292 | cfg80211_regdomain = rd; | 2176 | reset_regdomains(false, rd); |
2293 | return 0; | 2177 | return 0; |
2294 | } | 2178 | } |
2295 | 2179 | ||
2296 | /* Intersection requires a bit more work */ | 2180 | /* Intersection requires a bit more work */ |
2297 | 2181 | ||
2298 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { | 2182 | if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
2299 | 2183 | intersected_rd = regdom_intersect(rd, get_cfg80211_regdom()); | |
2300 | intersected_rd = regdom_intersect(rd, cfg80211_regdomain); | ||
2301 | if (!intersected_rd) | 2184 | if (!intersected_rd) |
2302 | return -EINVAL; | 2185 | return -EINVAL; |
2303 | 2186 | ||
@@ -2306,15 +2189,14 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
2306 | * However if a driver requested this specific regulatory | 2189 | * However if a driver requested this specific regulatory |
2307 | * domain we keep it for its private use | 2190 | * domain we keep it for its private use |
2308 | */ | 2191 | */ |
2309 | if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) | 2192 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) |
2310 | request_wiphy->regd = rd; | 2193 | rcu_assign_pointer(request_wiphy->regd, rd); |
2311 | else | 2194 | else |
2312 | kfree(rd); | 2195 | kfree(rd); |
2313 | 2196 | ||
2314 | rd = NULL; | 2197 | rd = NULL; |
2315 | 2198 | ||
2316 | reset_regdomains(false); | 2199 | reset_regdomains(false, intersected_rd); |
2317 | cfg80211_regdomain = intersected_rd; | ||
2318 | 2200 | ||
2319 | return 0; | 2201 | return 0; |
2320 | } | 2202 | } |
@@ -2326,15 +2208,15 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
2326 | /* | 2208 | /* |
2327 | * Use this call to set the current regulatory domain. Conflicts with | 2209 | * Use this call to set the current regulatory domain. Conflicts with |
2328 | * multiple drivers can be ironed out later. Caller must've already | 2210 | * multiple drivers can be ironed out later. Caller must've already |
2329 | * kmalloc'd the rd structure. Caller must hold cfg80211_mutex | 2211 | * kmalloc'd the rd structure. |
2330 | */ | 2212 | */ |
2331 | int set_regdom(const struct ieee80211_regdomain *rd) | 2213 | int set_regdom(const struct ieee80211_regdomain *rd) |
2332 | { | 2214 | { |
2215 | struct regulatory_request *lr; | ||
2333 | int r; | 2216 | int r; |
2334 | 2217 | ||
2335 | assert_cfg80211_lock(); | ||
2336 | |||
2337 | mutex_lock(®_mutex); | 2218 | mutex_lock(®_mutex); |
2219 | lr = get_last_request(); | ||
2338 | 2220 | ||
2339 | /* Note that this doesn't update the wiphys, this is done below */ | 2221 | /* Note that this doesn't update the wiphys, this is done below */ |
2340 | r = __set_regdom(rd); | 2222 | r = __set_regdom(rd); |
@@ -2343,23 +2225,25 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
2343 | reg_set_request_processed(); | 2225 | reg_set_request_processed(); |
2344 | 2226 | ||
2345 | kfree(rd); | 2227 | kfree(rd); |
2346 | mutex_unlock(®_mutex); | 2228 | goto out; |
2347 | return r; | ||
2348 | } | 2229 | } |
2349 | 2230 | ||
2350 | /* This would make this whole thing pointless */ | 2231 | /* This would make this whole thing pointless */ |
2351 | if (!last_request->intersect) | 2232 | if (WARN_ON(!lr->intersect && rd != get_cfg80211_regdom())) { |
2352 | BUG_ON(rd != cfg80211_regdomain); | 2233 | r = -EINVAL; |
2234 | goto out; | ||
2235 | } | ||
2353 | 2236 | ||
2354 | /* update all wiphys now with the new established regulatory domain */ | 2237 | /* update all wiphys now with the new established regulatory domain */ |
2355 | update_all_wiphy_regulatory(last_request->initiator); | 2238 | update_all_wiphy_regulatory(lr->initiator); |
2356 | 2239 | ||
2357 | print_regdomain(cfg80211_regdomain); | 2240 | print_regdomain(get_cfg80211_regdom()); |
2358 | 2241 | ||
2359 | nl80211_send_reg_change_event(last_request); | 2242 | nl80211_send_reg_change_event(lr); |
2360 | 2243 | ||
2361 | reg_set_request_processed(); | 2244 | reg_set_request_processed(); |
2362 | 2245 | ||
2246 | out: | ||
2363 | mutex_unlock(®_mutex); | 2247 | mutex_unlock(®_mutex); |
2364 | 2248 | ||
2365 | return r; | 2249 | return r; |
@@ -2367,20 +2251,26 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
2367 | 2251 | ||
2368 | int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env) | 2252 | int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env) |
2369 | { | 2253 | { |
2370 | if (last_request && !last_request->processed) { | 2254 | struct regulatory_request *lr; |
2371 | if (add_uevent_var(env, "COUNTRY=%c%c", | 2255 | u8 alpha2[2]; |
2372 | last_request->alpha2[0], | 2256 | bool add = false; |
2373 | last_request->alpha2[1])) | 2257 | |
2374 | return -ENOMEM; | 2258 | rcu_read_lock(); |
2259 | lr = get_last_request(); | ||
2260 | if (lr && !lr->processed) { | ||
2261 | memcpy(alpha2, lr->alpha2, 2); | ||
2262 | add = true; | ||
2375 | } | 2263 | } |
2264 | rcu_read_unlock(); | ||
2376 | 2265 | ||
2266 | if (add) | ||
2267 | return add_uevent_var(env, "COUNTRY=%c%c", | ||
2268 | alpha2[0], alpha2[1]); | ||
2377 | return 0; | 2269 | return 0; |
2378 | } | 2270 | } |
2379 | 2271 | ||
2380 | void wiphy_regulatory_register(struct wiphy *wiphy) | 2272 | void wiphy_regulatory_register(struct wiphy *wiphy) |
2381 | { | 2273 | { |
2382 | assert_cfg80211_lock(); | ||
2383 | |||
2384 | mutex_lock(®_mutex); | 2274 | mutex_lock(®_mutex); |
2385 | 2275 | ||
2386 | if (!reg_dev_ignore_cell_hint(wiphy)) | 2276 | if (!reg_dev_ignore_cell_hint(wiphy)) |
@@ -2395,32 +2285,32 @@ void wiphy_regulatory_register(struct wiphy *wiphy) | |||
2395 | void wiphy_regulatory_deregister(struct wiphy *wiphy) | 2285 | void wiphy_regulatory_deregister(struct wiphy *wiphy) |
2396 | { | 2286 | { |
2397 | struct wiphy *request_wiphy = NULL; | 2287 | struct wiphy *request_wiphy = NULL; |
2398 | 2288 | struct regulatory_request *lr; | |
2399 | assert_cfg80211_lock(); | ||
2400 | 2289 | ||
2401 | mutex_lock(®_mutex); | 2290 | mutex_lock(®_mutex); |
2291 | lr = get_last_request(); | ||
2402 | 2292 | ||
2403 | if (!reg_dev_ignore_cell_hint(wiphy)) | 2293 | if (!reg_dev_ignore_cell_hint(wiphy)) |
2404 | reg_num_devs_support_basehint--; | 2294 | reg_num_devs_support_basehint--; |
2405 | 2295 | ||
2406 | kfree(wiphy->regd); | 2296 | rcu_free_regdom(get_wiphy_regdom(wiphy)); |
2297 | rcu_assign_pointer(wiphy->regd, NULL); | ||
2407 | 2298 | ||
2408 | if (last_request) | 2299 | if (lr) |
2409 | request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); | 2300 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); |
2410 | 2301 | ||
2411 | if (!request_wiphy || request_wiphy != wiphy) | 2302 | if (!request_wiphy || request_wiphy != wiphy) |
2412 | goto out; | 2303 | goto out; |
2413 | 2304 | ||
2414 | last_request->wiphy_idx = WIPHY_IDX_STALE; | 2305 | lr->wiphy_idx = WIPHY_IDX_INVALID; |
2415 | last_request->country_ie_env = ENVIRON_ANY; | 2306 | lr->country_ie_env = ENVIRON_ANY; |
2416 | out: | 2307 | out: |
2417 | mutex_unlock(®_mutex); | 2308 | mutex_unlock(®_mutex); |
2418 | } | 2309 | } |
2419 | 2310 | ||
2420 | static void reg_timeout_work(struct work_struct *work) | 2311 | static void reg_timeout_work(struct work_struct *work) |
2421 | { | 2312 | { |
2422 | REG_DBG_PRINT("Timeout while waiting for CRDA to reply, " | 2313 | REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n"); |
2423 | "restoring regulatory settings\n"); | ||
2424 | restore_regulatory_settings(true); | 2314 | restore_regulatory_settings(true); |
2425 | } | 2315 | } |
2426 | 2316 | ||
@@ -2439,13 +2329,13 @@ int __init regulatory_init(void) | |||
2439 | 2329 | ||
2440 | reg_regdb_size_check(); | 2330 | reg_regdb_size_check(); |
2441 | 2331 | ||
2442 | cfg80211_regdomain = cfg80211_world_regdom; | 2332 | rcu_assign_pointer(cfg80211_regdomain, cfg80211_world_regdom); |
2443 | 2333 | ||
2444 | user_alpha2[0] = '9'; | 2334 | user_alpha2[0] = '9'; |
2445 | user_alpha2[1] = '7'; | 2335 | user_alpha2[1] = '7'; |
2446 | 2336 | ||
2447 | /* We always try to get an update for the static regdomain */ | 2337 | /* We always try to get an update for the static regdomain */ |
2448 | err = regulatory_hint_core(cfg80211_regdomain->alpha2); | 2338 | err = regulatory_hint_core(cfg80211_world_regdom->alpha2); |
2449 | if (err) { | 2339 | if (err) { |
2450 | if (err == -ENOMEM) | 2340 | if (err == -ENOMEM) |
2451 | return err; | 2341 | return err; |
@@ -2457,10 +2347,6 @@ int __init regulatory_init(void) | |||
2457 | * errors as non-fatal. | 2347 | * errors as non-fatal. |
2458 | */ | 2348 | */ |
2459 | pr_err("kobject_uevent_env() was unable to call CRDA during init\n"); | 2349 | pr_err("kobject_uevent_env() was unable to call CRDA during init\n"); |
2460 | #ifdef CONFIG_CFG80211_REG_DEBUG | ||
2461 | /* We want to find out exactly why when debugging */ | ||
2462 | WARN_ON(err); | ||
2463 | #endif | ||
2464 | } | 2350 | } |
2465 | 2351 | ||
2466 | /* | 2352 | /* |
@@ -2474,7 +2360,7 @@ int __init regulatory_init(void) | |||
2474 | return 0; | 2360 | return 0; |
2475 | } | 2361 | } |
2476 | 2362 | ||
2477 | void /* __init_or_exit */ regulatory_exit(void) | 2363 | void regulatory_exit(void) |
2478 | { | 2364 | { |
2479 | struct regulatory_request *reg_request, *tmp; | 2365 | struct regulatory_request *reg_request, *tmp; |
2480 | struct reg_beacon *reg_beacon, *btmp; | 2366 | struct reg_beacon *reg_beacon, *btmp; |
@@ -2482,43 +2368,27 @@ void /* __init_or_exit */ regulatory_exit(void) | |||
2482 | cancel_work_sync(®_work); | 2368 | cancel_work_sync(®_work); |
2483 | cancel_delayed_work_sync(®_timeout); | 2369 | cancel_delayed_work_sync(®_timeout); |
2484 | 2370 | ||
2485 | mutex_lock(&cfg80211_mutex); | 2371 | /* Lock to suppress warnings */ |
2486 | mutex_lock(®_mutex); | 2372 | mutex_lock(®_mutex); |
2487 | 2373 | reset_regdomains(true, NULL); | |
2488 | reset_regdomains(true); | 2374 | mutex_unlock(®_mutex); |
2489 | 2375 | ||
2490 | dev_set_uevent_suppress(®_pdev->dev, true); | 2376 | dev_set_uevent_suppress(®_pdev->dev, true); |
2491 | 2377 | ||
2492 | platform_device_unregister(reg_pdev); | 2378 | platform_device_unregister(reg_pdev); |
2493 | 2379 | ||
2494 | spin_lock_bh(®_pending_beacons_lock); | 2380 | list_for_each_entry_safe(reg_beacon, btmp, ®_pending_beacons, list) { |
2495 | if (!list_empty(®_pending_beacons)) { | 2381 | list_del(®_beacon->list); |
2496 | list_for_each_entry_safe(reg_beacon, btmp, | 2382 | kfree(reg_beacon); |
2497 | ®_pending_beacons, list) { | ||
2498 | list_del(®_beacon->list); | ||
2499 | kfree(reg_beacon); | ||
2500 | } | ||
2501 | } | 2383 | } |
2502 | spin_unlock_bh(®_pending_beacons_lock); | ||
2503 | 2384 | ||
2504 | if (!list_empty(®_beacon_list)) { | 2385 | list_for_each_entry_safe(reg_beacon, btmp, ®_beacon_list, list) { |
2505 | list_for_each_entry_safe(reg_beacon, btmp, | 2386 | list_del(®_beacon->list); |
2506 | ®_beacon_list, list) { | 2387 | kfree(reg_beacon); |
2507 | list_del(®_beacon->list); | ||
2508 | kfree(reg_beacon); | ||
2509 | } | ||
2510 | } | 2388 | } |
2511 | 2389 | ||
2512 | spin_lock(®_requests_lock); | 2390 | list_for_each_entry_safe(reg_request, tmp, ®_requests_list, list) { |
2513 | if (!list_empty(®_requests_list)) { | 2391 | list_del(®_request->list); |
2514 | list_for_each_entry_safe(reg_request, tmp, | 2392 | kfree(reg_request); |
2515 | ®_requests_list, list) { | ||
2516 | list_del(®_request->list); | ||
2517 | kfree(reg_request); | ||
2518 | } | ||
2519 | } | 2393 | } |
2520 | spin_unlock(®_requests_lock); | ||
2521 | |||
2522 | mutex_unlock(®_mutex); | ||
2523 | mutex_unlock(&cfg80211_mutex); | ||
2524 | } | 2394 | } |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 4c0a32ffd530..af2d5f8a5d82 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -16,10 +16,9 @@ | |||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | extern const struct ieee80211_regdomain *cfg80211_regdomain; | 19 | extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain; |
20 | 20 | ||
21 | bool is_world_regdom(const char *alpha2); | 21 | bool is_world_regdom(const char *alpha2); |
22 | bool reg_is_valid_request(const char *alpha2); | ||
23 | bool reg_supported_dfs_region(u8 dfs_region); | 22 | bool reg_supported_dfs_region(u8 dfs_region); |
24 | 23 | ||
25 | int regulatory_hint_user(const char *alpha2, | 24 | int regulatory_hint_user(const char *alpha2, |
@@ -55,8 +54,8 @@ bool reg_last_request_cell_base(void); | |||
55 | * set the wiphy->disable_beacon_hints to true. | 54 | * set the wiphy->disable_beacon_hints to true. |
56 | */ | 55 | */ |
57 | int regulatory_hint_found_beacon(struct wiphy *wiphy, | 56 | int regulatory_hint_found_beacon(struct wiphy *wiphy, |
58 | struct ieee80211_channel *beacon_chan, | 57 | struct ieee80211_channel *beacon_chan, |
59 | gfp_t gfp); | 58 | gfp_t gfp); |
60 | 59 | ||
61 | /** | 60 | /** |
62 | * regulatory_hint_11d - hints a country IE as a regulatory domain | 61 | * regulatory_hint_11d - hints a country IE as a regulatory domain |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f2431e41a373..a825dfe12cf7 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -192,7 +192,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
192 | prev_bssid, | 192 | prev_bssid, |
193 | params->ssid, params->ssid_len, | 193 | params->ssid, params->ssid_len, |
194 | params->ie, params->ie_len, | 194 | params->ie, params->ie_len, |
195 | false, ¶ms->crypto, | 195 | params->mfp != NL80211_MFP_NO, |
196 | ¶ms->crypto, | ||
196 | params->flags, ¶ms->ht_capa, | 197 | params->flags, ¶ms->ht_capa, |
197 | ¶ms->ht_capa_mask); | 198 | ¶ms->ht_capa_mask); |
198 | if (err) | 199 | if (err) |
@@ -519,10 +520,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
519 | * - country_ie + 2, the start of the country ie data, and | 520 | * - country_ie + 2, the start of the country ie data, and |
520 | * - and country_ie[1] which is the IE length | 521 | * - and country_ie[1] which is the IE length |
521 | */ | 522 | */ |
522 | regulatory_hint_11d(wdev->wiphy, | 523 | regulatory_hint_11d(wdev->wiphy, bss->channel->band, |
523 | bss->channel->band, | 524 | country_ie + 2, country_ie[1]); |
524 | country_ie + 2, | ||
525 | country_ie[1]); | ||
526 | kfree(country_ie); | 525 | kfree(country_ie); |
527 | } | 526 | } |
528 | 527 | ||
diff --git a/net/wireless/util.c b/net/wireless/util.c index 16d76a807c2f..1c2795d52db0 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -1184,7 +1184,8 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1184 | struct wireless_dev *wdev, | 1184 | struct wireless_dev *wdev, |
1185 | enum nl80211_iftype iftype, | 1185 | enum nl80211_iftype iftype, |
1186 | struct ieee80211_channel *chan, | 1186 | struct ieee80211_channel *chan, |
1187 | enum cfg80211_chan_mode chanmode) | 1187 | enum cfg80211_chan_mode chanmode, |
1188 | u8 radar_detect) | ||
1188 | { | 1189 | { |
1189 | struct wireless_dev *wdev_iter; | 1190 | struct wireless_dev *wdev_iter; |
1190 | u32 used_iftypes = BIT(iftype); | 1191 | u32 used_iftypes = BIT(iftype); |
@@ -1195,14 +1196,45 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1195 | enum cfg80211_chan_mode chmode; | 1196 | enum cfg80211_chan_mode chmode; |
1196 | int num_different_channels = 0; | 1197 | int num_different_channels = 0; |
1197 | int total = 1; | 1198 | int total = 1; |
1199 | bool radar_required; | ||
1198 | int i, j; | 1200 | int i, j; |
1199 | 1201 | ||
1200 | ASSERT_RTNL(); | 1202 | ASSERT_RTNL(); |
1201 | lockdep_assert_held(&rdev->devlist_mtx); | 1203 | lockdep_assert_held(&rdev->devlist_mtx); |
1202 | 1204 | ||
1205 | if (WARN_ON(hweight32(radar_detect) > 1)) | ||
1206 | return -EINVAL; | ||
1207 | |||
1208 | switch (iftype) { | ||
1209 | case NL80211_IFTYPE_ADHOC: | ||
1210 | case NL80211_IFTYPE_AP: | ||
1211 | case NL80211_IFTYPE_AP_VLAN: | ||
1212 | case NL80211_IFTYPE_MESH_POINT: | ||
1213 | case NL80211_IFTYPE_P2P_GO: | ||
1214 | case NL80211_IFTYPE_WDS: | ||
1215 | radar_required = !!(chan->flags & IEEE80211_CHAN_RADAR); | ||
1216 | break; | ||
1217 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1218 | case NL80211_IFTYPE_STATION: | ||
1219 | case NL80211_IFTYPE_MONITOR: | ||
1220 | radar_required = false; | ||
1221 | break; | ||
1222 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1223 | case NUM_NL80211_IFTYPES: | ||
1224 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1225 | default: | ||
1226 | return -EINVAL; | ||
1227 | } | ||
1228 | |||
1229 | if (radar_required && !radar_detect) | ||
1230 | return -EINVAL; | ||
1231 | |||
1203 | /* Always allow software iftypes */ | 1232 | /* Always allow software iftypes */ |
1204 | if (rdev->wiphy.software_iftypes & BIT(iftype)) | 1233 | if (rdev->wiphy.software_iftypes & BIT(iftype)) { |
1234 | if (radar_detect) | ||
1235 | return -EINVAL; | ||
1205 | return 0; | 1236 | return 0; |
1237 | } | ||
1206 | 1238 | ||
1207 | memset(num, 0, sizeof(num)); | 1239 | memset(num, 0, sizeof(num)); |
1208 | memset(used_channels, 0, sizeof(used_channels)); | 1240 | memset(used_channels, 0, sizeof(used_channels)); |
@@ -1275,7 +1307,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1275 | used_iftypes |= BIT(wdev_iter->iftype); | 1307 | used_iftypes |= BIT(wdev_iter->iftype); |
1276 | } | 1308 | } |
1277 | 1309 | ||
1278 | if (total == 1) | 1310 | if (total == 1 && !radar_detect) |
1279 | return 0; | 1311 | return 0; |
1280 | 1312 | ||
1281 | for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { | 1313 | for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { |
@@ -1308,6 +1340,9 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1308 | } | 1340 | } |
1309 | } | 1341 | } |
1310 | 1342 | ||
1343 | if (radar_detect && !(c->radar_detect_widths & radar_detect)) | ||
1344 | goto cont; | ||
1345 | |||
1311 | /* | 1346 | /* |
1312 | * Finally check that all iftypes that we're currently | 1347 | * Finally check that all iftypes that we're currently |
1313 | * using are actually part of this combination. If they | 1348 | * using are actually part of this combination. If they |