Unified · Split
| @@ -17,10 +17,12 @@ HCI · 16 unmodified lines | |||
| 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 · 6 unmodified lines | |||
| 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. · 7 unmodified lines | |||
| 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 { · 1 unmodified line | |||
| 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 · 6 unmodified lines | |||
| 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 · 39 unmodified lines | |||
| 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 | ||
| @@ -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 · 14 unmodified lines | |||
| 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 | }; | ||
| @@ -1353,6 +1353,14 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k · 1352 unmodified lines | |||
| 1353 | S: Supported | 1353 | S: Supported |
| 1354 | F: drivers/net/wireless/ath/ath9k/ | 1354 | F: drivers/net/wireless/ath/ath9k/ |
| 1355 | 1355 | ||
| 1356 | WILOCITY WIL6210 WIRELESS DRIVER | ||
| 1357 | M: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> | ||
| 1358 | L: linux-wireless@vger.kernel.org | ||
| 1359 | L: wil6210@qca.qualcomm.com | ||
| 1360 | S: Supported | ||
| 1361 | W: http://wireless.kernel.org/en/users/Drivers/wil6210 | ||
| 1362 | F: drivers/net/wireless/ath/wil6210/ | ||
| 1363 | |||
| 1356 | CARL9170 LINUX COMMUNITY WIRELESS DRIVER | 1364 | CARL9170 LINUX COMMUNITY WIRELESS DRIVER |
| 1357 | M: Christian Lamparter <chunkeey@googlemail.com> | 1365 | M: Christian Lamparter <chunkeey@googlemail.com> |
| 1358 | L: linux-wireless@vger.kernel.org | 1366 | L: linux-wireless@vger.kernel.org |
| @@ -62,7 +62,7 @@ static int __init uart8250_init_bcma(void) · 61 unmodified lines | |||
| 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; |
| @@ -67,8 +67,7 @@ config BCMA_DRIVER_GMAC_CMN · 66 unmodified lines | |||
| 67 | 67 | ||
| 68 | config BCMA_DRIVER_GPIO | 68 | config BCMA_DRIVER_GPIO |
| 69 | bool "BCMA GPIO driver" | 69 | bool "BCMA GPIO driver" |
| 70 | depends on BCMA | 70 | depends on BCMA && GPIOLIB |
| 71 | select GPIOLIB | ||
| 72 | help | 71 | help |
| 73 | Driver to provide access to the GPIO pins of the bcma bus. | 72 | Driver to provide access to the GPIO pins of the bcma bus. |
| 74 | 73 | ||
| @@ -31,6 +31,8 @@ int __init bcma_bus_early_register(struct bcma_bus *bus, · 30 unmodified lines | |||
| 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); |
| @@ -329,7 +329,7 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc) · 328 unmodified lines | |||
| 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); |
| @@ -35,7 +35,7 @@ static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { · 34 unmodified lines | |||
| 35 | { "M25P40", 0x12, 0x10000, 8, }, | 35 | { "M25P40", 0x12, 0x10000, 8, }, |
| 36 | 36 | ||
| 37 | { "M25P16", 0x14, 0x10000, 32, }, | 37 | { "M25P16", 0x14, 0x10000, 32, }, |
| 38 | { "M25P32", 0x14, 0x10000, 64, }, | 38 | { "M25P32", 0x15, 0x10000, 64, }, |
| 39 | { "M25P64", 0x16, 0x10000, 128, }, | 39 | { "M25P64", 0x16, 0x10000, 128, }, |
| 40 | { "M25FL128", 0x17, 0x10000, 256, }, | 40 | { "M25FL128", 0x17, 0x10000, 256, }, |
| 41 | { 0 }, | 41 | { 0 }, |
| @@ -74,28 +74,41 @@ static u32 bcma_core_mips_irqflag(struct bcma_device *dev) · 73 unmodified lines | |||
| 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) · 12 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 3 unmodified lines | |||
| 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) · 69 unmodified lines | |||
| 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) · 3 unmodified lines | |||
| 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; |
| @@ -94,19 +94,19 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, · 93 unmodified lines | |||
| 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, · 6 unmodified lines | |||
| 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, · 21 unmodified lines | |||
| 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, · 1 unmodified line | |||
| 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, · 5 unmodified lines | |||
| 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, · 1 unmodified line | |||
| 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 | ||
| @@ -277,7 +280,7 @@ static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc, · 64 unmodified lines | |||
| 277 | /* check for Header type 0 */ | 280 | /* check for Header type 0 */ |
| 278 | bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, | 281 | bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, |
| 279 | sizeof(u8)); | 282 | sizeof(u8)); |
| 280 | if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) | 283 | if ((byte_val & 0x7F) != PCI_HEADER_TYPE_NORMAL) |
| 281 | return cap_ptr; | 284 | return cap_ptr; |
| 282 | 285 | ||
| 283 | /* check if the capability pointer field exists */ | 286 | /* check if the capability pointer field exists */ |
| @@ -427,7 +430,7 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) · 143 unmodified lines | |||
| 427 | /* Reset RC */ | 430 | /* Reset RC */ |
| 428 | usleep_range(3000, 5000); | 431 | usleep_range(3000, 5000); |
| 429 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); | 432 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); |
| 430 | usleep_range(1000, 2000); | 433 | msleep(50); |
| 431 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | | 434 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | |
| 432 | BCMA_CORE_PCI_CTL_RST_OE); | 435 | BCMA_CORE_PCI_CTL_RST_OE); |
| 433 | 436 | ||
| @@ -489,6 +492,17 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) · 55 unmodified lines | |||
| 489 | 492 | ||
| 490 | bcma_core_pci_enable_crs(pc); | 493 | bcma_core_pci_enable_crs(pc); |
| 491 | 494 | ||
| 495 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706 || | ||
| 496 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4716) { | ||
| 497 | u16 val16; | ||
| 498 | bcma_extpci_read_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL, | ||
| 499 | &val16, sizeof(val16)); | ||
| 500 | val16 |= (2 << 5); /* Max payload size of 512 */ | ||
| 501 | val16 |= (2 << 12); /* MRRS 512 */ | ||
| 502 | bcma_extpci_write_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL, | ||
| 503 | &val16, sizeof(val16)); | ||
| 504 | } | ||
| 505 | |||
| 492 | /* Enable PCI bridge BAR0 memory & master access */ | 506 | /* Enable PCI bridge BAR0 memory & master access */ |
| 493 | tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; | 507 | tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; |
| 494 | bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); | 508 | bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); |
| @@ -577,7 +591,7 @@ int bcma_core_pci_plat_dev_init(struct pci_dev *dev) · 82 unmodified lines | |||
| 577 | pr_info("PCI: Fixing up device %s\n", pci_name(dev)); | 591 | pr_info("PCI: Fixing up device %s\n", pci_name(dev)); |
| 578 | 592 | ||
| 579 | /* Fix up interrupt lines */ | 593 | /* Fix up interrupt lines */ |
| 580 | dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2; | 594 | dev->irq = bcma_core_irq(pc_host->pdev->core); |
| 581 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | 595 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); |
| 582 | 596 | ||
| 583 | return 0; | 597 | return 0; |
| @@ -596,6 +610,6 @@ int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev) · 12 unmodified lines | |||
| 596 | 610 | ||
| 597 | pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, | 611 | pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, |
| 598 | pci_ops); | 612 | pci_ops); |
| 599 | return bcma_core_mips_irq(pc_host->pdev->core) + 2; | 613 | return bcma_core_irq(pc_host->pdev->core); |
| 600 | } | 614 | } |
| 601 | EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); | 615 | EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); |
| @@ -81,8 +81,8 @@ struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) · 80 unmodified lines | |||
| 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 | ||
| @@ -77,10 +77,15 @@ static struct usb_device_id ath3k_table[] = { · 76 unmodified lines | |||
| 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[] = { · 17 unmodified lines | |||
| 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 }, |
| @@ -135,10 +135,15 @@ static struct usb_device_id blacklist_table[] = { · 134 unmodified lines | |||
| 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 }, |
| @@ -30,5 +30,6 @@ source "drivers/net/wireless/ath/ath9k/Kconfig" · 29 unmodified lines | |||
| 30 | source "drivers/net/wireless/ath/carl9170/Kconfig" | 30 | source "drivers/net/wireless/ath/carl9170/Kconfig" |
| 31 | source "drivers/net/wireless/ath/ath6kl/Kconfig" | 31 | source "drivers/net/wireless/ath/ath6kl/Kconfig" |
| 32 | source "drivers/net/wireless/ath/ar5523/Kconfig" | 32 | source "drivers/net/wireless/ath/ar5523/Kconfig" |
| 33 | source "drivers/net/wireless/ath/wil6210/Kconfig" | ||
| 33 | 34 | ||
| 34 | endif | 35 | endif |
| @@ -3,6 +3,7 @@ obj-$(CONFIG_ATH9K_HW) += ath9k/ · 2 unmodified lines | |||
| 3 | obj-$(CONFIG_CARL9170) += carl9170/ | 3 | obj-$(CONFIG_CARL9170) += carl9170/ |
| 4 | obj-$(CONFIG_ATH6KL) += ath6kl/ | 4 | obj-$(CONFIG_ATH6KL) += ath6kl/ |
| 5 | obj-$(CONFIG_AR5523) += ar5523/ | 5 | obj-$(CONFIG_AR5523) += ar5523/ |
| 6 | obj-$(CONFIG_WIL6210) += wil6210/ | ||
| 6 | 7 | ||
| 7 | obj-$(CONFIG_ATH_COMMON) += ath.o | 8 | obj-$(CONFIG_ATH_COMMON) += ath.o |
| 8 | 9 | ||
| @@ -2,6 +2,7 @@ config ATH9K_HW · 1 unmodified line | |||
| 2 | tristate | 2 | tristate |
| 3 | config ATH9K_COMMON | 3 | config ATH9K_COMMON |
| 4 | tristate | 4 | tristate |
| 5 | select ATH_COMMON | ||
| 5 | config ATH9K_DFS_DEBUGFS | 6 | config ATH9K_DFS_DEBUGFS |
| 6 | def_bool y | 7 | def_bool y |
| 7 | depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED | 8 | depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED |
| @@ -17,7 +18,6 @@ config ATH9K_BTCOEX_SUPPORT · 9 unmodified lines | |||
| 17 | config ATH9K | 18 | config ATH9K |
| 18 | tristate "Atheros 802.11n wireless cards support" | 19 | tristate "Atheros 802.11n wireless cards support" |
| 19 | depends on MAC80211 | 20 | depends on MAC80211 |
| 20 | select ATH_COMMON | ||
| 21 | select ATH9K_HW | 21 | select ATH9K_HW |
| 22 | select MAC80211_LEDS | 22 | select MAC80211_LEDS |
| 23 | select LEDS_CLASS | 23 | select LEDS_CLASS |
| @@ -56,7 +56,8 @@ config ATH9K_AHB · 32 unmodified lines | |||
| 56 | 56 | ||
| 57 | config ATH9K_DEBUGFS | 57 | config ATH9K_DEBUGFS |
| 58 | bool "Atheros ath9k debugging" | 58 | bool "Atheros ath9k debugging" |
| 59 | depends on ATH9K && DEBUG_FS | 59 | depends on ATH9K |
| 60 | select MAC80211_DEBUGFS | ||
| 60 | ---help--- | 61 | ---help--- |
| 61 | Say Y, if you need access to ath9k's statistics for | 62 | Say Y, if you need access to ath9k's statistics for |
| 62 | interrupts, rate control, etc. | 63 | interrupts, rate control, etc. |
| @@ -86,29 +86,25 @@ static int ath_ahb_probe(struct platform_device *pdev) · 85 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 32 unmodified lines | |||
| 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) · 3 unmodified lines | |||
| 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 | ||
| @@ -152,7 +152,8 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, · 151 unmodified lines | |||
| 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, · 14 unmodified lines | |||
| 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, · 36 unmodified lines | |||
| 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) · 191 unmodified lines | |||
| 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) · 62 unmodified lines | |||
| 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) · 19 unmodified lines | |||
| 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; |
| @@ -104,7 +104,6 @@ struct ath9k_ani_default { · 103 unmodified lines | |||
| 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 { · 2 unmodified lines | |||
| 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 { · 19 unmodified lines | |||
| 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 */ |
| @@ -466,7 +466,7 @@ static const u32 ar5416Bank0[][2] = { · 465 unmodified lines | |||
| 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] = { · 73 unmodified lines | |||
| 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] = { · 30 unmodified lines | |||
| 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}, |
| @@ -470,16 +470,15 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah, · 469 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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) · 853 unmodified lines | |||
| 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) · 4 unmodified lines | |||
| 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) · 18 unmodified lines | |||
| 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 | } |
| @@ -460,7 +460,7 @@ static const u32 ar5416Common_9100[][2] = { · 459 unmodified lines | |||
| 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] = { · 30 unmodified lines | |||
| 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}, |
| @@ -23,13 +23,13 @@ · 22 unmodified lines | |||
| 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) · 66 unmodified lines | |||
| 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) · 9 unmodified lines | |||
| 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) · 283 unmodified lines | |||
| 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) |
| @@ -555,14 +555,73 @@ static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah, · 554 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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 | } |
| @@ -744,6 +744,186 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { · 743 unmodified lines | |||
| 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}, |
| @@ -32,7 +32,6 @@ struct coeff { · 31 unmodified lines | |||
| 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, · 10 unmodified lines | |||
| 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, · 2 unmodified lines | |||
| 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 = { · 251 unmodified lines | |||
| 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) · 630 unmodified lines | |||
| 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, · 31 unmodified lines | |||
| 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, · 13 unmodified lines | |||
| 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: · 4 unmodified lines | |||
| 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: · 18 unmodified lines | |||
| 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: · 11 unmodified lines | |||
| 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; |
| @@ -4586,14 +4586,14 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah, · 4585 unmodified lines | |||
| 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, · 24 unmodified lines | |||
| 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. */ |
| @@ -507,28 +507,59 @@ static void ar9003_tx_gain_table_mode4(struct ath_hw *ah) · 506 unmodified lines | |||
| 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); | ||
| 529 | } | ||
| 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); | ||
| 510 | } | 542 | } |
| 511 | 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) |
| @@ -544,7 +575,7 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) · 9 unmodified lines | |||
| 544 | ar9340Common_rx_gain_table_1p0); | 575 | ar9340Common_rx_gain_table_1p0); |
| 545 | else if (AR_SREV_9485_11(ah)) | 576 | else if (AR_SREV_9485_11(ah)) |
| 546 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 577 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
| 547 | ar9485Common_wo_xlna_rx_gain_1_1); | 578 | ar9485_common_rx_gain_1_1); |
| 548 | else if (AR_SREV_9550(ah)) { | 579 | else if (AR_SREV_9550(ah)) { |
| 549 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 580 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
| 550 | ar955x_1p0_common_rx_gain_table); | 581 | ar955x_1p0_common_rx_gain_table); |
| @@ -673,7 +704,7 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) · 122 unmodified lines | |||
| 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; |
| @@ -68,7 +68,7 @@ static const int m2ThreshExt_off = 127; · 67 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 3 unmodified lines | |||
| 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, · 463 unmodified lines | |||
| 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: · 832 unmodified lines | |||
| 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) · 27 unmodified lines | |||
| 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); |
| @@ -1028,7 +1028,7 @@ · 1027 unmodified lines | |||
| 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 | ||
| @@ -1172,6 +1172,106 @@ static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = { · 1171 unmodified lines | |||
| 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}, |
| @@ -260,6 +260,79 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { · 259 unmodified lines | |||
| 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] = { · 184 unmodified lines | |||
| 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}, |
| @@ -23,16 +23,16 @@ · 22 unmodified lines | |||
| 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] = { · 30 unmodified lines | |||
| 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] = { · 41 unmodified lines | |||
| 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] = { · 2 unmodified lines | |||
| 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] = { · 37 unmodified lines | |||
| 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] = { · 33 unmodified lines | |||
| 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] = { · 20 unmodified lines | |||
| 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] = { · 2 unmodified lines | |||
| 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] = { · 527 unmodified lines | |||
| 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] = { · 424 unmodified lines | |||
| 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 | ||
| @@ -685,6 +685,82 @@ static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = { · 684 unmodified lines | |||
| 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}, |
| @@ -109,14 +109,11 @@ struct ath_descdma { · 108 unmodified lines | |||
| 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 { · 194 unmodified lines | |||
| 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 { · 1 unmodified line | |||
| 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); · 3 unmodified lines | |||
| 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); · 294 unmodified lines | |||
| 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 { · 22 unmodified lines | |||
| 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 { · 62 unmodified lines | |||
| 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 { · 2 unmodified lines | |||
| 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); · 16 unmodified lines | |||
| 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); |
| @@ -147,6 +147,7 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, · 146 unmodified lines | |||
| 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, · 45 unmodified lines | |||
| 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) · 154 unmodified lines | |||
| 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", |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | |||
| 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, · 838 unmodified lines | |||
| 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 = { · 98 unmodified lines | |||
| 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) · 808 unmodified lines | |||
| 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); |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | |||
| 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 { · 187 unmodified lines | |||
| 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 { · 12 unmodified lines | |||
| 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, · 81 unmodified lines | |||
| 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 */ |
| @@ -344,6 +344,8 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, · 343 unmodified lines | |||
| 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 | ||
| @@ -101,22 +101,6 @@ static inline void ath9k_hw_spur_mitigate_freq(struct ath_hw *ah, · 100 unmodified lines | |||
| 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) |
| @@ -54,11 +54,6 @@ static void ath9k_hw_init_cal_settings(struct ath_hw *ah) · 53 unmodified lines | |||
| 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, · 143 unmodified lines | |||
| 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) · 339 unmodified lines | |||
| 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) · 29 unmodified lines | |||
| 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) · 57 unmodified lines | |||
| 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) · 470 unmodified lines | |||
| 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) · 1411 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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; |
| @@ -397,6 +397,7 @@ enum ath9k_int { · 396 unmodified lines | |||
| 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 { · 196 unmodified lines | |||
| 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 { · 8 unmodified lines | |||
| 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 { · 3 unmodified lines | |||
| 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); |
| @@ -660,6 +655,37 @@ struct ath_hw_private_ops { · 22 unmodified lines | |||
| 660 | void (*ani_cache_ini_regs)(struct ath_hw *ah); | 655 | void (*ani_cache_ini_regs)(struct ath_hw *ah); |
| 661 | }; | 656 | }; |
| 662 | 657 | ||
| 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 | |||
| 663 | /** | 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 | * |
| @@ -668,6 +694,10 @@ struct ath_hw_private_ops { · 2 unmodified lines | |||
| 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 { · 14 unmodified lines | |||
| 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 { · 16 unmodified lines | |||
| 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 { · 55 unmodified lines | |||
| 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 { · 52 unmodified lines | |||
| 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); · 139 unmodified lines | |||
| 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); · 80 unmodified lines | |||
| 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); |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | |||
| 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 | ||
| @@ -334,7 +335,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, · 308 unmodified lines | |||
| 334 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 335 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 335 | u8 *ds; | 336 | u8 *ds; |
| 336 | struct ath_buf *bf; | 337 | struct ath_buf *bf; |
| 337 | int i, bsize, error, desc_len; | 338 | int i, bsize, desc_len; |
| 338 | 339 | ||
| 339 | 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", |
| 340 | name, nbuf, ndesc); | 341 | name, nbuf, ndesc); |
| @@ -350,8 +351,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, · 9 unmodified lines | |||
| 350 | if ((desc_len % 4) != 0) { | 351 | if ((desc_len % 4) != 0) { |
| 351 | ath_err(common, "ath_desc not DWORD aligned\n"); | 352 | ath_err(common, "ath_desc not DWORD aligned\n"); |
| 352 | BUG_ON((desc_len % 4) != 0); | 353 | BUG_ON((desc_len % 4) != 0); |
| 353 | error = -ENOMEM; | 354 | return -ENOMEM; |
| 354 | goto fail; | ||
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | dd->dd_desc_len = desc_len * nbuf * ndesc; | 357 | dd->dd_desc_len = desc_len * nbuf * ndesc; |
| @@ -375,12 +375,11 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, · 17 unmodified lines | |||
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | /* allocate descriptors */ | 377 | /* allocate descriptors */ |
| 378 | 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, |
| 379 | &dd->dd_desc_paddr, GFP_KERNEL); | 379 | &dd->dd_desc_paddr, GFP_KERNEL); |
| 380 | if (dd->dd_desc == NULL) { | 380 | if (!dd->dd_desc) |
| 381 | error = -ENOMEM; | 381 | return -ENOMEM; |
| 382 | goto fail; | 382 | |
| 383 | } | ||
| 384 | ds = (u8 *) dd->dd_desc; | 383 | ds = (u8 *) dd->dd_desc; |
| 385 | 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", |
| 386 | name, ds, (u32) dd->dd_desc_len, | 385 | name, ds, (u32) dd->dd_desc_len, |
| @@ -388,12 +387,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, · 1 unmodified line | |||
| 388 | 387 | ||
| 389 | /* allocate buffers */ | 388 | /* allocate buffers */ |
| 390 | bsize = sizeof(struct ath_buf) * nbuf; | 389 | bsize = sizeof(struct ath_buf) * nbuf; |
| 391 | bf = kzalloc(bsize, GFP_KERNEL); | 390 | bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); |
| 392 | if (bf == NULL) { | 391 | if (!bf) |
| 393 | error = -ENOMEM; | 392 | return -ENOMEM; |
| 394 | goto fail2; | ||
| 395 | } | ||
| 396 | dd->dd_bufptr = bf; | ||
| 397 | 393 | ||
| 398 | for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { | 394 | for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { |
| 399 | bf->bf_desc = ds; | 395 | bf->bf_desc = ds; |
| @@ -419,12 +415,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, · 19 unmodified lines | |||
| 419 | list_add_tail(&bf->list, head); | 415 | list_add_tail(&bf->list, head); |
| 420 | } | 416 | } |
| 421 | return 0; | 417 | return 0; |
| 422 | fail2: | ||
| 423 | dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, | ||
| 424 | dd->dd_desc_paddr); | ||
| 425 | fail: | ||
| 426 | memset(dd, 0, sizeof(*dd)); | ||
| 427 | return error; | ||
| 428 | } | 418 | } |
| 429 | 419 | ||
| 430 | static int ath9k_init_queues(struct ath_softc *sc) | 420 | static int ath9k_init_queues(struct ath_softc *sc) |
| @@ -454,11 +444,13 @@ static int ath9k_init_channels_rates(struct ath_softc *sc) · 23 unmodified lines | |||
| 454 | ATH9K_NUM_CHANNELS); | 444 | ATH9K_NUM_CHANNELS); |
| 455 | 445 | ||
| 456 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { | 446 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { |
| 457 | channels = kmemdup(ath9k_2ghz_chantable, | 447 | channels = devm_kzalloc(sc->dev, |
| 458 | sizeof(ath9k_2ghz_chantable), GFP_KERNEL); | 448 | sizeof(ath9k_2ghz_chantable), GFP_KERNEL); |
| 459 | if (!channels) | 449 | if (!channels) |
| 460 | return -ENOMEM; | 450 | return -ENOMEM; |
| 461 | 451 | ||
| 452 | memcpy(channels, ath9k_2ghz_chantable, | ||
| 453 | sizeof(ath9k_2ghz_chantable)); | ||
| 462 | sc->sbands[IEEE80211_BAND_2GHZ].channels = channels; | 454 | sc->sbands[IEEE80211_BAND_2GHZ].channels = channels; |
| 463 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | 455 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; |
| 464 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = | 456 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = |
| @@ -469,14 +461,13 @@ static int ath9k_init_channels_rates(struct ath_softc *sc) · 4 unmodified lines | |||
| 469 | } | 461 | } |
| 470 | 462 | ||
| 471 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { | 463 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { |
| 472 | channels = kmemdup(ath9k_5ghz_chantable, | 464 | channels = devm_kzalloc(sc->dev, |
| 473 | sizeof(ath9k_5ghz_chantable), GFP_KERNEL); | 465 | sizeof(ath9k_5ghz_chantable), GFP_KERNEL); |
| 474 | if (!channels) { | 466 | if (!channels) |
| 475 | if (sc->sbands[IEEE80211_BAND_2GHZ].channels) | ||
| 476 | kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); | ||
| 477 | return -ENOMEM; | 467 | return -ENOMEM; |
| 478 | } | ||
| 479 | 468 | ||
| 469 | memcpy(channels, ath9k_5ghz_chantable, | ||
| 470 | sizeof(ath9k_5ghz_chantable)); | ||
| 480 | sc->sbands[IEEE80211_BAND_5GHZ].channels = channels; | 471 | sc->sbands[IEEE80211_BAND_5GHZ].channels = channels; |
| 481 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; | 472 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; |
| 482 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = | 473 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = |
| @@ -562,10 +553,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, · 79 unmodified lines | |||
| 562 | int ret = 0, i; | 553 | int ret = 0, i; |
| 563 | int csz = 0; | 554 | int csz = 0; |
| 564 | 555 | ||
| 565 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); | 556 | ah = devm_kzalloc(sc->dev, sizeof(struct ath_hw), GFP_KERNEL); |
| 566 | if (!ah) | 557 | if (!ah) |
| 567 | return -ENOMEM; | 558 | return -ENOMEM; |
| 568 | 559 | ||
| 560 | ah->dev = sc->dev; | ||
| 569 | ah->hw = sc->hw; | 561 | ah->hw = sc->hw; |
| 570 | ah->hw_version.devid = devid; | 562 | ah->hw_version.devid = devid; |
| 571 | ah->reg_ops.read = ath9k_ioread32; | 563 | ah->reg_ops.read = ath9k_ioread32; |
| @@ -633,7 +625,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, · 61 unmodified lines | |||
| 633 | if (pdata && pdata->eeprom_name) { | 625 | if (pdata && pdata->eeprom_name) { |
| 634 | ret = ath9k_eeprom_request(sc, pdata->eeprom_name); | 626 | ret = ath9k_eeprom_request(sc, pdata->eeprom_name); |
| 635 | if (ret) | 627 | if (ret) |
| 636 | goto err_eeprom; | 628 | return ret; |
| 637 | } | 629 | } |
| 638 | 630 | ||
| 639 | /* Initializes the hardware for all supported chipsets */ | 631 | /* Initializes the hardware for all supported chipsets */ |
| @@ -673,10 +665,6 @@ err_queues: · 33 unmodified lines | |||
| 673 | ath9k_hw_deinit(ah); | 665 | ath9k_hw_deinit(ah); |
| 674 | err_hw: | 666 | err_hw: |
| 675 | ath9k_eeprom_release(sc); | 667 | ath9k_eeprom_release(sc); |
| 676 | err_eeprom: | ||
| 677 | kfree(ah); | ||
| 678 | sc->sc_ah = NULL; | ||
| 679 | |||
| 680 | return ret; | 668 | return ret; |
| 681 | } | 669 | } |
| 682 | 670 | ||
| @@ -841,8 +829,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, · 158 unmodified lines | |||
| 841 | 829 | ||
| 842 | /* Bring up device */ | 830 | /* Bring up device */ |
| 843 | error = ath9k_init_softc(devid, sc, bus_ops); | 831 | error = ath9k_init_softc(devid, sc, bus_ops); |
| 844 | if (error != 0) | 832 | if (error) |
| 845 | goto error_init; | 833 | return error; |
| 846 | 834 | ||
| 847 | ah = sc->sc_ah; | 835 | ah = sc->sc_ah; |
| 848 | common = ath9k_hw_common(ah); | 836 | common = ath9k_hw_common(ah); |
| @@ -852,19 +840,19 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, · 3 unmodified lines | |||
| 852 | error = ath_regd_init(&common->regulatory, sc->hw->wiphy, | 840 | error = ath_regd_init(&common->regulatory, sc->hw->wiphy, |
| 853 | ath9k_reg_notifier); | 841 | ath9k_reg_notifier); |
| 854 | if (error) | 842 | if (error) |
| 855 | goto error_regd; | 843 | goto deinit; |
| 856 | 844 | ||
| 857 | reg = &common->regulatory; | 845 | reg = &common->regulatory; |
| 858 | 846 | ||
| 859 | /* Setup TX DMA */ | 847 | /* Setup TX DMA */ |
| 860 | error = ath_tx_init(sc, ATH_TXBUF); | 848 | error = ath_tx_init(sc, ATH_TXBUF); |
| 861 | if (error != 0) | 849 | if (error != 0) |
| 862 | goto error_tx; | 850 | goto deinit; |
| 863 | 851 | ||
| 864 | /* Setup RX DMA */ | 852 | /* Setup RX DMA */ |
| 865 | error = ath_rx_init(sc, ATH_RXBUF); | 853 | error = ath_rx_init(sc, ATH_RXBUF); |
| 866 | if (error != 0) | 854 | if (error != 0) |
| 867 | goto error_rx; | 855 | goto deinit; |
| 868 | 856 | ||
| 869 | ath9k_init_txpower_limits(sc); | 857 | ath9k_init_txpower_limits(sc); |
| 870 | 858 | ||
| @@ -878,19 +866,19 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, · 7 unmodified lines | |||
| 878 | /* Register with mac80211 */ | 866 | /* Register with mac80211 */ |
| 879 | error = ieee80211_register_hw(hw); | 867 | error = ieee80211_register_hw(hw); |
| 880 | if (error) | 868 | if (error) |
| 881 | goto error_register; | 869 | goto rx_cleanup; |
| 882 | 870 | ||
| 883 | error = ath9k_init_debug(ah); | 871 | error = ath9k_init_debug(ah); |
| 884 | if (error) { | 872 | if (error) { |
| 885 | ath_err(common, "Unable to create debugfs files\n"); | 873 | ath_err(common, "Unable to create debugfs files\n"); |
| 886 | goto error_world; | 874 | goto unregister; |
| 887 | } | 875 | } |
| 888 | 876 | ||
| 889 | /* Handle world regulatory */ | 877 | /* Handle world regulatory */ |
| 890 | if (!ath_is_world_regd(reg)) { | 878 | if (!ath_is_world_regd(reg)) { |
| 891 | error = regulatory_hint(hw->wiphy, reg->alpha2); | 879 | error = regulatory_hint(hw->wiphy, reg->alpha2); |
| 892 | if (error) | 880 | if (error) |
| 893 | goto error_world; | 881 | goto unregister; |
| 894 | } | 882 | } |
| 895 | 883 | ||
| 896 | ath_init_leds(sc); | 884 | ath_init_leds(sc); |
| @@ -898,17 +886,12 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, · 1 unmodified line | |||
| 898 | 886 | ||
| 899 | return 0; | 887 | return 0; |
| 900 | 888 | ||
| 901 | error_world: | 889 | unregister: |
| 902 | ieee80211_unregister_hw(hw); | 890 | ieee80211_unregister_hw(hw); |
| 903 | error_register: | 891 | rx_cleanup: |
| 904 | ath_rx_cleanup(sc); | 892 | ath_rx_cleanup(sc); |
| 905 | error_rx: | 893 | deinit: |
| 906 | ath_tx_cleanup(sc); | ||
| 907 | error_tx: | ||
| 908 | /* Nothing */ | ||
| 909 | error_regd: | ||
| 910 | ath9k_deinit_softc(sc); | 894 | ath9k_deinit_softc(sc); |
| 911 | error_init: | ||
| 912 | return error; | 895 | return error; |
| 913 | } | 896 | } |
| 914 | 897 | ||
| @@ -920,12 +903,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc) · 5 unmodified lines | |||
| 920 | { | 903 | { |
| 921 | int i = 0; | 904 | int i = 0; |
| 922 | 905 | ||
| 923 | if (sc->sbands[IEEE80211_BAND_2GHZ].channels) | ||
| 924 | kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); | ||
| 925 | |||
| 926 | if (sc->sbands[IEEE80211_BAND_5GHZ].channels) | ||
| 927 | kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels); | ||
| 928 | |||
| 929 | ath9k_deinit_btcoex(sc); | 906 | ath9k_deinit_btcoex(sc); |
| 930 | 907 | ||
| 931 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | 908 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) |
| @@ -937,8 +914,11 @@ static void ath9k_deinit_softc(struct ath_softc *sc) · 5 unmodified lines | |||
| 937 | sc->dfs_detector->exit(sc->dfs_detector); | 914 | sc->dfs_detector->exit(sc->dfs_detector); |
| 938 | 915 | ||
| 939 | ath9k_eeprom_release(sc); | 916 | ath9k_eeprom_release(sc); |
| 940 | kfree(sc->sc_ah); | 917 | |
| 941 | 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 | } | ||
| 942 | } | 922 | } |
| 943 | 923 | ||
| 944 | void ath9k_deinit_device(struct ath_softc *sc) | 924 | void ath9k_deinit_device(struct ath_softc *sc) |
| @@ -954,22 +934,9 @@ void ath9k_deinit_device(struct ath_softc *sc) · 9 unmodified lines | |||
| 954 | 934 | ||
| 955 | ieee80211_unregister_hw(hw); | 935 | ieee80211_unregister_hw(hw); |
| 956 | ath_rx_cleanup(sc); | 936 | ath_rx_cleanup(sc); |
| 957 | ath_tx_cleanup(sc); | ||
| 958 | ath9k_deinit_softc(sc); | 937 | ath9k_deinit_softc(sc); |
| 959 | } | 938 | } |
| 960 | 939 | ||
| 961 | void ath_descdma_cleanup(struct ath_softc *sc, | ||
| 962 | struct ath_descdma *dd, | ||
| 963 | struct list_head *head) | ||
| 964 | { | ||
| 965 | dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, | ||
| 966 | dd->dd_desc_paddr); | ||
| 967 | |||
| 968 | INIT_LIST_HEAD(head); | ||
| 969 | kfree(dd->dd_bufptr); | ||
| 970 | memset(dd, 0, sizeof(*dd)); | ||
| 971 | } | ||
| 972 | |||
| 973 | /************************/ | 940 | /************************/ |
| 974 | /* Module Hooks */ | 941 | /* Module Hooks */ |
| 975 | /************************/ | 942 | /************************/ |
| @@ -226,7 +226,8 @@ enum ath9k_phyerr { · 225 unmodified lines | |||
| 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 { |
| @@ -182,7 +182,7 @@ static void ath_restart_work(struct ath_softc *sc) · 181 unmodified lines | |||
| 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) · 7 unmodified lines | |||
| 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) · 39 unmodified lines | |||
| 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, · 3 unmodified lines | |||
| 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, · 15 unmodified lines | |||
| 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, · 11 unmodified lines | |||
| 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: · 223 unmodified lines | |||
| 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) · 14 unmodified lines | |||
| 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) · 211 unmodified lines | |||
| 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) · 264 unmodified lines | |||
| 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) · 107 unmodified lines | |||
| 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) { |
| @@ -1731,11 +1806,11 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) · 537 unmodified lines | |||
| 1731 | if (drop) { | 1806 | if (drop) { |
| 1732 | ath9k_ps_wakeup(sc); | 1807 | ath9k_ps_wakeup(sc); |
| 1733 | spin_lock_bh(&sc->sc_pcu_lock); | 1808 | spin_lock_bh(&sc->sc_pcu_lock); |
| 1734 | drain_txq = ath_drain_all_txq(sc, false); | 1809 | drain_txq = ath_drain_all_txq(sc); |
| 1735 | spin_unlock_bh(&sc->sc_pcu_lock); | 1810 | spin_unlock_bh(&sc->sc_pcu_lock); |
| 1736 | 1811 | ||
| 1737 | if (!drain_txq) | 1812 | if (!drain_txq) |
| 1738 | ath_reset(sc, false); | 1813 | ath_reset(sc); |
| 1739 | 1814 | ||
| 1740 | ath9k_ps_restore(sc); | 1815 | ath9k_ps_restore(sc); |
| 1741 | ieee80211_wake_queues(hw); | 1816 | ieee80211_wake_queues(hw); |
| @@ -1835,6 +1910,9 @@ static u32 fill_chainmask(u32 cap, u32 new) · 93 unmodified lines | |||
| 1835 | 1910 | ||
| 1836 | static bool validate_antenna_mask(struct ath_hw *ah, u32 val) | 1911 | static bool validate_antenna_mask(struct ath_hw *ah, u32 val) |
| 1837 | { | 1912 | { |
| 1913 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
| 1914 | return true; | ||
| 1915 | |||
| 1838 | switch (val & 0x7) { | 1916 | switch (val & 0x7) { |
| 1839 | case 0x1: | 1917 | case 0x1: |
| 1840 | case 0x3: | 1918 | case 0x3: |
| @@ -2240,6 +2318,19 @@ static void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) · 399 unmodified lines | |||
| 2240 | } | 2318 | } |
| 2241 | 2319 | ||
| 2242 | #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 | } | ||
| 2243 | 2334 | ||
| 2244 | struct ieee80211_ops ath9k_ops = { | 2335 | struct ieee80211_ops ath9k_ops = { |
| 2245 | .tx = ath9k_tx, | 2336 | .tx = ath9k_tx, |
| @@ -2286,4 +2377,6 @@ struct ieee80211_ops ath9k_ops = { · 40 unmodified lines | |||
| 2286 | .sta_add_debugfs = ath9k_sta_add_debugfs, | 2377 | .sta_add_debugfs = ath9k_sta_add_debugfs, |
| 2287 | .sta_remove_debugfs = ath9k_sta_remove_debugfs, | 2378 | .sta_remove_debugfs = ath9k_sta_remove_debugfs, |
| 2288 | #endif | 2379 | #endif |
| 2380 | .sw_scan_start = ath9k_sw_scan_start, | ||
| 2381 | .sw_scan_complete = ath9k_sw_scan_complete, | ||
| 2289 | }; | 2382 | }; |
| @@ -438,7 +438,7 @@ int ath_mci_setup(struct ath_softc *sc) · 437 unmodified lines | |||
| 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) · 32 unmodified lines | |||
| 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"); |
| @@ -147,7 +147,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = { · 146 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 29 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 14 unmodified lines | |||
| 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: · 1 unmodified line | |||
| 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) · 1 unmodified line | |||
| 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 |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 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) · 159 unmodified lines | |||
| 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) · 20 unmodified lines | |||
| 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: · 31 unmodified lines | |||
| 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) · 5 unmodified lines | |||
| 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) · 10 unmodified lines | |||
| 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) · 70 unmodified lines | |||
| 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) · 75 unmodified lines | |||
| 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: · 14 unmodified lines | |||
| 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) · 5 unmodified lines | |||
| 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, · 230 unmodified lines | |||
| 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, · 284 unmodified lines | |||
| 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) · 19 unmodified lines | |||
| 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) · 36 unmodified lines | |||
| 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) · 5 unmodified lines | |||
| 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: · 117 unmodified lines | |||
| 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); |
| @@ -789,6 +789,7 @@ · 788 unmodified lines | |||
| 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 @@ · 74 unmodified lines | |||
| 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 @@ · 9 unmodified lines | |||
| 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)) |
| @@ -378,7 +378,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf, · 377 unmodified lines | |||
| 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, · 105 unmodified lines | |||
| 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, · 107 unmodified lines | |||
| 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 · 721 unmodified lines | |||
| 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) · 116 unmodified lines | |||
| 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, · 15 unmodified lines | |||
| 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, · 3 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 2 unmodified lines | |||
| 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) · 29 unmodified lines | |||
| 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, · 587 unmodified lines | |||
| 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) · 158 unmodified lines | |||
| 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) · 13 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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; |
| @@ -85,20 +85,14 @@ enum carl9170_device_state { · 84 unmodified lines | |||
| 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 { · 185 unmodified lines | |||
| 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 { · 197 unmodified lines | |||
| 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 { |
| @@ -215,6 +215,24 @@ static int carl9170_fw_tx_sequence(struct ar9170 *ar) · 214 unmodified lines | |||
| 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) · 43 unmodified lines | |||
| 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)) |
| @@ -336,25 +354,24 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) · 65 unmodified lines | |||
| 336 | if (SUPP(CARL9170FW_WLANTX_CAB)) { | 354 | if (SUPP(CARL9170FW_WLANTX_CAB)) { |
| 337 | if_comb_types |= | 355 | if_comb_types |= |
| 338 | BIT(NL80211_IFTYPE_AP) | | 356 | BIT(NL80211_IFTYPE_AP) | |
| 339 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
| 340 | BIT(NL80211_IFTYPE_P2P_GO); | 357 | BIT(NL80211_IFTYPE_P2P_GO); |
| 358 | |||
| 359 | #ifdef CONFIG_MAC80211_MESH | ||
| 360 | if_comb_types |= | ||
| 361 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
| 362 | #endif /* CONFIG_MAC80211_MESH */ | ||
| 341 | } | 363 | } |
| 342 | } | 364 | } |
| 343 | 365 | ||
| 344 | ar->if_comb_limits[0].max = ar->fw.vif_num; | 366 | carl9170_fw_set_if_combinations(ar, if_comb_types); |
| 345 | ar->if_comb_limits[0].types = if_comb_types; | ||
| 346 | |||
| 347 | ar->if_combs[0].num_different_channels = 1; | ||
| 348 | ar->if_combs[0].max_interfaces = ar->fw.vif_num; | ||
| 349 | ar->if_combs[0].limits = ar->if_comb_limits; | ||
| 350 | ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits); | ||
| 351 | |||
| 352 | ar->hw->wiphy->iface_combinations = ar->if_combs; | ||
| 353 | ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs); | ||
| 354 | 367 | ||
| 355 | ar->hw->wiphy->interface_modes |= if_comb_types; | 368 | ar->hw->wiphy->interface_modes |= if_comb_types; |
| 356 | 369 | ||
| 357 | 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; | ||
| 358 | 375 | ||
| 359 | #undef SUPPORTED | 376 | #undef SUPPORTED |
| 360 | return carl9170_fw_tx_sequence(ar); | 377 | return carl9170_fw_tx_sequence(ar); |
| @@ -156,6 +156,14 @@ struct carl9170_psm { · 155 unmodified lines | |||
| 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; |
| @@ -384,7 +384,7 @@ · 383 unmodified lines | |||
| 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 | ||
| @@ -358,8 +358,13 @@ static int carl9170_op_start(struct ieee80211_hw *hw) · 357 unmodified lines | |||
| 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, · 199 unmodified lines | |||
| 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, · 3 unmodified lines | |||
| 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, · 15 unmodified lines | |||
| 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, · 2 unmodified lines | |||
| 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, · 32 unmodified lines | |||
| 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, · 450 unmodified lines | |||
| 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, · 142 unmodified lines | |||
| 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, · 17 unmodified lines | |||
| 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]); |
| @@ -1807,10 +1874,6 @@ void *carl9170_alloc(size_t priv_size) · 513 unmodified lines | |||
| 1807 | for (i = 0; i < ARRAY_SIZE(ar->noise); i++) | 1874 | for (i = 0; i < ARRAY_SIZE(ar->noise); i++) |
| 1808 | ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ | 1875 | ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ |
| 1809 | 1876 | ||
| 1810 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
| 1811 | |||
| 1812 | /* As IBSS Encryption is software-based, IBSS RSN is supported. */ | ||
| 1813 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | ||
| 1814 | return ar; | 1877 | return ar; |
| 1815 | 1878 | ||
| 1816 | err_nomem: | 1879 | err_nomem: |
| @@ -1520,35 +1520,92 @@ void carl9170_tx_scheduler(struct ar9170 *ar) · 1519 unmodified lines | |||
| 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: · 3 unmodified lines | |||
| 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: · 23 unmodified lines | |||
| 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 | /* |
| @@ -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 */ |
| @@ -0,0 +1,29 @@ | |||
| 1 | config WIL6210 | ||
| 2 | tristate "Wilocity 60g WiFi card wil6210 support" | ||
| 3 | depends on CFG80211 | ||
| 4 | depends on PCI | ||
| 5 | default n | ||
| 6 | ---help--- | ||
| 7 | This module adds support for wireless adapter based on | ||
| 8 | wil6210 chip by Wilocity. It supports operation on the | ||
| 9 | 60 GHz band, covered by the IEEE802.11ad standard. | ||
| 10 | |||
| 11 | http://wireless.kernel.org/en/users/Drivers/wil6210 | ||
| 12 | |||
| 13 | If you choose to build it as a module, it will be called | ||
| 14 | wil6210 | ||
| 15 | |||
| 16 | config WIL6210_ISR_COR | ||
| 17 | bool "Use Clear-On-Read mode for ISR registers for wil6210" | ||
| 18 | depends on WIL6210 | ||
| 19 | default y | ||
| 20 | ---help--- | ||
| 21 | ISR registers on wil6210 chip may operate in either | ||
| 22 | COR (Clear-On-Read) or W1C (Write-1-to-Clear) mode. | ||
| 23 | For production code, use COR (say y); is default since | ||
| 24 | it saves extra target transaction; | ||
| 25 | For ISR debug, use W1C (say n); is allows to monitor ISR | ||
| 26 | registers with debugfs. If COR were used, ISR would | ||
| 27 | self-clear when accessed for debug purposes, it makes | ||
| 28 | such monitoring impossible. | ||
| 29 | Say y unless you debug interrupts | ||
| @@ -0,0 +1,13 @@ | |||
| 1 | obj-$(CONFIG_WIL6210) += wil6210.o | ||
| 2 | |||
| 3 | wil6210-objs := main.o | ||
| 4 | wil6210-objs += netdev.o | ||
| 5 | wil6210-objs += cfg80211.o | ||
| 6 | wil6210-objs += pcie_bus.o | ||
| 7 | wil6210-objs += debugfs.o | ||
| 8 | wil6210-objs += wmi.o | ||
| 9 | wil6210-objs += interrupt.o | ||
| 10 | wil6210-objs += txrx.o | ||
| 11 | |||
| 12 | subdir-ccflags-y += -Werror | ||
| 13 | subdir-ccflags-y += -D__CHECK_ENDIAN__ | ||
| @@ -0,0 +1,573 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/netdevice.h> | ||
| 19 | #include <linux/sched.h> | ||
| 20 | #include <linux/etherdevice.h> | ||
| 21 | #include <linux/wireless.h> | ||
| 22 | #include <linux/ieee80211.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/version.h> | ||
| 25 | #include <net/cfg80211.h> | ||
| 26 | |||
| 27 | #include "wil6210.h" | ||
| 28 | #include "wmi.h" | ||
| 29 | |||
| 30 | #define CHAN60G(_channel, _flags) { \ | ||
| 31 | .band = IEEE80211_BAND_60GHZ, \ | ||
| 32 | .center_freq = 56160 + (2160 * (_channel)), \ | ||
| 33 | .hw_value = (_channel), \ | ||
| 34 | .flags = (_flags), \ | ||
| 35 | .max_antenna_gain = 0, \ | ||
| 36 | .max_power = 40, \ | ||
| 37 | } | ||
| 38 | |||
| 39 | static struct ieee80211_channel wil_60ghz_channels[] = { | ||
| 40 | CHAN60G(1, 0), | ||
| 41 | CHAN60G(2, 0), | ||
| 42 | CHAN60G(3, 0), | ||
| 43 | /* channel 4 not supported yet */ | ||
| 44 | }; | ||
| 45 | |||
| 46 | static struct ieee80211_supported_band wil_band_60ghz = { | ||
| 47 | .channels = wil_60ghz_channels, | ||
| 48 | .n_channels = ARRAY_SIZE(wil_60ghz_channels), | ||
| 49 | .ht_cap = { | ||
| 50 | .ht_supported = true, | ||
| 51 | .cap = 0, /* TODO */ | ||
| 52 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, /* TODO */ | ||
| 53 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, /* TODO */ | ||
| 54 | .mcs = { | ||
| 55 | /* MCS 1..12 - SC PHY */ | ||
| 56 | .rx_mask = {0xfe, 0x1f}, /* 1..12 */ | ||
| 57 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, /* TODO */ | ||
| 58 | }, | ||
| 59 | }, | ||
| 60 | }; | ||
| 61 | |||
| 62 | static const struct ieee80211_txrx_stypes | ||
| 63 | wil_mgmt_stypes[NUM_NL80211_IFTYPES] = { | ||
| 64 | [NL80211_IFTYPE_STATION] = { | ||
| 65 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
| 66 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
| 67 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
| 68 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
| 69 | }, | ||
| 70 | [NL80211_IFTYPE_AP] = { | ||
| 71 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
| 72 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
| 73 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
| 74 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
| 75 | }, | ||
| 76 | [NL80211_IFTYPE_P2P_CLIENT] = { | ||
| 77 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
| 78 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
| 79 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
| 80 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
| 81 | }, | ||
| 82 | [NL80211_IFTYPE_P2P_GO] = { | ||
| 83 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
| 84 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
| 85 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
| 86 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
| 87 | }, | ||
| 88 | }; | ||
| 89 | |||
| 90 | static const u32 wil_cipher_suites[] = { | ||
| 91 | WLAN_CIPHER_SUITE_GCMP, | ||
| 92 | }; | ||
| 93 | |||
| 94 | int wil_iftype_nl2wmi(enum nl80211_iftype type) | ||
| 95 | { | ||
| 96 | static const struct { | ||
| 97 | enum nl80211_iftype nl; | ||
| 98 | enum wmi_network_type wmi; | ||
| 99 | } __nl2wmi[] = { | ||
| 100 | {NL80211_IFTYPE_ADHOC, WMI_NETTYPE_ADHOC}, | ||
| 101 | {NL80211_IFTYPE_STATION, WMI_NETTYPE_INFRA}, | ||
| 102 | {NL80211_IFTYPE_AP, WMI_NETTYPE_AP}, | ||
| 103 | {NL80211_IFTYPE_P2P_CLIENT, WMI_NETTYPE_P2P}, | ||
| 104 | {NL80211_IFTYPE_P2P_GO, WMI_NETTYPE_P2P}, | ||
| 105 | {NL80211_IFTYPE_MONITOR, WMI_NETTYPE_ADHOC}, /* FIXME */ | ||
| 106 | }; | ||
| 107 | uint i; | ||
| 108 | |||
| 109 | for (i = 0; i < ARRAY_SIZE(__nl2wmi); i++) { | ||
| 110 | if (__nl2wmi[i].nl == type) | ||
| 111 | return __nl2wmi[i].wmi; | ||
| 112 | } | ||
| 113 | |||
| 114 | return -EOPNOTSUPP; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int wil_cfg80211_get_station(struct wiphy *wiphy, | ||
| 118 | struct net_device *ndev, | ||
| 119 | u8 *mac, struct station_info *sinfo) | ||
| 120 | { | ||
| 121 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 122 | int rc; | ||
| 123 | struct wmi_notify_req_cmd cmd = { | ||
| 124 | .cid = 0, | ||
| 125 | .interval_usec = 0, | ||
| 126 | }; | ||
| 127 | |||
| 128 | if (memcmp(mac, wil->dst_addr[0], ETH_ALEN)) | ||
| 129 | return -ENOENT; | ||
| 130 | |||
| 131 | /* WMI_NOTIFY_REQ_DONE_EVENTID handler fills wil->stats.bf_mcs */ | ||
| 132 | rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), | ||
| 133 | WMI_NOTIFY_REQ_DONE_EVENTID, NULL, 0, 20); | ||
| 134 | if (rc) | ||
| 135 | return rc; | ||
| 136 | |||
| 137 | sinfo->generation = wil->sinfo_gen; | ||
| 138 | |||
| 139 | sinfo->filled |= STATION_INFO_TX_BITRATE; | ||
| 140 | sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; | ||
| 141 | sinfo->txrate.mcs = wil->stats.bf_mcs; | ||
| 142 | sinfo->filled |= STATION_INFO_RX_BITRATE; | ||
| 143 | sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; | ||
| 144 | sinfo->rxrate.mcs = wil->stats.last_mcs_rx; | ||
| 145 | |||
| 146 | if (test_bit(wil_status_fwconnected, &wil->status)) { | ||
| 147 | sinfo->filled |= STATION_INFO_SIGNAL; | ||
| 148 | sinfo->signal = 12; /* TODO: provide real value */ | ||
| 149 | } | ||
| 150 | |||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static int wil_cfg80211_change_iface(struct wiphy *wiphy, | ||
| 155 | struct net_device *ndev, | ||
| 156 | enum nl80211_iftype type, u32 *flags, | ||
| 157 | struct vif_params *params) | ||
| 158 | { | ||
| 159 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 160 | struct wireless_dev *wdev = wil->wdev; | ||
| 161 | |||
| 162 | switch (type) { | ||
| 163 | case NL80211_IFTYPE_STATION: | ||
| 164 | case NL80211_IFTYPE_AP: | ||
| 165 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 166 | case NL80211_IFTYPE_P2P_GO: | ||
| 167 | break; | ||
| 168 | case NL80211_IFTYPE_MONITOR: | ||
| 169 | if (flags) | ||
| 170 | wil->monitor_flags = *flags; | ||
| 171 | else | ||
| 172 | wil->monitor_flags = 0; | ||
| 173 | |||
| 174 | break; | ||
| 175 | default: | ||
| 176 | return -EOPNOTSUPP; | ||
| 177 | } | ||
| 178 | |||
| 179 | wdev->iftype = type; | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | static int wil_cfg80211_scan(struct wiphy *wiphy, | ||
| 185 | struct cfg80211_scan_request *request) | ||
| 186 | { | ||
| 187 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 188 | struct wireless_dev *wdev = wil->wdev; | ||
| 189 | struct { | ||
| 190 | struct wmi_start_scan_cmd cmd; | ||
| 191 | u16 chnl[4]; | ||
| 192 | } __packed cmd; | ||
| 193 | uint i, n; | ||
| 194 | |||
| 195 | if (wil->scan_request) { | ||
| 196 | wil_err(wil, "Already scanning\n"); | ||
| 197 | return -EAGAIN; | ||
| 198 | } | ||
| 199 | |||
| 200 | /* check we are client side */ | ||
| 201 | switch (wdev->iftype) { | ||
| 202 | case NL80211_IFTYPE_STATION: | ||
| 203 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 204 | break; | ||
| 205 | default: | ||
| 206 | return -EOPNOTSUPP; | ||
| 207 | |||
| 208 | } | ||
| 209 | |||
| 210 | /* FW don't support scan after connection attempt */ | ||
| 211 | if (test_bit(wil_status_dontscan, &wil->status)) { | ||
| 212 | wil_err(wil, "Scan after connect attempt not supported\n"); | ||
| 213 | return -EBUSY; | ||
| 214 | } | ||
| 215 | |||
| 216 | wil->scan_request = request; | ||
| 217 | |||
| 218 | memset(&cmd, 0, sizeof(cmd)); | ||
| 219 | cmd.cmd.num_channels = 0; | ||
| 220 | n = min(request->n_channels, 4U); | ||
| 221 | for (i = 0; i < n; i++) { | ||
| 222 | int ch = request->channels[i]->hw_value; | ||
| 223 | if (ch == 0) { | ||
| 224 | wil_err(wil, | ||
| 225 | "Scan requested for unknown frequency %dMhz\n", | ||
| 226 | request->channels[i]->center_freq); | ||
| 227 | continue; | ||
| 228 | } | ||
| 229 | /* 0-based channel indexes */ | ||
| 230 | cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1; | ||
| 231 | wil_dbg(wil, "Scan for ch %d : %d MHz\n", ch, | ||
| 232 | request->channels[i]->center_freq); | ||
| 233 | } | ||
| 234 | |||
| 235 | return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + | ||
| 236 | cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); | ||
| 237 | } | ||
| 238 | |||
| 239 | static int wil_cfg80211_connect(struct wiphy *wiphy, | ||
| 240 | struct net_device *ndev, | ||
| 241 | struct cfg80211_connect_params *sme) | ||
| 242 | { | ||
| 243 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 244 | struct cfg80211_bss *bss; | ||
| 245 | struct wmi_connect_cmd conn; | ||
| 246 | const u8 *ssid_eid; | ||
| 247 | const u8 *rsn_eid; | ||
| 248 | int ch; | ||
| 249 | int rc = 0; | ||
| 250 | |||
| 251 | bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, | ||
| 252 | sme->ssid, sme->ssid_len, | ||
| 253 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | ||
| 254 | if (!bss) { | ||
| 255 | wil_err(wil, "Unable to find BSS\n"); | ||
| 256 | return -ENOENT; | ||
| 257 | } | ||
| 258 | |||
| 259 | ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); | ||
| 260 | if (!ssid_eid) { | ||
| 261 | wil_err(wil, "No SSID\n"); | ||
| 262 | rc = -ENOENT; | ||
| 263 | goto out; | ||
| 264 | } | ||
| 265 | |||
| 266 | rsn_eid = sme->ie ? | ||
| 267 | cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) : | ||
| 268 | NULL; | ||
| 269 | if (rsn_eid) { | ||
| 270 | if (sme->ie_len > WMI_MAX_IE_LEN) { | ||
| 271 | rc = -ERANGE; | ||
| 272 | wil_err(wil, "IE too large (%td bytes)\n", | ||
| 273 | sme->ie_len); | ||
| 274 | goto out; | ||
| 275 | } | ||
| 276 | /* | ||
| 277 | * For secure assoc, send: | ||
| 278 | * (1) WMI_DELETE_CIPHER_KEY_CMD | ||
| 279 | * (2) WMI_SET_APPIE_CMD | ||
| 280 | */ | ||
| 281 | rc = wmi_del_cipher_key(wil, 0, bss->bssid); | ||
| 282 | if (rc) { | ||
| 283 | wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n"); | ||
| 284 | goto out; | ||
| 285 | } | ||
| 286 | /* WMI_SET_APPIE_CMD */ | ||
| 287 | rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); | ||
| 288 | if (rc) { | ||
| 289 | wil_err(wil, "WMI_SET_APPIE_CMD failed\n"); | ||
| 290 | goto out; | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | /* WMI_CONNECT_CMD */ | ||
| 295 | memset(&conn, 0, sizeof(conn)); | ||
| 296 | switch (bss->capability & 0x03) { | ||
| 297 | case WLAN_CAPABILITY_DMG_TYPE_AP: | ||
| 298 | conn.network_type = WMI_NETTYPE_INFRA; | ||
| 299 | break; | ||
| 300 | case WLAN_CAPABILITY_DMG_TYPE_PBSS: | ||
| 301 | conn.network_type = WMI_NETTYPE_P2P; | ||
| 302 | break; | ||
| 303 | default: | ||
| 304 | wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n", | ||
| 305 | bss->capability); | ||
| 306 | goto out; | ||
| 307 | } | ||
| 308 | if (rsn_eid) { | ||
| 309 | conn.dot11_auth_mode = WMI_AUTH11_SHARED; | ||
| 310 | conn.auth_mode = WMI_AUTH_WPA2_PSK; | ||
| 311 | conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP; | ||
| 312 | conn.pairwise_crypto_len = 16; | ||
| 313 | } else { | ||
| 314 | conn.dot11_auth_mode = WMI_AUTH11_OPEN; | ||
| 315 | conn.auth_mode = WMI_AUTH_NONE; | ||
| 316 | } | ||
| 317 | |||
| 318 | conn.ssid_len = min_t(u8, ssid_eid[1], 32); | ||
| 319 | memcpy(conn.ssid, ssid_eid+2, conn.ssid_len); | ||
| 320 | |||
| 321 | ch = bss->channel->hw_value; | ||
| 322 | if (ch == 0) { | ||
| 323 | wil_err(wil, "BSS at unknown frequency %dMhz\n", | ||
| 324 | bss->channel->center_freq); | ||
| 325 | rc = -EOPNOTSUPP; | ||
| 326 | goto out; | ||
| 327 | } | ||
| 328 | conn.channel = ch - 1; | ||
| 329 | |||
| 330 | memcpy(conn.bssid, bss->bssid, 6); | ||
| 331 | memcpy(conn.dst_mac, bss->bssid, 6); | ||
| 332 | /* | ||
| 333 | * FW don't support scan after connection attempt | ||
| 334 | */ | ||
| 335 | set_bit(wil_status_dontscan, &wil->status); | ||
| 336 | |||
| 337 | rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); | ||
| 338 | if (rc == 0) { | ||
| 339 | /* Connect can take lots of time */ | ||
| 340 | mod_timer(&wil->connect_timer, | ||
| 341 | jiffies + msecs_to_jiffies(2000)); | ||
| 342 | } | ||
| 343 | |||
| 344 | out: | ||
| 345 | cfg80211_put_bss(bss); | ||
| 346 | |||
| 347 | return rc; | ||
| 348 | } | ||
| 349 | |||
| 350 | static int wil_cfg80211_disconnect(struct wiphy *wiphy, | ||
| 351 | struct net_device *ndev, | ||
| 352 | u16 reason_code) | ||
| 353 | { | ||
| 354 | int rc; | ||
| 355 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 356 | |||
| 357 | rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); | ||
| 358 | |||
| 359 | return rc; | ||
| 360 | } | ||
| 361 | |||
| 362 | static int wil_cfg80211_set_channel(struct wiphy *wiphy, | ||
| 363 | struct cfg80211_chan_def *chandef) | ||
| 364 | { | ||
| 365 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 366 | struct wireless_dev *wdev = wil->wdev; | ||
| 367 | |||
| 368 | wdev->preset_chandef = *chandef; | ||
| 369 | |||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | static int wil_cfg80211_add_key(struct wiphy *wiphy, | ||
| 374 | struct net_device *ndev, | ||
| 375 | u8 key_index, bool pairwise, | ||
| 376 | const u8 *mac_addr, | ||
| 377 | struct key_params *params) | ||
| 378 | { | ||
| 379 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 380 | |||
| 381 | /* group key is not used */ | ||
| 382 | if (!pairwise) | ||
| 383 | return 0; | ||
| 384 | |||
| 385 | return wmi_add_cipher_key(wil, key_index, mac_addr, | ||
| 386 | params->key_len, params->key); | ||
| 387 | } | ||
| 388 | |||
| 389 | static int wil_cfg80211_del_key(struct wiphy *wiphy, | ||
| 390 | struct net_device *ndev, | ||
| 391 | u8 key_index, bool pairwise, | ||
| 392 | const u8 *mac_addr) | ||
| 393 | { | ||
| 394 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 395 | |||
| 396 | /* group key is not used */ | ||
| 397 | if (!pairwise) | ||
| 398 | return 0; | ||
| 399 | |||
| 400 | return wmi_del_cipher_key(wil, key_index, mac_addr); | ||
| 401 | } | ||
| 402 | |||
| 403 | /* Need to be present or wiphy_new() will WARN */ | ||
| 404 | static int wil_cfg80211_set_default_key(struct wiphy *wiphy, | ||
| 405 | struct net_device *ndev, | ||
| 406 | u8 key_index, bool unicast, | ||
| 407 | bool multicast) | ||
| 408 | { | ||
| 409 | return 0; | ||
| 410 | } | ||
| 411 | |||
| 412 | static int wil_cfg80211_start_ap(struct wiphy *wiphy, | ||
| 413 | struct net_device *ndev, | ||
| 414 | struct cfg80211_ap_settings *info) | ||
| 415 | { | ||
| 416 | int rc = 0; | ||
| 417 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 418 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | ||
| 419 | struct ieee80211_channel *channel = info->chandef.chan; | ||
| 420 | struct cfg80211_beacon_data *bcon = &info->beacon; | ||
| 421 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | ||
| 422 | |||
| 423 | if (!channel) { | ||
| 424 | wil_err(wil, "AP: No channel???\n"); | ||
| 425 | return -EINVAL; | ||
| 426 | } | ||
| 427 | |||
| 428 | wil_dbg(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value, | ||
| 429 | channel->center_freq, info->privacy ? "secure" : "open"); | ||
| 430 | print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, | ||
| 431 | info->ssid, info->ssid_len); | ||
| 432 | |||
| 433 | rc = wil_reset(wil); | ||
| 434 | if (rc) | ||
| 435 | return rc; | ||
| 436 | |||
| 437 | rc = wmi_set_ssid(wil, info->ssid_len, info->ssid); | ||
| 438 | if (rc) | ||
| 439 | return rc; | ||
| 440 | |||
| 441 | rc = wmi_set_channel(wil, channel->hw_value); | ||
| 442 | if (rc) | ||
| 443 | return rc; | ||
| 444 | |||
| 445 | /* MAC address - pre-requisite for other commands */ | ||
| 446 | wmi_set_mac_address(wil, ndev->dev_addr); | ||
| 447 | |||
| 448 | /* IE's */ | ||
| 449 | /* bcon 'head IE's are not relevant for 60g band */ | ||
| 450 | wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, | ||
| 451 | bcon->beacon_ies); | ||
| 452 | wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, | ||
| 453 | bcon->proberesp_ies); | ||
| 454 | wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, | ||
| 455 | bcon->assocresp_ies); | ||
| 456 | |||
| 457 | wil->secure_pcp = info->privacy; | ||
| 458 | |||
| 459 | rc = wmi_set_bcon(wil, info->beacon_interval, wmi_nettype); | ||
| 460 | if (rc) | ||
| 461 | return rc; | ||
| 462 | |||
| 463 | /* Rx VRING. After MAC and beacon */ | ||
| 464 | rc = wil_rx_init(wil); | ||
| 465 | |||
| 466 | netif_carrier_on(ndev); | ||
| 467 | |||
| 468 | return rc; | ||
| 469 | } | ||
| 470 | |||
| 471 | static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | ||
| 472 | struct net_device *ndev) | ||
| 473 | { | ||
| 474 | int rc = 0; | ||
| 475 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
| 476 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | ||
| 477 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | ||
| 478 | |||
| 479 | /* To stop beaconing, set BI to 0 */ | ||
| 480 | rc = wmi_set_bcon(wil, 0, wmi_nettype); | ||
| 481 | |||
| 482 | return rc; | ||
| 483 | } | ||
| 484 | |||
| 485 | static struct cfg80211_ops wil_cfg80211_ops = { | ||
| 486 | .scan = wil_cfg80211_scan, | ||
| 487 | .connect = wil_cfg80211_connect, | ||
| 488 | .disconnect = wil_cfg80211_disconnect, | ||
| 489 | .change_virtual_intf = wil_cfg80211_change_iface, | ||
| 490 | .get_station = wil_cfg80211_get_station, | ||
| 491 | .set_monitor_channel = wil_cfg80211_set_channel, | ||
| 492 | .add_key = wil_cfg80211_add_key, | ||
| 493 | .del_key = wil_cfg80211_del_key, | ||
| 494 | .set_default_key = wil_cfg80211_set_default_key, | ||
| 495 | /* AP mode */ | ||
| 496 | .start_ap = wil_cfg80211_start_ap, | ||
| 497 | .stop_ap = wil_cfg80211_stop_ap, | ||
| 498 | }; | ||
| 499 | |||
| 500 | static void wil_wiphy_init(struct wiphy *wiphy) | ||
| 501 | { | ||
| 502 | /* TODO: set real value */ | ||
| 503 | wiphy->max_scan_ssids = 10; | ||
| 504 | wiphy->max_num_pmkids = 0 /* TODO: */; | ||
| 505 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
| 506 | BIT(NL80211_IFTYPE_AP) | | ||
| 507 | BIT(NL80211_IFTYPE_MONITOR); | ||
| 508 | /* TODO: enable P2P when integrated with supplicant: | ||
| 509 | * BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | ||
| 510 | */ | ||
| 511 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | | ||
| 512 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
| 513 | dev_warn(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", | ||
| 514 | __func__, wiphy->flags); | ||
| 515 | wiphy->probe_resp_offload = | ||
| 516 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | ||
| 517 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | ||
| 518 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | ||
| 519 | |||
| 520 | wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz; | ||
| 521 | |||
| 522 | /* TODO: figure this out */ | ||
| 523 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
| 524 | |||
| 525 | wiphy->cipher_suites = wil_cipher_suites; | ||
| 526 | wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); | ||
| 527 | wiphy->mgmt_stypes = wil_mgmt_stypes; | ||
| 528 | } | ||
| 529 | |||
| 530 | struct wireless_dev *wil_cfg80211_init(struct device *dev) | ||
| 531 | { | ||
| 532 | int rc = 0; | ||
| 533 | struct wireless_dev *wdev; | ||
| 534 | |||
| 535 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
| 536 | if (!wdev) | ||
| 537 | return ERR_PTR(-ENOMEM); | ||
| 538 | |||
| 539 | wdev->wiphy = wiphy_new(&wil_cfg80211_ops, | ||
| 540 | sizeof(struct wil6210_priv)); | ||
| 541 | if (!wdev->wiphy) { | ||
| 542 | rc = -ENOMEM; | ||
| 543 | goto out; | ||
| 544 | } | ||
| 545 | |||
| 546 | set_wiphy_dev(wdev->wiphy, dev); | ||
| 547 | wil_wiphy_init(wdev->wiphy); | ||
| 548 | |||
| 549 | rc = wiphy_register(wdev->wiphy); | ||
| 550 | if (rc < 0) | ||
| 551 | goto out_failed_reg; | ||
| 552 | |||
| 553 | return wdev; | ||
| 554 | |||
| 555 | out_failed_reg: | ||
| 556 | wiphy_free(wdev->wiphy); | ||
| 557 | out: | ||
| 558 | kfree(wdev); | ||
| 559 | |||
| 560 | return ERR_PTR(rc); | ||
| 561 | } | ||
| 562 | |||
| 563 | void wil_wdev_free(struct wil6210_priv *wil) | ||
| 564 | { | ||
| 565 | struct wireless_dev *wdev = wil_to_wdev(wil); | ||
| 566 | |||
| 567 | if (!wdev) | ||
| 568 | return; | ||
| 569 | |||
| 570 | wiphy_unregister(wdev->wiphy); | ||
| 571 | wiphy_free(wdev->wiphy); | ||
| 572 | kfree(wdev); | ||
| 573 | } | ||
| @@ -0,0 +1,30 @@ | |||
| 1 | #ifndef WIL_DBG_HEXDUMP_H_ | ||
| 2 | #define WIL_DBG_HEXDUMP_H_ | ||
| 3 | |||
| 4 | #if defined(CONFIG_DYNAMIC_DEBUG) | ||
| 5 | #define wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ | ||
| 6 | groupsize, buf, len, ascii) \ | ||
| 7 | do { \ | ||
| 8 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, \ | ||
| 9 | __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\ | ||
| 10 | if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ | ||
| 11 | print_hex_dump(KERN_DEBUG, prefix_str, \ | ||
| 12 | prefix_type, rowsize, groupsize, \ | ||
| 13 | buf, len, ascii); \ | ||
| 14 | } while (0) | ||
| 15 | |||
| 16 | #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ | ||
| 17 | groupsize, buf, len, ascii) \ | ||
| 18 | wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ | ||
| 19 | groupsize, buf, len, ascii) | ||
| 20 | |||
| 21 | #define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \ | ||
| 22 | wil_dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true) | ||
| 23 | #else /* defined(CONFIG_DYNAMIC_DEBUG) */ | ||
| 24 | #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ | ||
| 25 | groupsize, buf, len, ascii) \ | ||
| 26 | print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize, \ | ||
| 27 | groupsize, buf, len, ascii) | ||
| 28 | #endif /* defined(CONFIG_DYNAMIC_DEBUG) */ | ||
| 29 | |||
| 30 | #endif /* WIL_DBG_HEXDUMP_H_ */ | ||
| @@ -0,0 +1,603 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/debugfs.h> | ||
| 19 | #include <linux/seq_file.h> | ||
| 20 | #include <linux/pci.h> | ||
| 21 | #include <linux/rtnetlink.h> | ||
| 22 | |||
| 23 | #include "wil6210.h" | ||
| 24 | #include "txrx.h" | ||
| 25 | |||
| 26 | /* Nasty hack. Better have per device instances */ | ||
| 27 | static u32 mem_addr; | ||
| 28 | static u32 dbg_txdesc_index; | ||
| 29 | |||
| 30 | static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, | ||
| 31 | const char *name, struct vring *vring) | ||
| 32 | { | ||
| 33 | void __iomem *x = wmi_addr(wil, vring->hwtail); | ||
| 34 | |||
| 35 | seq_printf(s, "VRING %s = {\n", name); | ||
| 36 | seq_printf(s, " pa = 0x%016llx\n", (unsigned long long)vring->pa); | ||
| 37 | seq_printf(s, " va = 0x%p\n", vring->va); | ||
| 38 | seq_printf(s, " size = %d\n", vring->size); | ||
| 39 | seq_printf(s, " swtail = %d\n", vring->swtail); | ||
| 40 | seq_printf(s, " swhead = %d\n", vring->swhead); | ||
| 41 | seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail); | ||
| 42 | if (x) | ||
| 43 | seq_printf(s, "0x%08x\n", ioread32(x)); | ||
| 44 | else | ||
| 45 | seq_printf(s, "???\n"); | ||
| 46 | |||
| 47 | if (vring->va && (vring->size < 1025)) { | ||
| 48 | uint i; | ||
| 49 | for (i = 0; i < vring->size; i++) { | ||
| 50 | volatile struct vring_tx_desc *d = &vring->va[i].tx; | ||
| 51 | if ((i % 64) == 0 && (i != 0)) | ||
| 52 | seq_printf(s, "\n"); | ||
| 53 | seq_printf(s, "%s", (d->dma.status & BIT(0)) ? | ||
| 54 | "S" : (vring->ctx[i] ? "H" : "h")); | ||
| 55 | } | ||
| 56 | seq_printf(s, "\n"); | ||
| 57 | } | ||
| 58 | seq_printf(s, "}\n"); | ||
| 59 | } | ||
| 60 | |||
| 61 | static int wil_vring_debugfs_show(struct seq_file *s, void *data) | ||
| 62 | { | ||
| 63 | uint i; | ||
| 64 | struct wil6210_priv *wil = s->private; | ||
| 65 | |||
| 66 | wil_print_vring(s, wil, "rx", &wil->vring_rx); | ||
| 67 | |||
| 68 | for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { | ||
| 69 | struct vring *vring = &(wil->vring_tx[i]); | ||
| 70 | if (vring->va) { | ||
| 71 | char name[10]; | ||
| 72 | snprintf(name, sizeof(name), "tx_%2d", i); | ||
| 73 | wil_print_vring(s, wil, name, vring); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | static int wil_vring_seq_open(struct inode *inode, struct file *file) | ||
| 81 | { | ||
| 82 | return single_open(file, wil_vring_debugfs_show, inode->i_private); | ||
| 83 | } | ||
| 84 | |||
| 85 | static const struct file_operations fops_vring = { | ||
| 86 | .open = wil_vring_seq_open, | ||
| 87 | .release = single_release, | ||
| 88 | .read = seq_read, | ||
| 89 | .llseek = seq_lseek, | ||
| 90 | }; | ||
| 91 | |||
| 92 | static void wil_print_ring(struct seq_file *s, const char *prefix, | ||
| 93 | void __iomem *off) | ||
| 94 | { | ||
| 95 | struct wil6210_priv *wil = s->private; | ||
| 96 | struct wil6210_mbox_ring r; | ||
| 97 | int rsize; | ||
| 98 | uint i; | ||
| 99 | |||
| 100 | wil_memcpy_fromio_32(&r, off, sizeof(r)); | ||
| 101 | wil_mbox_ring_le2cpus(&r); | ||
| 102 | /* | ||
| 103 | * we just read memory block from NIC. This memory may be | ||
| 104 | * garbage. Check validity before using it. | ||
| 105 | */ | ||
| 106 | rsize = r.size / sizeof(struct wil6210_mbox_ring_desc); | ||
| 107 | |||
| 108 | seq_printf(s, "ring %s = {\n", prefix); | ||
| 109 | seq_printf(s, " base = 0x%08x\n", r.base); | ||
| 110 | seq_printf(s, " size = 0x%04x bytes -> %d entries\n", r.size, rsize); | ||
| 111 | seq_printf(s, " tail = 0x%08x\n", r.tail); | ||
| 112 | seq_printf(s, " head = 0x%08x\n", r.head); | ||
| 113 | seq_printf(s, " entry size = %d\n", r.entry_size); | ||
| 114 | |||
| 115 | if (r.size % sizeof(struct wil6210_mbox_ring_desc)) { | ||
| 116 | seq_printf(s, " ??? size is not multiple of %zd, garbage?\n", | ||
| 117 | sizeof(struct wil6210_mbox_ring_desc)); | ||
| 118 | goto out; | ||
| 119 | } | ||
| 120 | |||
| 121 | if (!wmi_addr(wil, r.base) || | ||
| 122 | !wmi_addr(wil, r.tail) || | ||
| 123 | !wmi_addr(wil, r.head)) { | ||
| 124 | seq_printf(s, " ??? pointers are garbage?\n"); | ||
| 125 | goto out; | ||
| 126 | } | ||
| 127 | |||
| 128 | for (i = 0; i < rsize; i++) { | ||
| 129 | struct wil6210_mbox_ring_desc d; | ||
| 130 | struct wil6210_mbox_hdr hdr; | ||
| 131 | size_t delta = i * sizeof(d); | ||
| 132 | void __iomem *x = wil->csr + HOSTADDR(r.base) + delta; | ||
| 133 | |||
| 134 | wil_memcpy_fromio_32(&d, x, sizeof(d)); | ||
| 135 | |||
| 136 | seq_printf(s, " [%2x] %s %s%s 0x%08x", i, | ||
| 137 | d.sync ? "F" : "E", | ||
| 138 | (r.tail - r.base == delta) ? "t" : " ", | ||
| 139 | (r.head - r.base == delta) ? "h" : " ", | ||
| 140 | le32_to_cpu(d.addr)); | ||
| 141 | if (0 == wmi_read_hdr(wil, d.addr, &hdr)) { | ||
| 142 | u16 len = le16_to_cpu(hdr.len); | ||
| 143 | seq_printf(s, " -> %04x %04x %04x %02x\n", | ||
| 144 | le16_to_cpu(hdr.seq), len, | ||
| 145 | le16_to_cpu(hdr.type), hdr.flags); | ||
| 146 | if (len <= MAX_MBOXITEM_SIZE) { | ||
| 147 | int n = 0; | ||
| 148 | unsigned char printbuf[16 * 3 + 2]; | ||
| 149 | unsigned char databuf[MAX_MBOXITEM_SIZE]; | ||
| 150 | void __iomem *src = wmi_buffer(wil, d.addr) + | ||
| 151 | sizeof(struct wil6210_mbox_hdr); | ||
| 152 | /* | ||
| 153 | * No need to check @src for validity - | ||
| 154 | * we already validated @d.addr while | ||
| 155 | * reading header | ||
| 156 | */ | ||
| 157 | wil_memcpy_fromio_32(databuf, src, len); | ||
| 158 | while (n < len) { | ||
| 159 | int l = min(len - n, 16); | ||
| 160 | hex_dump_to_buffer(databuf + n, l, | ||
| 161 | 16, 1, printbuf, | ||
| 162 | sizeof(printbuf), | ||
| 163 | false); | ||
| 164 | seq_printf(s, " : %s\n", printbuf); | ||
| 165 | n += l; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | } else { | ||
| 169 | seq_printf(s, "\n"); | ||
| 170 | } | ||
| 171 | } | ||
| 172 | out: | ||
| 173 | seq_printf(s, "}\n"); | ||
| 174 | } | ||
| 175 | |||
| 176 | static int wil_mbox_debugfs_show(struct seq_file *s, void *data) | ||
| 177 | { | ||
| 178 | struct wil6210_priv *wil = s->private; | ||
| 179 | |||
| 180 | wil_print_ring(s, "tx", wil->csr + HOST_MBOX + | ||
| 181 | offsetof(struct wil6210_mbox_ctl, tx)); | ||
| 182 | wil_print_ring(s, "rx", wil->csr + HOST_MBOX + | ||
| 183 | offsetof(struct wil6210_mbox_ctl, rx)); | ||
| 184 | |||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static int wil_mbox_seq_open(struct inode *inode, struct file *file) | ||
| 189 | { | ||
| 190 | return single_open(file, wil_mbox_debugfs_show, inode->i_private); | ||
| 191 | } | ||
| 192 | |||
| 193 | static const struct file_operations fops_mbox = { | ||
| 194 | .open = wil_mbox_seq_open, | ||
| 195 | .release = single_release, | ||
| 196 | .read = seq_read, | ||
| 197 | .llseek = seq_lseek, | ||
| 198 | }; | ||
| 199 | |||
| 200 | static int wil_debugfs_iomem_x32_set(void *data, u64 val) | ||
| 201 | { | ||
| 202 | iowrite32(val, (void __iomem *)data); | ||
| 203 | wmb(); /* make sure write propagated to HW */ | ||
| 204 | |||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | |||
| 208 | static int wil_debugfs_iomem_x32_get(void *data, u64 *val) | ||
| 209 | { | ||
| 210 | *val = ioread32((void __iomem *)data); | ||
| 211 | |||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | |||
| 215 | DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get, | ||
| 216 | wil_debugfs_iomem_x32_set, "0x%08llx\n"); | ||
| 217 | |||
| 218 | static struct dentry *wil_debugfs_create_iomem_x32(const char *name, | ||
| 219 | mode_t mode, | ||
| 220 | struct dentry *parent, | ||
| 221 | void __iomem *value) | ||
| 222 | { | ||
| 223 | return debugfs_create_file(name, mode, parent, (void * __force)value, | ||
| 224 | &fops_iomem_x32); | ||
| 225 | } | ||
| 226 | |||
| 227 | static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, | ||
| 228 | const char *name, | ||
| 229 | struct dentry *parent, u32 off) | ||
| 230 | { | ||
| 231 | struct dentry *d = debugfs_create_dir(name, parent); | ||
| 232 | |||
| 233 | if (IS_ERR_OR_NULL(d)) | ||
| 234 | return -ENODEV; | ||
| 235 | |||
| 236 | wil_debugfs_create_iomem_x32("ICC", S_IRUGO | S_IWUSR, d, | ||
| 237 | wil->csr + off); | ||
| 238 | wil_debugfs_create_iomem_x32("ICR", S_IRUGO | S_IWUSR, d, | ||
| 239 | wil->csr + off + 4); | ||
| 240 | wil_debugfs_create_iomem_x32("ICM", S_IRUGO | S_IWUSR, d, | ||
| 241 | wil->csr + off + 8); | ||
| 242 | wil_debugfs_create_iomem_x32("ICS", S_IWUSR, d, | ||
| 243 | wil->csr + off + 12); | ||
| 244 | wil_debugfs_create_iomem_x32("IMV", S_IRUGO | S_IWUSR, d, | ||
| 245 | wil->csr + off + 16); | ||
| 246 | wil_debugfs_create_iomem_x32("IMS", S_IWUSR, d, | ||
| 247 | wil->csr + off + 20); | ||
| 248 | wil_debugfs_create_iomem_x32("IMC", S_IWUSR, d, | ||
| 249 | wil->csr + off + 24); | ||
| 250 | |||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, | ||
| 255 | struct dentry *parent) | ||
| 256 | { | ||
| 257 | struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent); | ||
| 258 | |||
| 259 | if (IS_ERR_OR_NULL(d)) | ||
| 260 | return -ENODEV; | ||
| 261 | |||
| 262 | wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO, d, wil->csr + | ||
| 263 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); | ||
| 264 | wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO, d, wil->csr + | ||
| 265 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); | ||
| 266 | wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO, d, wil->csr + | ||
| 267 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW)); | ||
| 268 | |||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | |||
| 272 | static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil, | ||
| 273 | struct dentry *parent) | ||
| 274 | { | ||
| 275 | struct dentry *d = debugfs_create_dir("ITR_CNT", parent); | ||
| 276 | |||
| 277 | if (IS_ERR_OR_NULL(d)) | ||
| 278 | return -ENODEV; | ||
| 279 | |||
| 280 | wil_debugfs_create_iomem_x32("TRSH", S_IRUGO, d, wil->csr + | ||
| 281 | HOSTADDR(RGF_DMA_ITR_CNT_TRSH)); | ||
| 282 | wil_debugfs_create_iomem_x32("DATA", S_IRUGO, d, wil->csr + | ||
| 283 | HOSTADDR(RGF_DMA_ITR_CNT_DATA)); | ||
| 284 | wil_debugfs_create_iomem_x32("CTL", S_IRUGO, d, wil->csr + | ||
| 285 | HOSTADDR(RGF_DMA_ITR_CNT_CRL)); | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | static int wil_memread_debugfs_show(struct seq_file *s, void *data) | ||
| 291 | { | ||
| 292 | struct wil6210_priv *wil = s->private; | ||
| 293 | void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr)); | ||
| 294 | |||
| 295 | if (a) | ||
| 296 | seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, ioread32(a)); | ||
| 297 | else | ||
| 298 | seq_printf(s, "[0x%08x] = INVALID\n", mem_addr); | ||
| 299 | |||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int wil_memread_seq_open(struct inode *inode, struct file *file) | ||
| 304 | { | ||
| 305 | return single_open(file, wil_memread_debugfs_show, inode->i_private); | ||
| 306 | } | ||
| 307 | |||
| 308 | static const struct file_operations fops_memread = { | ||
| 309 | .open = wil_memread_seq_open, | ||
| 310 | .release = single_release, | ||
| 311 | .read = seq_read, | ||
| 312 | .llseek = seq_lseek, | ||
| 313 | }; | ||
| 314 | |||
| 315 | static int wil_default_open(struct inode *inode, struct file *file) | ||
| 316 | { | ||
| 317 | if (inode->i_private) | ||
| 318 | file->private_data = inode->i_private; | ||
| 319 | |||
| 320 | return 0; | ||
| 321 | } | ||
| 322 | |||
| 323 | static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, | ||
| 324 | size_t count, loff_t *ppos) | ||
| 325 | { | ||
| 326 | enum { max_count = 4096 }; | ||
| 327 | struct debugfs_blob_wrapper *blob = file->private_data; | ||
| 328 | loff_t pos = *ppos; | ||
| 329 | size_t available = blob->size; | ||
| 330 | void *buf; | ||
| 331 | size_t ret; | ||
| 332 | |||
| 333 | if (pos < 0) | ||
| 334 | return -EINVAL; | ||
| 335 | |||
| 336 | if (pos >= available || !count) | ||
| 337 | return 0; | ||
| 338 | |||
| 339 | if (count > available - pos) | ||
| 340 | count = available - pos; | ||
| 341 | if (count > max_count) | ||
| 342 | count = max_count; | ||
| 343 | |||
| 344 | buf = kmalloc(count, GFP_KERNEL); | ||
| 345 | if (!buf) | ||
| 346 | return -ENOMEM; | ||
| 347 | |||
| 348 | wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data + | ||
| 349 | pos, count); | ||
| 350 | |||
| 351 | ret = copy_to_user(user_buf, buf, count); | ||
| 352 | kfree(buf); | ||
| 353 | if (ret == count) | ||
| 354 | return -EFAULT; | ||
| 355 | |||
| 356 | count -= ret; | ||
| 357 | *ppos = pos + count; | ||
| 358 | |||
| 359 | return count; | ||
| 360 | } | ||
| 361 | |||
| 362 | static const struct file_operations fops_ioblob = { | ||
| 363 | .read = wil_read_file_ioblob, | ||
| 364 | .open = wil_default_open, | ||
| 365 | .llseek = default_llseek, | ||
| 366 | }; | ||
| 367 | |||
| 368 | static | ||
| 369 | struct dentry *wil_debugfs_create_ioblob(const char *name, | ||
| 370 | mode_t mode, | ||
| 371 | struct dentry *parent, | ||
| 372 | struct debugfs_blob_wrapper *blob) | ||
| 373 | { | ||
| 374 | return debugfs_create_file(name, mode, parent, blob, &fops_ioblob); | ||
| 375 | } | ||
| 376 | /*---reset---*/ | ||
| 377 | static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, | ||
| 378 | size_t len, loff_t *ppos) | ||
| 379 | { | ||
| 380 | struct wil6210_priv *wil = file->private_data; | ||
| 381 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 382 | |||
| 383 | /** | ||
| 384 | * BUG: | ||
| 385 | * this code does NOT sync device state with the rest of system | ||
| 386 | * use with care, debug only!!! | ||
| 387 | */ | ||
| 388 | rtnl_lock(); | ||
| 389 | dev_close(ndev); | ||
| 390 | ndev->flags &= ~IFF_UP; | ||
| 391 | rtnl_unlock(); | ||
| 392 | wil_reset(wil); | ||
| 393 | |||
| 394 | return len; | ||
| 395 | } | ||
| 396 | |||
| 397 | static const struct file_operations fops_reset = { | ||
| 398 | .write = wil_write_file_reset, | ||
| 399 | .open = wil_default_open, | ||
| 400 | }; | ||
| 401 | /*---------Tx descriptor------------*/ | ||
| 402 | |||
| 403 | static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) | ||
| 404 | { | ||
| 405 | struct wil6210_priv *wil = s->private; | ||
| 406 | struct vring *vring = &(wil->vring_tx[0]); | ||
| 407 | |||
| 408 | if (!vring->va) { | ||
| 409 | seq_printf(s, "No Tx VRING\n"); | ||
| 410 | return 0; | ||
| 411 | } | ||
| 412 | |||
| 413 | if (dbg_txdesc_index < vring->size) { | ||
| 414 | volatile struct vring_tx_desc *d = | ||
| 415 | &(vring->va[dbg_txdesc_index].tx); | ||
| 416 | volatile u32 *u = (volatile u32 *)d; | ||
| 417 | struct sk_buff *skb = vring->ctx[dbg_txdesc_index]; | ||
| 418 | |||
| 419 | seq_printf(s, "Tx[%3d] = {\n", dbg_txdesc_index); | ||
| 420 | seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n", | ||
| 421 | u[0], u[1], u[2], u[3]); | ||
| 422 | seq_printf(s, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n", | ||
| 423 | u[4], u[5], u[6], u[7]); | ||
| 424 | seq_printf(s, " SKB = %p\n", skb); | ||
| 425 | |||
| 426 | if (skb) { | ||
| 427 | unsigned char printbuf[16 * 3 + 2]; | ||
| 428 | int i = 0; | ||
| 429 | int len = skb_headlen(skb); | ||
| 430 | void *p = skb->data; | ||
| 431 | |||
| 432 | seq_printf(s, " len = %d\n", len); | ||
| 433 | |||
| 434 | while (i < len) { | ||
| 435 | int l = min(len - i, 16); | ||
| 436 | hex_dump_to_buffer(p + i, l, 16, 1, printbuf, | ||
| 437 | sizeof(printbuf), false); | ||
| 438 | seq_printf(s, " : %s\n", printbuf); | ||
| 439 | i += l; | ||
| 440 | } | ||
| 441 | } | ||
| 442 | seq_printf(s, "}\n"); | ||
| 443 | } else { | ||
| 444 | seq_printf(s, "TxDesc index (%d) >= size (%d)\n", | ||
| 445 | dbg_txdesc_index, vring->size); | ||
| 446 | } | ||
| 447 | |||
| 448 | return 0; | ||
| 449 | } | ||
| 450 | |||
| 451 | static int wil_txdesc_seq_open(struct inode *inode, struct file *file) | ||
| 452 | { | ||
| 453 | return single_open(file, wil_txdesc_debugfs_show, inode->i_private); | ||
| 454 | } | ||
| 455 | |||
| 456 | static const struct file_operations fops_txdesc = { | ||
| 457 | .open = wil_txdesc_seq_open, | ||
| 458 | .release = single_release, | ||
| 459 | .read = seq_read, | ||
| 460 | .llseek = seq_lseek, | ||
| 461 | }; | ||
| 462 | |||
| 463 | /*---------beamforming------------*/ | ||
| 464 | static int wil_bf_debugfs_show(struct seq_file *s, void *data) | ||
| 465 | { | ||
| 466 | struct wil6210_priv *wil = s->private; | ||
| 467 | seq_printf(s, | ||
| 468 | "TSF : 0x%016llx\n" | ||
| 469 | "TxMCS : %d\n" | ||
| 470 | "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n", | ||
| 471 | wil->stats.tsf, wil->stats.bf_mcs, | ||
| 472 | wil->stats.my_rx_sector, wil->stats.my_tx_sector, | ||
| 473 | wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); | ||
| 474 | return 0; | ||
| 475 | } | ||
| 476 | |||
| 477 | static int wil_bf_seq_open(struct inode *inode, struct file *file) | ||
| 478 | { | ||
| 479 | return single_open(file, wil_bf_debugfs_show, inode->i_private); | ||
| 480 | } | ||
| 481 | |||
| 482 | static const struct file_operations fops_bf = { | ||
| 483 | .open = wil_bf_seq_open, | ||
| 484 | .release = single_release, | ||
| 485 | .read = seq_read, | ||
| 486 | .llseek = seq_lseek, | ||
| 487 | }; | ||
| 488 | /*---------SSID------------*/ | ||
| 489 | static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf, | ||
| 490 | size_t count, loff_t *ppos) | ||
| 491 | { | ||
| 492 | struct wil6210_priv *wil = file->private_data; | ||
| 493 | struct wireless_dev *wdev = wil_to_wdev(wil); | ||
| 494 | |||
| 495 | return simple_read_from_buffer(user_buf, count, ppos, | ||
| 496 | wdev->ssid, wdev->ssid_len); | ||
| 497 | } | ||
| 498 | |||
| 499 | static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf, | ||
| 500 | size_t count, loff_t *ppos) | ||
| 501 | { | ||
| 502 | struct wil6210_priv *wil = file->private_data; | ||
| 503 | struct wireless_dev *wdev = wil_to_wdev(wil); | ||
| 504 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 505 | |||
| 506 | if (*ppos != 0) { | ||
| 507 | wil_err(wil, "Unable to set SSID substring from [%d]\n", | ||
| 508 | (int)*ppos); | ||
| 509 | return -EINVAL; | ||
| 510 | } | ||
| 511 | |||
| 512 | if (count > sizeof(wdev->ssid)) { | ||
| 513 | wil_err(wil, "SSID too long, len = %d\n", (int)count); | ||
| 514 | return -EINVAL; | ||
| 515 | } | ||
| 516 | if (netif_running(ndev)) { | ||
| 517 | wil_err(wil, "Unable to change SSID on running interface\n"); | ||
| 518 | return -EINVAL; | ||
| 519 | } | ||
| 520 | |||
| 521 | wdev->ssid_len = count; | ||
| 522 | return simple_write_to_buffer(wdev->ssid, wdev->ssid_len, ppos, | ||
| 523 | buf, count); | ||
| 524 | } | ||
| 525 | |||
| 526 | static const struct file_operations fops_ssid = { | ||
| 527 | .read = wil_read_file_ssid, | ||
| 528 | .write = wil_write_file_ssid, | ||
| 529 | .open = wil_default_open, | ||
| 530 | }; | ||
| 531 | |||
| 532 | /*----------------*/ | ||
| 533 | int wil6210_debugfs_init(struct wil6210_priv *wil) | ||
| 534 | { | ||
| 535 | struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, | ||
| 536 | wil_to_wiphy(wil)->debugfsdir); | ||
| 537 | |||
| 538 | if (IS_ERR_OR_NULL(dbg)) | ||
| 539 | return -ENODEV; | ||
| 540 | |||
| 541 | debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox); | ||
| 542 | debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring); | ||
| 543 | debugfs_create_file("txdesc", S_IRUGO, dbg, wil, &fops_txdesc); | ||
| 544 | debugfs_create_u32("txdesc_index", S_IRUGO | S_IWUSR, dbg, | ||
| 545 | &dbg_txdesc_index); | ||
| 546 | debugfs_create_file("bf", S_IRUGO, dbg, wil, &fops_bf); | ||
| 547 | debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid); | ||
| 548 | debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg, | ||
| 549 | &wil->secure_pcp); | ||
| 550 | |||
| 551 | wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg, | ||
| 552 | HOSTADDR(RGF_USER_USER_ICR)); | ||
| 553 | wil6210_debugfs_create_ISR(wil, "DMA_EP_TX_ICR", dbg, | ||
| 554 | HOSTADDR(RGF_DMA_EP_TX_ICR)); | ||
| 555 | wil6210_debugfs_create_ISR(wil, "DMA_EP_RX_ICR", dbg, | ||
| 556 | HOSTADDR(RGF_DMA_EP_RX_ICR)); | ||
| 557 | wil6210_debugfs_create_ISR(wil, "DMA_EP_MISC_ICR", dbg, | ||
| 558 | HOSTADDR(RGF_DMA_EP_MISC_ICR)); | ||
| 559 | wil6210_debugfs_create_pseudo_ISR(wil, dbg); | ||
| 560 | wil6210_debugfs_create_ITR_CNT(wil, dbg); | ||
| 561 | |||
| 562 | debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr); | ||
| 563 | debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); | ||
| 564 | |||
| 565 | debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset); | ||
| 566 | |||
| 567 | wil->rgf_blob.data = (void * __force)wil->csr + 0; | ||
| 568 | wil->rgf_blob.size = 0xa000; | ||
| 569 | wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob); | ||
| 570 | |||
| 571 | wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000; | ||
| 572 | wil->fw_code_blob.size = 0x40000; | ||
| 573 | wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg, | ||
| 574 | &wil->fw_code_blob); | ||
| 575 | |||
| 576 | wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000; | ||
| 577 | wil->fw_data_blob.size = 0x8000; | ||
| 578 | wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg, | ||
| 579 | &wil->fw_data_blob); | ||
| 580 | |||
| 581 | wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000; | ||
| 582 | wil->fw_peri_blob.size = 0x18000; | ||
| 583 | wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg, | ||
| 584 | &wil->fw_peri_blob); | ||
| 585 | |||
| 586 | wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000; | ||
| 587 | wil->uc_code_blob.size = 0x10000; | ||
| 588 | wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg, | ||
| 589 | &wil->uc_code_blob); | ||
| 590 | |||
| 591 | wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000; | ||
| 592 | wil->uc_data_blob.size = 0x4000; | ||
| 593 | wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg, | ||
| 594 | &wil->uc_data_blob); | ||
| 595 | |||
| 596 | return 0; | ||
| 597 | } | ||
| 598 | |||
| 599 | void wil6210_debugfs_remove(struct wil6210_priv *wil) | ||
| 600 | { | ||
| 601 | debugfs_remove_recursive(wil->debug); | ||
| 602 | wil->debug = NULL; | ||
| 603 | } | ||
| @@ -0,0 +1,471 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/interrupt.h> | ||
| 18 | |||
| 19 | #include "wil6210.h" | ||
| 20 | |||
| 21 | /** | ||
| 22 | * Theory of operation: | ||
| 23 | * | ||
| 24 | * There is ISR pseudo-cause register, | ||
| 25 | * dma_rgf->DMA_RGF.PSEUDO_CAUSE.PSEUDO_CAUSE | ||
| 26 | * Its bits represents OR'ed bits from 3 real ISR registers: | ||
| 27 | * TX, RX, and MISC. | ||
| 28 | * | ||
| 29 | * Registers may be configured to either "write 1 to clear" or | ||
| 30 | * "clear on read" mode | ||
| 31 | * | ||
| 32 | * When handling interrupt, one have to mask/unmask interrupts for the | ||
| 33 | * real ISR registers, or hardware may malfunction. | ||
| 34 | * | ||
| 35 | */ | ||
| 36 | |||
| 37 | #define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) | ||
| 38 | #define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE | ||
| 39 | #define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ | ||
| 40 | BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) | ||
| 41 | #define WIL6210_IMC_MISC (ISR_MISC_FW_READY | ISR_MISC_MBOX_EVT) | ||
| 42 | |||
| 43 | #define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \ | ||
| 44 | BIT_DMA_PSEUDO_CAUSE_TX | \ | ||
| 45 | BIT_DMA_PSEUDO_CAUSE_MISC)) | ||
| 46 | |||
| 47 | #if defined(CONFIG_WIL6210_ISR_COR) | ||
| 48 | /* configure to Clear-On-Read mode */ | ||
| 49 | #define WIL_ICR_ICC_VALUE (0xFFFFFFFFUL) | ||
| 50 | |||
| 51 | static inline void wil_icr_clear(u32 x, void __iomem *addr) | ||
| 52 | { | ||
| 53 | |||
| 54 | } | ||
| 55 | #else /* defined(CONFIG_WIL6210_ISR_COR) */ | ||
| 56 | /* configure to Write-1-to-Clear mode */ | ||
| 57 | #define WIL_ICR_ICC_VALUE (0UL) | ||
| 58 | |||
| 59 | static inline void wil_icr_clear(u32 x, void __iomem *addr) | ||
| 60 | { | ||
| 61 | iowrite32(x, addr); | ||
| 62 | } | ||
| 63 | #endif /* defined(CONFIG_WIL6210_ISR_COR) */ | ||
| 64 | |||
| 65 | static inline u32 wil_ioread32_and_clear(void __iomem *addr) | ||
| 66 | { | ||
| 67 | u32 x = ioread32(addr); | ||
| 68 | |||
| 69 | wil_icr_clear(x, addr); | ||
| 70 | |||
| 71 | return x; | ||
| 72 | } | ||
| 73 | |||
| 74 | static void wil6210_mask_irq_tx(struct wil6210_priv *wil) | ||
| 75 | { | ||
| 76 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
| 77 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
| 78 | offsetof(struct RGF_ICR, IMS)); | ||
| 79 | } | ||
| 80 | |||
| 81 | static void wil6210_mask_irq_rx(struct wil6210_priv *wil) | ||
| 82 | { | ||
| 83 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
| 84 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
| 85 | offsetof(struct RGF_ICR, IMS)); | ||
| 86 | } | ||
| 87 | |||
| 88 | static void wil6210_mask_irq_misc(struct wil6210_priv *wil) | ||
| 89 | { | ||
| 90 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
| 91 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
| 92 | offsetof(struct RGF_ICR, IMS)); | ||
| 93 | } | ||
| 94 | |||
| 95 | static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) | ||
| 96 | { | ||
| 97 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
| 98 | |||
| 99 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
| 100 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); | ||
| 101 | |||
| 102 | clear_bit(wil_status_irqen, &wil->status); | ||
| 103 | } | ||
| 104 | |||
| 105 | static void wil6210_unmask_irq_tx(struct wil6210_priv *wil) | ||
| 106 | { | ||
| 107 | iowrite32(WIL6210_IMC_TX, wil->csr + | ||
| 108 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
| 109 | offsetof(struct RGF_ICR, IMC)); | ||
| 110 | } | ||
| 111 | |||
| 112 | static void wil6210_unmask_irq_rx(struct wil6210_priv *wil) | ||
| 113 | { | ||
| 114 | iowrite32(WIL6210_IMC_RX, wil->csr + | ||
| 115 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
| 116 | offsetof(struct RGF_ICR, IMC)); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void wil6210_unmask_irq_misc(struct wil6210_priv *wil) | ||
| 120 | { | ||
| 121 | iowrite32(WIL6210_IMC_MISC, wil->csr + | ||
| 122 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
| 123 | offsetof(struct RGF_ICR, IMC)); | ||
| 124 | } | ||
| 125 | |||
| 126 | static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) | ||
| 127 | { | ||
| 128 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
| 129 | |||
| 130 | set_bit(wil_status_irqen, &wil->status); | ||
| 131 | |||
| 132 | iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr + | ||
| 133 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); | ||
| 134 | } | ||
| 135 | |||
| 136 | void wil6210_disable_irq(struct wil6210_priv *wil) | ||
| 137 | { | ||
| 138 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
| 139 | |||
| 140 | wil6210_mask_irq_tx(wil); | ||
| 141 | wil6210_mask_irq_rx(wil); | ||
| 142 | wil6210_mask_irq_misc(wil); | ||
| 143 | wil6210_mask_irq_pseudo(wil); | ||
| 144 | } | ||
| 145 | |||
| 146 | void wil6210_enable_irq(struct wil6210_priv *wil) | ||
| 147 | { | ||
| 148 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
| 149 | |||
| 150 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
| 151 | offsetof(struct RGF_ICR, ICC)); | ||
| 152 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
| 153 | offsetof(struct RGF_ICR, ICC)); | ||
| 154 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
| 155 | offsetof(struct RGF_ICR, ICC)); | ||
| 156 | |||
| 157 | wil6210_unmask_irq_pseudo(wil); | ||
| 158 | wil6210_unmask_irq_tx(wil); | ||
| 159 | wil6210_unmask_irq_rx(wil); | ||
| 160 | wil6210_unmask_irq_misc(wil); | ||
| 161 | } | ||
| 162 | |||
| 163 | static irqreturn_t wil6210_irq_rx(int irq, void *cookie) | ||
| 164 | { | ||
| 165 | struct wil6210_priv *wil = cookie; | ||
| 166 | u32 isr = wil_ioread32_and_clear(wil->csr + | ||
| 167 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
| 168 | offsetof(struct RGF_ICR, ICR)); | ||
| 169 | |||
| 170 | wil_dbg_IRQ(wil, "ISR RX 0x%08x\n", isr); | ||
| 171 | |||
| 172 | if (!isr) { | ||
| 173 | wil_err(wil, "spurious IRQ: RX\n"); | ||
| 174 | return IRQ_NONE; | ||
| 175 | } | ||
| 176 | |||
| 177 | wil6210_mask_irq_rx(wil); | ||
| 178 | |||
| 179 | if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { | ||
| 180 | wil_dbg_IRQ(wil, "RX done\n"); | ||
| 181 | isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; | ||
| 182 | wil_rx_handle(wil); | ||
| 183 | } | ||
| 184 | |||
| 185 | if (isr) | ||
| 186 | wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr); | ||
| 187 | |||
| 188 | wil6210_unmask_irq_rx(wil); | ||
| 189 | |||
| 190 | return IRQ_HANDLED; | ||
| 191 | } | ||
| 192 | |||
| 193 | static irqreturn_t wil6210_irq_tx(int irq, void *cookie) | ||
| 194 | { | ||
| 195 | struct wil6210_priv *wil = cookie; | ||
| 196 | u32 isr = wil_ioread32_and_clear(wil->csr + | ||
| 197 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
| 198 | offsetof(struct RGF_ICR, ICR)); | ||
| 199 | |||
| 200 | wil_dbg_IRQ(wil, "ISR TX 0x%08x\n", isr); | ||
| 201 | |||
| 202 | if (!isr) { | ||
| 203 | wil_err(wil, "spurious IRQ: TX\n"); | ||
| 204 | return IRQ_NONE; | ||
| 205 | } | ||
| 206 | |||
| 207 | wil6210_mask_irq_tx(wil); | ||
| 208 | |||
| 209 | if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { | ||
| 210 | uint i; | ||
| 211 | wil_dbg_IRQ(wil, "TX done\n"); | ||
| 212 | isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; | ||
| 213 | for (i = 0; i < 24; i++) { | ||
| 214 | u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i); | ||
| 215 | if (isr & mask) { | ||
| 216 | isr &= ~mask; | ||
| 217 | wil_dbg_IRQ(wil, "TX done(%i)\n", i); | ||
| 218 | wil_tx_complete(wil, i); | ||
| 219 | } | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | if (isr) | ||
| 224 | wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr); | ||
| 225 | |||
| 226 | wil6210_unmask_irq_tx(wil); | ||
| 227 | |||
| 228 | return IRQ_HANDLED; | ||
| 229 | } | ||
| 230 | |||
| 231 | static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | ||
| 232 | { | ||
| 233 | struct wil6210_priv *wil = cookie; | ||
| 234 | u32 isr = wil_ioread32_and_clear(wil->csr + | ||
| 235 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
| 236 | offsetof(struct RGF_ICR, ICR)); | ||
| 237 | |||
| 238 | wil_dbg_IRQ(wil, "ISR MISC 0x%08x\n", isr); | ||
| 239 | |||
| 240 | if (!isr) { | ||
| 241 | wil_err(wil, "spurious IRQ: MISC\n"); | ||
| 242 | return IRQ_NONE; | ||
| 243 | } | ||
| 244 | |||
| 245 | wil6210_mask_irq_misc(wil); | ||
| 246 | |||
| 247 | if (isr & ISR_MISC_FW_READY) { | ||
| 248 | wil_dbg_IRQ(wil, "IRQ: FW ready\n"); | ||
| 249 | /** | ||
| 250 | * Actual FW ready indicated by the | ||
| 251 | * WMI_FW_READY_EVENTID | ||
| 252 | */ | ||
| 253 | isr &= ~ISR_MISC_FW_READY; | ||
| 254 | } | ||
| 255 | |||
| 256 | wil->isr_misc = isr; | ||
| 257 | |||
| 258 | if (isr) { | ||
| 259 | return IRQ_WAKE_THREAD; | ||
| 260 | } else { | ||
| 261 | wil6210_unmask_irq_misc(wil); | ||
| 262 | return IRQ_HANDLED; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) | ||
| 267 | { | ||
| 268 | struct wil6210_priv *wil = cookie; | ||
| 269 | u32 isr = wil->isr_misc; | ||
| 270 | |||
| 271 | wil_dbg_IRQ(wil, "Thread ISR MISC 0x%08x\n", isr); | ||
| 272 | |||
| 273 | if (isr & ISR_MISC_MBOX_EVT) { | ||
| 274 | wil_dbg_IRQ(wil, "MBOX event\n"); | ||
| 275 | wmi_recv_cmd(wil); | ||
| 276 | isr &= ~ISR_MISC_MBOX_EVT; | ||
| 277 | } | ||
| 278 | |||
| 279 | if (isr) | ||
| 280 | wil_err(wil, "un-handled MISC ISR bits 0x%08x\n", isr); | ||
| 281 | |||
| 282 | wil->isr_misc = 0; | ||
| 283 | |||
| 284 | wil6210_unmask_irq_misc(wil); | ||
| 285 | |||
| 286 | return IRQ_HANDLED; | ||
| 287 | } | ||
| 288 | |||
| 289 | /** | ||
| 290 | * thread IRQ handler | ||
| 291 | */ | ||
| 292 | static irqreturn_t wil6210_thread_irq(int irq, void *cookie) | ||
| 293 | { | ||
| 294 | struct wil6210_priv *wil = cookie; | ||
| 295 | |||
| 296 | wil_dbg_IRQ(wil, "Thread IRQ\n"); | ||
| 297 | /* Discover real IRQ cause */ | ||
| 298 | if (wil->isr_misc) | ||
| 299 | wil6210_irq_misc_thread(irq, cookie); | ||
| 300 | |||
| 301 | wil6210_unmask_irq_pseudo(wil); | ||
| 302 | |||
| 303 | return IRQ_HANDLED; | ||
| 304 | } | ||
| 305 | |||
| 306 | /* DEBUG | ||
| 307 | * There is subtle bug in hardware that causes IRQ to raise when it should be | ||
| 308 | * masked. It is quite rare and hard to debug. | ||
| 309 | * | ||
| 310 | * Catch irq issue if it happens and print all I can. | ||
| 311 | */ | ||
| 312 | static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause) | ||
| 313 | { | ||
| 314 | if (!test_bit(wil_status_irqen, &wil->status)) { | ||
| 315 | u32 icm_rx = wil_ioread32_and_clear(wil->csr + | ||
| 316 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
| 317 | offsetof(struct RGF_ICR, ICM)); | ||
| 318 | u32 icr_rx = wil_ioread32_and_clear(wil->csr + | ||
| 319 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
| 320 | offsetof(struct RGF_ICR, ICR)); | ||
| 321 | u32 imv_rx = ioread32(wil->csr + | ||
| 322 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
| 323 | offsetof(struct RGF_ICR, IMV)); | ||
| 324 | u32 icm_tx = wil_ioread32_and_clear(wil->csr + | ||
| 325 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
| 326 | offsetof(struct RGF_ICR, ICM)); | ||
| 327 | u32 icr_tx = wil_ioread32_and_clear(wil->csr + | ||
| 328 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
| 329 | offsetof(struct RGF_ICR, ICR)); | ||
| 330 | u32 imv_tx = ioread32(wil->csr + | ||
| 331 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
| 332 | offsetof(struct RGF_ICR, IMV)); | ||
| 333 | u32 icm_misc = wil_ioread32_and_clear(wil->csr + | ||
| 334 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
| 335 | offsetof(struct RGF_ICR, ICM)); | ||
| 336 | u32 icr_misc = wil_ioread32_and_clear(wil->csr + | ||
| 337 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
| 338 | offsetof(struct RGF_ICR, ICR)); | ||
| 339 | u32 imv_misc = ioread32(wil->csr + | ||
| 340 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
| 341 | offsetof(struct RGF_ICR, IMV)); | ||
| 342 | wil_err(wil, "IRQ when it should be masked: pseudo 0x%08x\n" | ||
| 343 | "Rx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" | ||
| 344 | "Tx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" | ||
| 345 | "Misc icm:icr:imv 0x%08x 0x%08x 0x%08x\n", | ||
| 346 | pseudo_cause, | ||
| 347 | icm_rx, icr_rx, imv_rx, | ||
| 348 | icm_tx, icr_tx, imv_tx, | ||
| 349 | icm_misc, icr_misc, imv_misc); | ||
| 350 | |||
| 351 | return -EINVAL; | ||
| 352 | } | ||
| 353 | |||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | static irqreturn_t wil6210_hardirq(int irq, void *cookie) | ||
| 358 | { | ||
| 359 | irqreturn_t rc = IRQ_HANDLED; | ||
| 360 | struct wil6210_priv *wil = cookie; | ||
| 361 | u32 pseudo_cause = ioread32(wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); | ||
| 362 | |||
| 363 | /** | ||
| 364 | * pseudo_cause is Clear-On-Read, no need to ACK | ||
| 365 | */ | ||
| 366 | if ((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff)) | ||
| 367 | return IRQ_NONE; | ||
| 368 | |||
| 369 | /* FIXME: IRQ mask debug */ | ||
| 370 | if (wil6210_debug_irq_mask(wil, pseudo_cause)) | ||
| 371 | return IRQ_NONE; | ||
| 372 | |||
| 373 | wil6210_mask_irq_pseudo(wil); | ||
| 374 | |||
| 375 | /* Discover real IRQ cause | ||
| 376 | * There are 2 possible phases for every IRQ: | ||
| 377 | * - hard IRQ handler called right here | ||
| 378 | * - threaded handler called later | ||
| 379 | * | ||
| 380 | * Hard IRQ handler reads and clears ISR. | ||
| 381 | * | ||
| 382 | * If threaded handler requested, hard IRQ handler | ||
| 383 | * returns IRQ_WAKE_THREAD and saves ISR register value | ||
| 384 | * for the threaded handler use. | ||
| 385 | * | ||
| 386 | * voting for wake thread - need at least 1 vote | ||
| 387 | */ | ||
| 388 | if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) && | ||
| 389 | (wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD)) | ||
| 390 | rc = IRQ_WAKE_THREAD; | ||
| 391 | |||
| 392 | if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) && | ||
| 393 | (wil6210_irq_tx(irq, cookie) == IRQ_WAKE_THREAD)) | ||
| 394 | rc = IRQ_WAKE_THREAD; | ||
| 395 | |||
| 396 | if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) && | ||
| 397 | (wil6210_irq_misc(irq, cookie) == IRQ_WAKE_THREAD)) | ||
| 398 | rc = IRQ_WAKE_THREAD; | ||
| 399 | |||
| 400 | /* if thread is requested, it will unmask IRQ */ | ||
| 401 | if (rc != IRQ_WAKE_THREAD) | ||
| 402 | wil6210_unmask_irq_pseudo(wil); | ||
| 403 | |||
| 404 | wil_dbg_IRQ(wil, "Hard IRQ 0x%08x\n", pseudo_cause); | ||
| 405 | |||
| 406 | return rc; | ||
| 407 | } | ||
| 408 | |||
| 409 | static int wil6210_request_3msi(struct wil6210_priv *wil, int irq) | ||
| 410 | { | ||
| 411 | int rc; | ||
| 412 | /* | ||
| 413 | * IRQ's are in the following order: | ||
| 414 | * - Tx | ||
| 415 | * - Rx | ||
| 416 | * - Misc | ||
| 417 | */ | ||
| 418 | |||
| 419 | rc = request_irq(irq, wil6210_irq_tx, IRQF_SHARED, | ||
| 420 | WIL_NAME"_tx", wil); | ||
| 421 | if (rc) | ||
| 422 | return rc; | ||
| 423 | |||
| 424 | rc = request_irq(irq + 1, wil6210_irq_rx, IRQF_SHARED, | ||
| 425 | WIL_NAME"_rx", wil); | ||
| 426 | if (rc) | ||
| 427 | goto free0; | ||
| 428 | |||
| 429 | rc = request_threaded_irq(irq + 2, wil6210_irq_misc, | ||
| 430 | wil6210_irq_misc_thread, | ||
| 431 | IRQF_SHARED, WIL_NAME"_misc", wil); | ||
| 432 | if (rc) | ||
| 433 | goto free1; | ||
| 434 | |||
| 435 | return 0; | ||
| 436 | /* error branch */ | ||
| 437 | free1: | ||
| 438 | free_irq(irq + 1, wil); | ||
| 439 | free0: | ||
| 440 | free_irq(irq, wil); | ||
| 441 | |||
| 442 | return rc; | ||
| 443 | } | ||
| 444 | |||
| 445 | int wil6210_init_irq(struct wil6210_priv *wil, int irq) | ||
| 446 | { | ||
| 447 | int rc; | ||
| 448 | if (wil->n_msi == 3) | ||
| 449 | rc = wil6210_request_3msi(wil, irq); | ||
| 450 | else | ||
| 451 | rc = request_threaded_irq(irq, wil6210_hardirq, | ||
| 452 | wil6210_thread_irq, | ||
| 453 | wil->n_msi ? 0 : IRQF_SHARED, | ||
| 454 | WIL_NAME, wil); | ||
| 455 | if (rc) | ||
| 456 | return rc; | ||
| 457 | |||
| 458 | wil6210_enable_irq(wil); | ||
| 459 | |||
| 460 | return 0; | ||
| 461 | } | ||
| 462 | |||
| 463 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq) | ||
| 464 | { | ||
| 465 | wil6210_disable_irq(wil); | ||
| 466 | free_irq(irq, wil); | ||
| 467 | if (wil->n_msi == 3) { | ||
| 468 | free_irq(irq + 1, wil); | ||
| 469 | free_irq(irq + 2, wil); | ||
| 470 | } | ||
| 471 | } | ||
| @@ -0,0 +1,407 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/netdevice.h> | ||
| 19 | #include <linux/sched.h> | ||
| 20 | #include <linux/ieee80211.h> | ||
| 21 | #include <linux/wireless.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | #include <linux/moduleparam.h> | ||
| 24 | #include <linux/if_arp.h> | ||
| 25 | |||
| 26 | #include "wil6210.h" | ||
| 27 | |||
| 28 | /* | ||
| 29 | * Due to a hardware issue, | ||
| 30 | * one has to read/write to/from NIC in 32-bit chunks; | ||
| 31 | * regular memcpy_fromio and siblings will | ||
| 32 | * not work on 64-bit platform - it uses 64-bit transactions | ||
| 33 | * | ||
| 34 | * Force 32-bit transactions to enable NIC on 64-bit platforms | ||
| 35 | * | ||
| 36 | * To avoid byte swap on big endian host, __raw_{read|write}l | ||
| 37 | * should be used - {read|write}l would swap bytes to provide | ||
| 38 | * little endian on PCI value in host endianness. | ||
| 39 | */ | ||
| 40 | void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, | ||
| 41 | size_t count) | ||
| 42 | { | ||
| 43 | u32 *d = dst; | ||
| 44 | const volatile u32 __iomem *s = src; | ||
| 45 | |||
| 46 | /* size_t is unsigned, if (count%4 != 0) it will wrap */ | ||
| 47 | for (count += 4; count > 4; count -= 4) | ||
| 48 | *d++ = __raw_readl(s++); | ||
| 49 | } | ||
| 50 | |||
| 51 | void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | ||
| 52 | size_t count) | ||
| 53 | { | ||
| 54 | volatile u32 __iomem *d = dst; | ||
| 55 | const u32 *s = src; | ||
| 56 | |||
| 57 | for (count += 4; count > 4; count -= 4) | ||
| 58 | __raw_writel(*s++, d++); | ||
| 59 | } | ||
| 60 | |||
| 61 | static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) | ||
| 62 | { | ||
| 63 | uint i; | ||
| 64 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 65 | struct wireless_dev *wdev = wil->wdev; | ||
| 66 | |||
| 67 | wil_dbg(wil, "%s()\n", __func__); | ||
| 68 | |||
| 69 | wil_link_off(wil); | ||
| 70 | clear_bit(wil_status_fwconnected, &wil->status); | ||
| 71 | |||
| 72 | switch (wdev->sme_state) { | ||
| 73 | case CFG80211_SME_CONNECTED: | ||
| 74 | cfg80211_disconnected(ndev, WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
| 75 | NULL, 0, GFP_KERNEL); | ||
| 76 | break; | ||
| 77 | case CFG80211_SME_CONNECTING: | ||
| 78 | cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, | ||
| 79 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
| 80 | GFP_KERNEL); | ||
| 81 | break; | ||
| 82 | default: | ||
| 83 | ; | ||
| 84 | } | ||
| 85 | |||
| 86 | for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) | ||
| 87 | wil_vring_fini_tx(wil, i); | ||
| 88 | } | ||
| 89 | |||
| 90 | static void wil_disconnect_worker(struct work_struct *work) | ||
| 91 | { | ||
| 92 | struct wil6210_priv *wil = container_of(work, | ||
| 93 | struct wil6210_priv, disconnect_worker); | ||
| 94 | |||
| 95 | _wil6210_disconnect(wil, NULL); | ||
| 96 | } | ||
| 97 | |||
| 98 | static void wil_connect_timer_fn(ulong x) | ||
| 99 | { | ||
| 100 | struct wil6210_priv *wil = (void *)x; | ||
| 101 | |||
| 102 | wil_dbg(wil, "Connect timeout\n"); | ||
| 103 | |||
| 104 | /* reschedule to thread context - disconnect won't | ||
| 105 | * run from atomic context | ||
| 106 | */ | ||
| 107 | schedule_work(&wil->disconnect_worker); | ||
| 108 | } | ||
| 109 | |||
| 110 | int wil_priv_init(struct wil6210_priv *wil) | ||
| 111 | { | ||
| 112 | wil_dbg(wil, "%s()\n", __func__); | ||
| 113 | |||
| 114 | mutex_init(&wil->mutex); | ||
| 115 | mutex_init(&wil->wmi_mutex); | ||
| 116 | |||
| 117 | init_completion(&wil->wmi_ready); | ||
| 118 | |||
| 119 | wil->pending_connect_cid = -1; | ||
| 120 | setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); | ||
| 121 | |||
| 122 | INIT_WORK(&wil->wmi_connect_worker, wmi_connect_worker); | ||
| 123 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); | ||
| 124 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); | ||
| 125 | |||
| 126 | INIT_LIST_HEAD(&wil->pending_wmi_ev); | ||
| 127 | spin_lock_init(&wil->wmi_ev_lock); | ||
| 128 | |||
| 129 | wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi"); | ||
| 130 | if (!wil->wmi_wq) | ||
| 131 | return -EAGAIN; | ||
| 132 | |||
| 133 | wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect"); | ||
| 134 | if (!wil->wmi_wq_conn) { | ||
| 135 | destroy_workqueue(wil->wmi_wq); | ||
| 136 | return -EAGAIN; | ||
| 137 | } | ||
| 138 | |||
| 139 | /* make shadow copy of registers that should not change on run time */ | ||
| 140 | wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, | ||
| 141 | sizeof(struct wil6210_mbox_ctl)); | ||
| 142 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); | ||
| 143 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid) | ||
| 149 | { | ||
| 150 | del_timer_sync(&wil->connect_timer); | ||
| 151 | _wil6210_disconnect(wil, bssid); | ||
| 152 | } | ||
| 153 | |||
| 154 | void wil_priv_deinit(struct wil6210_priv *wil) | ||
| 155 | { | ||
| 156 | cancel_work_sync(&wil->disconnect_worker); | ||
| 157 | wil6210_disconnect(wil, NULL); | ||
| 158 | wmi_event_flush(wil); | ||
| 159 | destroy_workqueue(wil->wmi_wq_conn); | ||
| 160 | destroy_workqueue(wil->wmi_wq); | ||
| 161 | } | ||
| 162 | |||
| 163 | static void wil_target_reset(struct wil6210_priv *wil) | ||
| 164 | { | ||
| 165 | wil_dbg(wil, "Resetting...\n"); | ||
| 166 | |||
| 167 | /* register write */ | ||
| 168 | #define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a)) | ||
| 169 | /* register set = read, OR, write */ | ||
| 170 | #define S(a, v) iowrite32(ioread32(wil->csr + HOSTADDR(a)) | v, \ | ||
| 171 | wil->csr + HOSTADDR(a)) | ||
| 172 | |||
| 173 | /* hpal_perst_from_pad_src_n_mask */ | ||
| 174 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); | ||
| 175 | /* car_perst_rst_src_n_mask */ | ||
| 176 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); | ||
| 177 | |||
| 178 | W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ | ||
| 179 | W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ | ||
| 180 | |||
| 181 | msleep(100); | ||
| 182 | |||
| 183 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); | ||
| 184 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); | ||
| 185 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); | ||
| 186 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); | ||
| 187 | |||
| 188 | msleep(100); | ||
| 189 | |||
| 190 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); | ||
| 191 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); | ||
| 192 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); | ||
| 193 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | ||
| 194 | |||
| 195 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); | ||
| 196 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); | ||
| 197 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | ||
| 198 | |||
| 199 | msleep(2000); | ||
| 200 | |||
| 201 | W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */ | ||
| 202 | |||
| 203 | msleep(2000); | ||
| 204 | |||
| 205 | wil_dbg(wil, "Reset completed\n"); | ||
| 206 | |||
| 207 | #undef W | ||
| 208 | #undef S | ||
| 209 | } | ||
| 210 | |||
| 211 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) | ||
| 212 | { | ||
| 213 | le32_to_cpus(&r->base); | ||
| 214 | le16_to_cpus(&r->entry_size); | ||
| 215 | le16_to_cpus(&r->size); | ||
| 216 | le32_to_cpus(&r->tail); | ||
| 217 | le32_to_cpus(&r->head); | ||
| 218 | } | ||
| 219 | |||
| 220 | static int wil_wait_for_fw_ready(struct wil6210_priv *wil) | ||
| 221 | { | ||
| 222 | ulong to = msecs_to_jiffies(1000); | ||
| 223 | ulong left = wait_for_completion_timeout(&wil->wmi_ready, to); | ||
| 224 | if (0 == left) { | ||
| 225 | wil_err(wil, "Firmware not ready\n"); | ||
| 226 | return -ETIME; | ||
| 227 | } else { | ||
| 228 | wil_dbg(wil, "FW ready after %d ms\n", | ||
| 229 | jiffies_to_msecs(to-left)); | ||
| 230 | } | ||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | /* | ||
| 235 | * We reset all the structures, and we reset the UMAC. | ||
| 236 | * After calling this routine, you're expected to reload | ||
| 237 | * the firmware. | ||
| 238 | */ | ||
| 239 | int wil_reset(struct wil6210_priv *wil) | ||
| 240 | { | ||
| 241 | int rc; | ||
| 242 | |||
| 243 | cancel_work_sync(&wil->disconnect_worker); | ||
| 244 | wil6210_disconnect(wil, NULL); | ||
| 245 | |||
| 246 | wmi_event_flush(wil); | ||
| 247 | |||
| 248 | flush_workqueue(wil->wmi_wq); | ||
| 249 | flush_workqueue(wil->wmi_wq_conn); | ||
| 250 | |||
| 251 | wil6210_disable_irq(wil); | ||
| 252 | wil->status = 0; | ||
| 253 | |||
| 254 | /* TODO: put MAC in reset */ | ||
| 255 | wil_target_reset(wil); | ||
| 256 | |||
| 257 | /* init after reset */ | ||
| 258 | wil->pending_connect_cid = -1; | ||
| 259 | INIT_COMPLETION(wil->wmi_ready); | ||
| 260 | |||
| 261 | /* make shadow copy of registers that should not change on run time */ | ||
| 262 | wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, | ||
| 263 | sizeof(struct wil6210_mbox_ctl)); | ||
| 264 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); | ||
| 265 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); | ||
| 266 | |||
| 267 | /* TODO: release MAC reset */ | ||
| 268 | wil6210_enable_irq(wil); | ||
| 269 | |||
| 270 | /* we just started MAC, wait for FW ready */ | ||
| 271 | rc = wil_wait_for_fw_ready(wil); | ||
| 272 | |||
| 273 | return rc; | ||
| 274 | } | ||
| 275 | |||
| 276 | |||
| 277 | void wil_link_on(struct wil6210_priv *wil) | ||
| 278 | { | ||
| 279 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 280 | |||
| 281 | wil_dbg(wil, "%s()\n", __func__); | ||
| 282 | |||
| 283 | netif_carrier_on(ndev); | ||
| 284 | netif_tx_wake_all_queues(ndev); | ||
| 285 | } | ||
| 286 | |||
| 287 | void wil_link_off(struct wil6210_priv *wil) | ||
| 288 | { | ||
| 289 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 290 | |||
| 291 | wil_dbg(wil, "%s()\n", __func__); | ||
| 292 | |||
| 293 | netif_tx_stop_all_queues(ndev); | ||
| 294 | netif_carrier_off(ndev); | ||
| 295 | } | ||
| 296 | |||
| 297 | static int __wil_up(struct wil6210_priv *wil) | ||
| 298 | { | ||
| 299 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 300 | struct wireless_dev *wdev = wil->wdev; | ||
| 301 | struct ieee80211_channel *channel = wdev->preset_chandef.chan; | ||
| 302 | int rc; | ||
| 303 | int bi; | ||
| 304 | u16 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | ||
| 305 | |||
| 306 | rc = wil_reset(wil); | ||
| 307 | if (rc) | ||
| 308 | return rc; | ||
| 309 | |||
| 310 | /* FIXME Firmware works now in PBSS mode(ToDS=0, FromDS=0) */ | ||
| 311 | wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC); | ||
| 312 | switch (wdev->iftype) { | ||
| 313 | case NL80211_IFTYPE_STATION: | ||
| 314 | wil_dbg(wil, "type: STATION\n"); | ||
| 315 | bi = 0; | ||
| 316 | ndev->type = ARPHRD_ETHER; | ||
| 317 | break; | ||
| 318 | case NL80211_IFTYPE_AP: | ||
| 319 | wil_dbg(wil, "type: AP\n"); | ||
| 320 | bi = 100; | ||
| 321 | ndev->type = ARPHRD_ETHER; | ||
| 322 | break; | ||
| 323 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 324 | wil_dbg(wil, "type: P2P_CLIENT\n"); | ||
| 325 | bi = 0; | ||
| 326 | ndev->type = ARPHRD_ETHER; | ||
| 327 | break; | ||
| 328 | case NL80211_IFTYPE_P2P_GO: | ||
| 329 | wil_dbg(wil, "type: P2P_GO\n"); | ||
| 330 | bi = 100; | ||
| 331 | ndev->type = ARPHRD_ETHER; | ||
| 332 | break; | ||
| 333 | case NL80211_IFTYPE_MONITOR: | ||
| 334 | wil_dbg(wil, "type: Monitor\n"); | ||
| 335 | bi = 0; | ||
| 336 | ndev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
| 337 | /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */ | ||
| 338 | break; | ||
| 339 | default: | ||
| 340 | return -EOPNOTSUPP; | ||
| 341 | } | ||
| 342 | |||
| 343 | /* Apply profile in the following order: */ | ||
| 344 | /* SSID and channel for the AP */ | ||
| 345 | switch (wdev->iftype) { | ||
| 346 | case NL80211_IFTYPE_AP: | ||
| 347 | case NL80211_IFTYPE_P2P_GO: | ||
| 348 | if (wdev->ssid_len == 0) { | ||
| 349 | wil_err(wil, "SSID not set\n"); | ||
| 350 | return -EINVAL; | ||
| 351 | } | ||
| 352 | wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid); | ||
| 353 | if (channel) | ||
| 354 | wmi_set_channel(wil, channel->hw_value); | ||
| 355 | break; | ||
| 356 | default: | ||
| 357 | ; | ||
| 358 | } | ||
| 359 | |||
| 360 | /* MAC address - pre-requisite for other commands */ | ||
| 361 | wmi_set_mac_address(wil, ndev->dev_addr); | ||
| 362 | |||
| 363 | /* Set up beaconing if required. */ | ||
| 364 | rc = wmi_set_bcon(wil, bi, wmi_nettype); | ||
| 365 | if (rc) | ||
| 366 | return rc; | ||
| 367 | |||
| 368 | /* Rx VRING. After MAC and beacon */ | ||
| 369 | wil_rx_init(wil); | ||
| 370 | |||
| 371 | return 0; | ||
| 372 | } | ||
| 373 | |||
| 374 | int wil_up(struct wil6210_priv *wil) | ||
| 375 | { | ||
| 376 | int rc; | ||
| 377 | |||
| 378 | mutex_lock(&wil->mutex); | ||
| 379 | rc = __wil_up(wil); | ||
| 380 | mutex_unlock(&wil->mutex); | ||
| 381 | |||
| 382 | return rc; | ||
| 383 | } | ||
| 384 | |||
| 385 | static int __wil_down(struct wil6210_priv *wil) | ||
| 386 | { | ||
| 387 | if (wil->scan_request) { | ||
| 388 | cfg80211_scan_done(wil->scan_request, true); | ||
| 389 | wil->scan_request = NULL; | ||
| 390 | } | ||
| 391 | |||
| 392 | wil6210_disconnect(wil, NULL); | ||
| 393 | wil_rx_fini(wil); | ||
| 394 | |||
| 395 | return 0; | ||
| 396 | } | ||
| 397 | |||
| 398 | int wil_down(struct wil6210_priv *wil) | ||
| 399 | { | ||
| 400 | int rc; | ||
| 401 | |||
| 402 | mutex_lock(&wil->mutex); | ||
| 403 | rc = __wil_down(wil); | ||
| 404 | mutex_unlock(&wil->mutex); | ||
| 405 | |||
| 406 | return rc; | ||
| 407 | } | ||
| @@ -0,0 +1,157 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/netdevice.h> | ||
| 19 | #include <linux/etherdevice.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | |||
| 22 | #include "wil6210.h" | ||
| 23 | |||
| 24 | static int wil_open(struct net_device *ndev) | ||
| 25 | { | ||
| 26 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
| 27 | |||
| 28 | return wil_up(wil); | ||
| 29 | } | ||
| 30 | |||
| 31 | static int wil_stop(struct net_device *ndev) | ||
| 32 | { | ||
| 33 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
| 34 | |||
| 35 | return wil_down(wil); | ||
| 36 | } | ||
| 37 | |||
| 38 | /* | ||
| 39 | * AC to queue mapping | ||
| 40 | * | ||
| 41 | * AC_VO -> queue 3 | ||
| 42 | * AC_VI -> queue 2 | ||
| 43 | * AC_BE -> queue 1 | ||
| 44 | * AC_BK -> queue 0 | ||
| 45 | */ | ||
| 46 | static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb) | ||
| 47 | { | ||
| 48 | static const u16 wil_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; | ||
| 49 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
| 50 | u16 rc; | ||
| 51 | |||
| 52 | skb->priority = cfg80211_classify8021d(skb); | ||
| 53 | |||
| 54 | rc = wil_1d_to_queue[skb->priority]; | ||
| 55 | |||
| 56 | wil_dbg_TXRX(wil, "%s() %d -> %d\n", __func__, (int)skb->priority, | ||
| 57 | (int)rc); | ||
| 58 | |||
| 59 | return rc; | ||
| 60 | } | ||
| 61 | |||
| 62 | static const struct net_device_ops wil_netdev_ops = { | ||
| 63 | .ndo_open = wil_open, | ||
| 64 | .ndo_stop = wil_stop, | ||
| 65 | .ndo_start_xmit = wil_start_xmit, | ||
| 66 | .ndo_select_queue = wil_select_queue, | ||
| 67 | .ndo_set_mac_address = eth_mac_addr, | ||
| 68 | .ndo_validate_addr = eth_validate_addr, | ||
| 69 | }; | ||
| 70 | |||
| 71 | void *wil_if_alloc(struct device *dev, void __iomem *csr) | ||
| 72 | { | ||
| 73 | struct net_device *ndev; | ||
| 74 | struct wireless_dev *wdev; | ||
| 75 | struct wil6210_priv *wil; | ||
| 76 | struct ieee80211_channel *ch; | ||
| 77 | int rc = 0; | ||
| 78 | |||
| 79 | wdev = wil_cfg80211_init(dev); | ||
| 80 | if (IS_ERR(wdev)) { | ||
| 81 | dev_err(dev, "wil_cfg80211_init failed\n"); | ||
| 82 | return wdev; | ||
| 83 | } | ||
| 84 | |||
| 85 | wil = wdev_to_wil(wdev); | ||
| 86 | wil->csr = csr; | ||
| 87 | wil->wdev = wdev; | ||
| 88 | |||
| 89 | rc = wil_priv_init(wil); | ||
| 90 | if (rc) { | ||
| 91 | dev_err(dev, "wil_priv_init failed\n"); | ||
| 92 | goto out_wdev; | ||
| 93 | } | ||
| 94 | |||
| 95 | wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ | ||
| 96 | /* default monitor channel */ | ||
| 97 | ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; | ||
| 98 | cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); | ||
| 99 | |||
| 100 | ndev = alloc_netdev_mqs(0, "wlan%d", ether_setup, WIL6210_TX_QUEUES, 1); | ||
| 101 | if (!ndev) { | ||
| 102 | dev_err(dev, "alloc_netdev_mqs failed\n"); | ||
| 103 | rc = -ENOMEM; | ||
| 104 | goto out_priv; | ||
| 105 | } | ||
| 106 | |||
| 107 | ndev->netdev_ops = &wil_netdev_ops; | ||
| 108 | ndev->ieee80211_ptr = wdev; | ||
| 109 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); | ||
| 110 | wdev->netdev = ndev; | ||
| 111 | |||
| 112 | wil_link_off(wil); | ||
| 113 | |||
| 114 | return wil; | ||
| 115 | |||
| 116 | out_priv: | ||
| 117 | wil_priv_deinit(wil); | ||
| 118 | |||
| 119 | out_wdev: | ||
| 120 | wil_wdev_free(wil); | ||
| 121 | |||
| 122 | return ERR_PTR(rc); | ||
| 123 | } | ||
| 124 | |||
| 125 | void wil_if_free(struct wil6210_priv *wil) | ||
| 126 | { | ||
| 127 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 128 | if (!ndev) | ||
| 129 | return; | ||
| 130 | |||
| 131 | free_netdev(ndev); | ||
| 132 | wil_priv_deinit(wil); | ||
| 133 | wil_wdev_free(wil); | ||
| 134 | } | ||
| 135 | |||
| 136 | int wil_if_add(struct wil6210_priv *wil) | ||
| 137 | { | ||
| 138 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 139 | int rc; | ||
| 140 | |||
| 141 | rc = register_netdev(ndev); | ||
| 142 | if (rc < 0) { | ||
| 143 | dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); | ||
| 144 | return rc; | ||
| 145 | } | ||
| 146 | |||
| 147 | wil_link_off(wil); | ||
| 148 | |||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | void wil_if_remove(struct wil6210_priv *wil) | ||
| 153 | { | ||
| 154 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 155 | |||
| 156 | unregister_netdev(ndev); | ||
| 157 | } | ||
| @@ -0,0 +1,223 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/netdevice.h> | ||
| 21 | #include <linux/debugfs.h> | ||
| 22 | #include <linux/pci.h> | ||
| 23 | #include <linux/moduleparam.h> | ||
| 24 | |||
| 25 | #include "wil6210.h" | ||
| 26 | |||
| 27 | static int use_msi = 1; | ||
| 28 | module_param(use_msi, int, S_IRUGO); | ||
| 29 | MODULE_PARM_DESC(use_msi, | ||
| 30 | " Use MSI interrupt: " | ||
| 31 | "0 - don't, 1 - (default) - single, or 3"); | ||
| 32 | |||
| 33 | /* Bus ops */ | ||
| 34 | static int wil_if_pcie_enable(struct wil6210_priv *wil) | ||
| 35 | { | ||
| 36 | struct pci_dev *pdev = wil->pdev; | ||
| 37 | int rc; | ||
| 38 | |||
| 39 | pci_set_master(pdev); | ||
| 40 | |||
| 41 | /* | ||
| 42 | * how many MSI interrupts to request? | ||
| 43 | */ | ||
| 44 | switch (use_msi) { | ||
| 45 | case 3: | ||
| 46 | case 1: | ||
| 47 | case 0: | ||
| 48 | break; | ||
| 49 | default: | ||
| 50 | wil_err(wil, "Invalid use_msi=%d, default to 1\n", | ||
| 51 | use_msi); | ||
| 52 | use_msi = 1; | ||
| 53 | } | ||
| 54 | wil->n_msi = use_msi; | ||
| 55 | if (wil->n_msi) { | ||
| 56 | wil_dbg(wil, "Setup %d MSI interrupts\n", use_msi); | ||
| 57 | rc = pci_enable_msi_block(pdev, wil->n_msi); | ||
| 58 | if (rc && (wil->n_msi == 3)) { | ||
| 59 | wil_err(wil, "3 MSI mode failed, try 1 MSI\n"); | ||
| 60 | wil->n_msi = 1; | ||
| 61 | rc = pci_enable_msi_block(pdev, wil->n_msi); | ||
| 62 | } | ||
| 63 | if (rc) { | ||
| 64 | wil_err(wil, "pci_enable_msi failed, use INTx\n"); | ||
| 65 | wil->n_msi = 0; | ||
| 66 | } | ||
| 67 | } else { | ||
| 68 | wil_dbg(wil, "MSI interrupts disabled, use INTx\n"); | ||
| 69 | } | ||
| 70 | |||
| 71 | rc = wil6210_init_irq(wil, pdev->irq); | ||
| 72 | if (rc) | ||
| 73 | goto stop_master; | ||
| 74 | |||
| 75 | /* need reset here to obtain MAC */ | ||
| 76 | rc = wil_reset(wil); | ||
| 77 | if (rc) | ||
| 78 | goto release_irq; | ||
| 79 | |||
| 80 | return 0; | ||
| 81 | |||
| 82 | release_irq: | ||
| 83 | wil6210_fini_irq(wil, pdev->irq); | ||
| 84 | /* safe to call if no MSI */ | ||
| 85 | pci_disable_msi(pdev); | ||
| 86 | stop_master: | ||
| 87 | pci_clear_master(pdev); | ||
| 88 | return rc; | ||
| 89 | } | ||
| 90 | |||
| 91 | static int wil_if_pcie_disable(struct wil6210_priv *wil) | ||
| 92 | { | ||
| 93 | struct pci_dev *pdev = wil->pdev; | ||
| 94 | |||
| 95 | pci_clear_master(pdev); | ||
| 96 | /* disable and release IRQ */ | ||
| 97 | wil6210_fini_irq(wil, pdev->irq); | ||
| 98 | /* safe to call if no MSI */ | ||
| 99 | pci_disable_msi(pdev); | ||
| 100 | /* TODO: disable HW */ | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
| 106 | { | ||
| 107 | struct wil6210_priv *wil; | ||
| 108 | struct device *dev = &pdev->dev; | ||
| 109 | void __iomem *csr; | ||
| 110 | int rc; | ||
| 111 | |||
| 112 | /* check HW */ | ||
| 113 | dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n", | ||
| 114 | (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); | ||
| 115 | |||
| 116 | if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { | ||
| 117 | dev_err(&pdev->dev, "Not " WIL_NAME "? " | ||
| 118 | "BAR0 size is %lu while expecting %lu\n", | ||
| 119 | (ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE); | ||
| 120 | return -ENODEV; | ||
| 121 | } | ||
| 122 | |||
| 123 | rc = pci_enable_device(pdev); | ||
| 124 | if (rc) { | ||
| 125 | dev_err(&pdev->dev, "pci_enable_device failed\n"); | ||
| 126 | return -ENODEV; | ||
| 127 | } | ||
| 128 | /* rollback to err_disable_pdev */ | ||
| 129 | |||
| 130 | rc = pci_request_region(pdev, 0, WIL_NAME); | ||
| 131 | if (rc) { | ||
| 132 | dev_err(&pdev->dev, "pci_request_region failed\n"); | ||
| 133 | goto err_disable_pdev; | ||
| 134 | } | ||
| 135 | /* rollback to err_release_reg */ | ||
| 136 | |||
| 137 | csr = pci_ioremap_bar(pdev, 0); | ||
| 138 | if (!csr) { | ||
| 139 | dev_err(&pdev->dev, "pci_ioremap_bar failed\n"); | ||
| 140 | rc = -ENODEV; | ||
| 141 | goto err_release_reg; | ||
| 142 | } | ||
| 143 | /* rollback to err_iounmap */ | ||
| 144 | dev_info(&pdev->dev, "CSR at %pR -> %p\n", &pdev->resource[0], csr); | ||
| 145 | |||
| 146 | wil = wil_if_alloc(dev, csr); | ||
| 147 | if (IS_ERR(wil)) { | ||
| 148 | rc = (int)PTR_ERR(wil); | ||
| 149 | dev_err(dev, "wil_if_alloc failed: %d\n", rc); | ||
| 150 | goto err_iounmap; | ||
| 151 | } | ||
| 152 | /* rollback to if_free */ | ||
| 153 | |||
| 154 | pci_set_drvdata(pdev, wil); | ||
| 155 | wil->pdev = pdev; | ||
| 156 | |||
| 157 | /* FW should raise IRQ when ready */ | ||
| 158 | rc = wil_if_pcie_enable(wil); | ||
| 159 | if (rc) { | ||
| 160 | wil_err(wil, "Enable device failed\n"); | ||
| 161 | goto if_free; | ||
| 162 | } | ||
| 163 | /* rollback to bus_disable */ | ||
| 164 | |||
| 165 | rc = wil_if_add(wil); | ||
| 166 | if (rc) { | ||
| 167 | wil_err(wil, "wil_if_add failed: %d\n", rc); | ||
| 168 | goto bus_disable; | ||
| 169 | } | ||
| 170 | |||
| 171 | wil6210_debugfs_init(wil); | ||
| 172 | |||
| 173 | /* check FW is alive */ | ||
| 174 | wmi_echo(wil); | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | |||
| 178 | bus_disable: | ||
| 179 | wil_if_pcie_disable(wil); | ||
| 180 | if_free: | ||
| 181 | wil_if_free(wil); | ||
| 182 | err_iounmap: | ||
| 183 | pci_iounmap(pdev, csr); | ||
| 184 | err_release_reg: | ||
| 185 | pci_release_region(pdev, 0); | ||
| 186 | err_disable_pdev: | ||
| 187 | pci_disable_device(pdev); | ||
| 188 | |||
| 189 | return rc; | ||
| 190 | } | ||
| 191 | |||
| 192 | static void wil_pcie_remove(struct pci_dev *pdev) | ||
| 193 | { | ||
| 194 | struct wil6210_priv *wil = pci_get_drvdata(pdev); | ||
| 195 | |||
| 196 | wil6210_debugfs_remove(wil); | ||
| 197 | wil_if_pcie_disable(wil); | ||
| 198 | wil_if_remove(wil); | ||
| 199 | wil_if_free(wil); | ||
| 200 | pci_iounmap(pdev, wil->csr); | ||
| 201 | pci_release_region(pdev, 0); | ||
| 202 | pci_disable_device(pdev); | ||
| 203 | pci_set_drvdata(pdev, NULL); | ||
| 204 | } | ||
| 205 | |||
| 206 | static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { | ||
| 207 | { PCI_DEVICE(0x1ae9, 0x0301) }, | ||
| 208 | { /* end: all zeroes */ }, | ||
| 209 | }; | ||
| 210 | MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); | ||
| 211 | |||
| 212 | static struct pci_driver wil6210_driver = { | ||
| 213 | .probe = wil_pcie_probe, | ||
| 214 | .remove = wil_pcie_remove, | ||
| 215 | .id_table = wil6210_pcie_ids, | ||
| 216 | .name = WIL_NAME, | ||
| 217 | }; | ||
| 218 | |||
| 219 | module_pci_driver(wil6210_driver); | ||
| 220 | |||
| 221 | MODULE_LICENSE("Dual BSD/GPL"); | ||
| 222 | MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>"); | ||
| 223 | MODULE_DESCRIPTION("Driver for 60g WiFi WIL6210 card"); | ||
| @@ -0,0 +1,871 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/netdevice.h> | ||
| 19 | #include <linux/etherdevice.h> | ||
| 20 | #include <linux/hardirq.h> | ||
| 21 | #include <net/ieee80211_radiotap.h> | ||
| 22 | #include <linux/if_arp.h> | ||
| 23 | #include <linux/moduleparam.h> | ||
| 24 | |||
| 25 | #include "wil6210.h" | ||
| 26 | #include "wmi.h" | ||
| 27 | #include "txrx.h" | ||
| 28 | |||
| 29 | static bool rtap_include_phy_info; | ||
| 30 | module_param(rtap_include_phy_info, bool, S_IRUGO); | ||
| 31 | MODULE_PARM_DESC(rtap_include_phy_info, | ||
| 32 | " Include PHY info in the radiotap header, default - no"); | ||
| 33 | |||
| 34 | static inline int wil_vring_is_empty(struct vring *vring) | ||
| 35 | { | ||
| 36 | return vring->swhead == vring->swtail; | ||
| 37 | } | ||
| 38 | |||
| 39 | static inline u32 wil_vring_next_tail(struct vring *vring) | ||
| 40 | { | ||
| 41 | return (vring->swtail + 1) % vring->size; | ||
| 42 | } | ||
| 43 | |||
| 44 | static inline void wil_vring_advance_head(struct vring *vring, int n) | ||
| 45 | { | ||
| 46 | vring->swhead = (vring->swhead + n) % vring->size; | ||
| 47 | } | ||
| 48 | |||
| 49 | static inline int wil_vring_is_full(struct vring *vring) | ||
| 50 | { | ||
| 51 | return wil_vring_next_tail(vring) == vring->swhead; | ||
| 52 | } | ||
| 53 | /* | ||
| 54 | * Available space in Tx Vring | ||
| 55 | */ | ||
| 56 | static inline int wil_vring_avail_tx(struct vring *vring) | ||
| 57 | { | ||
| 58 | u32 swhead = vring->swhead; | ||
| 59 | u32 swtail = vring->swtail; | ||
| 60 | int used = (vring->size + swhead - swtail) % vring->size; | ||
| 61 | |||
| 62 | return vring->size - used - 1; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) | ||
| 66 | { | ||
| 67 | struct device *dev = wil_to_dev(wil); | ||
| 68 | size_t sz = vring->size * sizeof(vring->va[0]); | ||
| 69 | uint i; | ||
| 70 | |||
| 71 | BUILD_BUG_ON(sizeof(vring->va[0]) != 32); | ||
| 72 | |||
| 73 | vring->swhead = 0; | ||
| 74 | vring->swtail = 0; | ||
| 75 | vring->ctx = kzalloc(vring->size * sizeof(vring->ctx[0]), GFP_KERNEL); | ||
| 76 | if (!vring->ctx) { | ||
| 77 | wil_err(wil, "vring_alloc [%d] failed to alloc ctx mem\n", | ||
| 78 | vring->size); | ||
| 79 | vring->va = NULL; | ||
| 80 | return -ENOMEM; | ||
| 81 | } | ||
| 82 | /* | ||
| 83 | * vring->va should be aligned on its size rounded up to power of 2 | ||
| 84 | * This is granted by the dma_alloc_coherent | ||
| 85 | */ | ||
| 86 | vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL); | ||
| 87 | if (!vring->va) { | ||
| 88 | wil_err(wil, "vring_alloc [%d] failed to alloc DMA mem\n", | ||
| 89 | vring->size); | ||
| 90 | kfree(vring->ctx); | ||
| 91 | vring->ctx = NULL; | ||
| 92 | return -ENOMEM; | ||
| 93 | } | ||
| 94 | /* initially, all descriptors are SW owned | ||
| 95 | * For Tx and Rx, ownership bit is at the same location, thus | ||
| 96 | * we can use any | ||
| 97 | */ | ||
| 98 | for (i = 0; i < vring->size; i++) { | ||
| 99 | volatile struct vring_tx_desc *d = &(vring->va[i].tx); | ||
| 100 | d->dma.status = TX_DMA_STATUS_DU; | ||
| 101 | } | ||
| 102 | |||
| 103 | wil_dbg(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size, | ||
| 104 | vring->va, (unsigned long long)vring->pa, vring->ctx); | ||
| 105 | |||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, | ||
| 110 | int tx) | ||
| 111 | { | ||
| 112 | struct device *dev = wil_to_dev(wil); | ||
| 113 | size_t sz = vring->size * sizeof(vring->va[0]); | ||
| 114 | |||
| 115 | while (!wil_vring_is_empty(vring)) { | ||
| 116 | if (tx) { | ||
| 117 | volatile struct vring_tx_desc *d = | ||
| 118 | &vring->va[vring->swtail].tx; | ||
| 119 | dma_addr_t pa = d->dma.addr_low | | ||
| 120 | ((u64)d->dma.addr_high << 32); | ||
| 121 | struct sk_buff *skb = vring->ctx[vring->swtail]; | ||
| 122 | if (skb) { | ||
| 123 | dma_unmap_single(dev, pa, d->dma.length, | ||
| 124 | DMA_TO_DEVICE); | ||
| 125 | dev_kfree_skb_any(skb); | ||
| 126 | vring->ctx[vring->swtail] = NULL; | ||
| 127 | } else { | ||
| 128 | dma_unmap_page(dev, pa, d->dma.length, | ||
| 129 | DMA_TO_DEVICE); | ||
| 130 | } | ||
| 131 | vring->swtail = wil_vring_next_tail(vring); | ||
| 132 | } else { /* rx */ | ||
| 133 | volatile struct vring_rx_desc *d = | ||
| 134 | &vring->va[vring->swtail].rx; | ||
| 135 | dma_addr_t pa = d->dma.addr_low | | ||
| 136 | ((u64)d->dma.addr_high << 32); | ||
| 137 | struct sk_buff *skb = vring->ctx[vring->swhead]; | ||
| 138 | dma_unmap_single(dev, pa, d->dma.length, | ||
| 139 | DMA_FROM_DEVICE); | ||
| 140 | kfree_skb(skb); | ||
| 141 | wil_vring_advance_head(vring, 1); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | dma_free_coherent(dev, sz, (void *)vring->va, vring->pa); | ||
| 145 | kfree(vring->ctx); | ||
| 146 | vring->pa = 0; | ||
| 147 | vring->va = NULL; | ||
| 148 | vring->ctx = NULL; | ||
| 149 | } | ||
| 150 | |||
| 151 | /** | ||
| 152 | * Allocate one skb for Rx VRING | ||
| 153 | * | ||
| 154 | * Safe to call from IRQ | ||
| 155 | */ | ||
| 156 | static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, | ||
| 157 | u32 i, int headroom) | ||
| 158 | { | ||
| 159 | struct device *dev = wil_to_dev(wil); | ||
| 160 | unsigned int sz = RX_BUF_LEN; | ||
| 161 | volatile struct vring_rx_desc *d = &(vring->va[i].rx); | ||
| 162 | dma_addr_t pa; | ||
| 163 | |||
| 164 | /* TODO align */ | ||
| 165 | struct sk_buff *skb = dev_alloc_skb(sz + headroom); | ||
| 166 | if (unlikely(!skb)) | ||
| 167 | return -ENOMEM; | ||
| 168 | |||
| 169 | skb_reserve(skb, headroom); | ||
| 170 | skb_put(skb, sz); | ||
| 171 | |||
| 172 | pa = dma_map_single(dev, skb->data, skb->len, DMA_FROM_DEVICE); | ||
| 173 | if (unlikely(dma_mapping_error(dev, pa))) { | ||
| 174 | kfree_skb(skb); | ||
| 175 | return -ENOMEM; | ||
| 176 | } | ||
| 177 | |||
| 178 | d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT; | ||
| 179 | d->dma.addr_low = lower_32_bits(pa); | ||
| 180 | d->dma.addr_high = (u16)upper_32_bits(pa); | ||
| 181 | /* ip_length don't care */ | ||
| 182 | /* b11 don't care */ | ||
| 183 | /* error don't care */ | ||
| 184 | d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ | ||
| 185 | d->dma.length = sz; | ||
| 186 | vring->ctx[i] = skb; | ||
| 187 | |||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | /** | ||
| 192 | * Adds radiotap header | ||
| 193 | * | ||
| 194 | * Any error indicated as "Bad FCS" | ||
| 195 | * | ||
| 196 | * Vendor data for 04:ce:14-1 (Wilocity-1) consists of: | ||
| 197 | * - Rx descriptor: 32 bytes | ||
| 198 | * - Phy info | ||
| 199 | */ | ||
| 200 | static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, | ||
| 201 | struct sk_buff *skb, | ||
| 202 | volatile struct vring_rx_desc *d) | ||
| 203 | { | ||
| 204 | struct wireless_dev *wdev = wil->wdev; | ||
| 205 | struct wil6210_rtap { | ||
| 206 | struct ieee80211_radiotap_header rthdr; | ||
| 207 | /* fields should be in the order of bits in rthdr.it_present */ | ||
| 208 | /* flags */ | ||
| 209 | u8 flags; | ||
| 210 | /* channel */ | ||
| 211 | __le16 chnl_freq __aligned(2); | ||
| 212 | __le16 chnl_flags; | ||
| 213 | /* MCS */ | ||
| 214 | u8 mcs_present; | ||
| 215 | u8 mcs_flags; | ||
| 216 | u8 mcs_index; | ||
| 217 | } __packed; | ||
| 218 | struct wil6210_rtap_vendor { | ||
| 219 | struct wil6210_rtap rtap; | ||
| 220 | /* vendor */ | ||
| 221 | u8 vendor_oui[3] __aligned(2); | ||
| 222 | u8 vendor_ns; | ||
| 223 | __le16 vendor_skip; | ||
| 224 | u8 vendor_data[0]; | ||
| 225 | } __packed; | ||
| 226 | struct wil6210_rtap_vendor *rtap_vendor; | ||
| 227 | int rtap_len = sizeof(struct wil6210_rtap); | ||
| 228 | int phy_length = 0; /* phy info header size, bytes */ | ||
| 229 | static char phy_data[128]; | ||
| 230 | struct ieee80211_channel *ch = wdev->preset_chandef.chan; | ||
| 231 | |||
| 232 | if (rtap_include_phy_info) { | ||
| 233 | rtap_len = sizeof(*rtap_vendor) + sizeof(*d); | ||
| 234 | /* calculate additional length */ | ||
| 235 | if (d->dma.status & RX_DMA_STATUS_PHY_INFO) { | ||
| 236 | /** | ||
| 237 | * PHY info starts from 8-byte boundary | ||
| 238 | * there are 8-byte lines, last line may be partially | ||
| 239 | * written (HW bug), thus FW configures for last line | ||
| 240 | * to be excessive. Driver skips this last line. | ||
| 241 | */ | ||
| 242 | int len = min_t(int, 8 + sizeof(phy_data), | ||
| 243 | wil_rxdesc_phy_length(d)); | ||
| 244 | if (len > 8) { | ||
| 245 | void *p = skb_tail_pointer(skb); | ||
| 246 | void *pa = PTR_ALIGN(p, 8); | ||
| 247 | if (skb_tailroom(skb) >= len + (pa - p)) { | ||
| 248 | phy_length = len - 8; | ||
| 249 | memcpy(phy_data, pa, phy_length); | ||
| 250 | } | ||
| 251 | } | ||
| 252 | } | ||
| 253 | rtap_len += phy_length; | ||
| 254 | } | ||
| 255 | |||
| 256 | if (skb_headroom(skb) < rtap_len && | ||
| 257 | pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) { | ||
| 258 | wil_err(wil, "Unable to expand headrom to %d\n", rtap_len); | ||
| 259 | return; | ||
| 260 | } | ||
| 261 | |||
| 262 | rtap_vendor = (void *)skb_push(skb, rtap_len); | ||
| 263 | memset(rtap_vendor, 0, rtap_len); | ||
| 264 | |||
| 265 | rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION; | ||
| 266 | rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len); | ||
| 267 | rtap_vendor->rtap.rthdr.it_present = cpu_to_le32( | ||
| 268 | (1 << IEEE80211_RADIOTAP_FLAGS) | | ||
| 269 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
| 270 | (1 << IEEE80211_RADIOTAP_MCS)); | ||
| 271 | if (d->dma.status & RX_DMA_STATUS_ERROR) | ||
| 272 | rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS; | ||
| 273 | |||
| 274 | rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); | ||
| 275 | rtap_vendor->rtap.chnl_flags = cpu_to_le16(0); | ||
| 276 | |||
| 277 | rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; | ||
| 278 | rtap_vendor->rtap.mcs_flags = 0; | ||
| 279 | rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d); | ||
| 280 | |||
| 281 | if (rtap_include_phy_info) { | ||
| 282 | rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 << | ||
| 283 | IEEE80211_RADIOTAP_VENDOR_NAMESPACE); | ||
| 284 | /* OUI for Wilocity 04:ce:14 */ | ||
| 285 | rtap_vendor->vendor_oui[0] = 0x04; | ||
| 286 | rtap_vendor->vendor_oui[1] = 0xce; | ||
| 287 | rtap_vendor->vendor_oui[2] = 0x14; | ||
| 288 | rtap_vendor->vendor_ns = 1; | ||
| 289 | /* Rx descriptor + PHY data */ | ||
| 290 | rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) + | ||
| 291 | phy_length); | ||
| 292 | memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d)); | ||
| 293 | memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data, | ||
| 294 | phy_length); | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | /* | ||
| 299 | * Fast swap in place between 2 registers | ||
| 300 | */ | ||
| 301 | static void wil_swap_u16(u16 *a, u16 *b) | ||
| 302 | { | ||
| 303 | *a ^= *b; | ||
| 304 | *b ^= *a; | ||
| 305 | *a ^= *b; | ||
| 306 | } | ||
| 307 | |||
| 308 | static void wil_swap_ethaddr(void *data) | ||
| 309 | { | ||
| 310 | struct ethhdr *eth = data; | ||
| 311 | u16 *s = (u16 *)eth->h_source; | ||
| 312 | u16 *d = (u16 *)eth->h_dest; | ||
| 313 | |||
| 314 | wil_swap_u16(s++, d++); | ||
| 315 | wil_swap_u16(s++, d++); | ||
| 316 | wil_swap_u16(s, d); | ||
| 317 | } | ||
| 318 | |||
| 319 | /** | ||
| 320 | * reap 1 frame from @swhead | ||
| 321 | * | ||
| 322 | * Safe to call from IRQ | ||
| 323 | */ | ||
| 324 | static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | ||
| 325 | struct vring *vring) | ||
| 326 | { | ||
| 327 | struct device *dev = wil_to_dev(wil); | ||
| 328 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 329 | volatile struct vring_rx_desc *d; | ||
| 330 | struct sk_buff *skb; | ||
| 331 | dma_addr_t pa; | ||
| 332 | unsigned int sz = RX_BUF_LEN; | ||
| 333 | u8 ftype; | ||
| 334 | u8 ds_bits; | ||
| 335 | |||
| 336 | if (wil_vring_is_empty(vring)) | ||
| 337 | return NULL; | ||
| 338 | |||
| 339 | d = &(vring->va[vring->swhead].rx); | ||
| 340 | if (!(d->dma.status & RX_DMA_STATUS_DU)) { | ||
| 341 | /* it is not error, we just reached end of Rx done area */ | ||
| 342 | return NULL; | ||
| 343 | } | ||
| 344 | |||
| 345 | pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); | ||
| 346 | skb = vring->ctx[vring->swhead]; | ||
| 347 | dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); | ||
| 348 | skb_trim(skb, d->dma.length); | ||
| 349 | |||
| 350 | wil->stats.last_mcs_rx = wil_rxdesc_mcs(d); | ||
| 351 | |||
| 352 | /* use radiotap header only if required */ | ||
| 353 | if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) | ||
| 354 | wil_rx_add_radiotap_header(wil, skb, d); | ||
| 355 | |||
| 356 | wil_dbg_TXRX(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length); | ||
| 357 | wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_NONE, 32, 4, | ||
| 358 | (const void *)d, sizeof(*d), false); | ||
| 359 | |||
| 360 | wil_vring_advance_head(vring, 1); | ||
| 361 | |||
| 362 | /* no extra checks if in sniffer mode */ | ||
| 363 | if (ndev->type != ARPHRD_ETHER) | ||
| 364 | return skb; | ||
| 365 | /* | ||
| 366 | * Non-data frames may be delivered through Rx DMA channel (ex: BAR) | ||
| 367 | * Driver should recognize it by frame type, that is found | ||
| 368 | * in Rx descriptor. If type is not data, it is 802.11 frame as is | ||
| 369 | */ | ||
| 370 | ftype = wil_rxdesc_ftype(d) << 2; | ||
| 371 | if (ftype != IEEE80211_FTYPE_DATA) { | ||
| 372 | wil_dbg_TXRX(wil, "Non-data frame ftype 0x%08x\n", ftype); | ||
| 373 | /* TODO: process it */ | ||
| 374 | kfree_skb(skb); | ||
| 375 | return NULL; | ||
| 376 | } | ||
| 377 | |||
| 378 | if (skb->len < ETH_HLEN) { | ||
| 379 | wil_err(wil, "Short frame, len = %d\n", skb->len); | ||
| 380 | /* TODO: process it (i.e. BAR) */ | ||
| 381 | kfree_skb(skb); | ||
| 382 | return NULL; | ||
| 383 | } | ||
| 384 | |||
| 385 | ds_bits = wil_rxdesc_ds_bits(d); | ||
| 386 | if (ds_bits == 1) { | ||
| 387 | /* | ||
| 388 | * HW bug - in ToDS mode, i.e. Rx on AP side, | ||
| 389 | * addresses get swapped | ||
| 390 | */ | ||
| 391 | wil_swap_ethaddr(skb->data); | ||
| 392 | } | ||
| 393 | |||
| 394 | return skb; | ||
| 395 | } | ||
| 396 | |||
| 397 | /** | ||
| 398 | * allocate and fill up to @count buffers in rx ring | ||
| 399 | * buffers posted at @swtail | ||
| 400 | */ | ||
| 401 | static int wil_rx_refill(struct wil6210_priv *wil, int count) | ||
| 402 | { | ||
| 403 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 404 | struct vring *v = &wil->vring_rx; | ||
| 405 | u32 next_tail; | ||
| 406 | int rc = 0; | ||
| 407 | int headroom = ndev->type == ARPHRD_IEEE80211_RADIOTAP ? | ||
| 408 | WIL6210_RTAP_SIZE : 0; | ||
| 409 | |||
| 410 | for (; next_tail = wil_vring_next_tail(v), | ||
| 411 | (next_tail != v->swhead) && (count-- > 0); | ||
| 412 | v->swtail = next_tail) { | ||
| 413 | rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom); | ||
| 414 | if (rc) { | ||
| 415 | wil_err(wil, "Error %d in wil_rx_refill[%d]\n", | ||
| 416 | rc, v->swtail); | ||
| 417 | break; | ||
| 418 | } | ||
| 419 | } | ||
| 420 | iowrite32(v->swtail, wil->csr + HOSTADDR(v->hwtail)); | ||
| 421 | |||
| 422 | return rc; | ||
| 423 | } | ||
| 424 | |||
| 425 | /* | ||
| 426 | * Pass Rx packet to the netif. Update statistics. | ||
| 427 | */ | ||
| 428 | static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | ||
| 429 | { | ||
| 430 | int rc; | ||
| 431 | unsigned int len = skb->len; | ||
| 432 | |||
| 433 | if (in_interrupt()) | ||
| 434 | rc = netif_rx(skb); | ||
| 435 | else | ||
| 436 | rc = netif_rx_ni(skb); | ||
| 437 | |||
| 438 | if (likely(rc == NET_RX_SUCCESS)) { | ||
| 439 | ndev->stats.rx_packets++; | ||
| 440 | ndev->stats.rx_bytes += len; | ||
| 441 | |||
| 442 | } else { | ||
| 443 | ndev->stats.rx_dropped++; | ||
| 444 | } | ||
| 445 | } | ||
| 446 | |||
| 447 | /** | ||
| 448 | * Proceed all completed skb's from Rx VRING | ||
| 449 | * | ||
| 450 | * Safe to call from IRQ | ||
| 451 | */ | ||
| 452 | void wil_rx_handle(struct wil6210_priv *wil) | ||
| 453 | { | ||
| 454 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 455 | struct vring *v = &wil->vring_rx; | ||
| 456 | struct sk_buff *skb; | ||
| 457 | |||
| 458 | if (!v->va) { | ||
| 459 | wil_err(wil, "Rx IRQ while Rx not yet initialized\n"); | ||
| 460 | return; | ||
| 461 | } | ||
| 462 | wil_dbg_TXRX(wil, "%s()\n", __func__); | ||
| 463 | while (NULL != (skb = wil_vring_reap_rx(wil, v))) { | ||
| 464 | wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_OFFSET, 16, 1, | ||
| 465 | skb->data, skb_headlen(skb), false); | ||
| 466 | |||
| 467 | skb_orphan(skb); | ||
| 468 | |||
| 469 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { | ||
| 470 | skb->dev = ndev; | ||
| 471 | skb_reset_mac_header(skb); | ||
| 472 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
| 473 | skb->pkt_type = PACKET_OTHERHOST; | ||
| 474 | skb->protocol = htons(ETH_P_802_2); | ||
| 475 | |||
| 476 | } else { | ||
| 477 | skb->protocol = eth_type_trans(skb, ndev); | ||
| 478 | } | ||
| 479 | |||
| 480 | wil_netif_rx_any(skb, ndev); | ||
| 481 | } | ||
| 482 | wil_rx_refill(wil, v->size); | ||
| 483 | } | ||
| 484 | |||
| 485 | int wil_rx_init(struct wil6210_priv *wil) | ||
| 486 | { | ||
| 487 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 488 | struct wireless_dev *wdev = wil->wdev; | ||
| 489 | struct vring *vring = &wil->vring_rx; | ||
| 490 | int rc; | ||
| 491 | struct wmi_cfg_rx_chain_cmd cmd = { | ||
| 492 | .action = WMI_RX_CHAIN_ADD, | ||
| 493 | .rx_sw_ring = { | ||
| 494 | .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), | ||
| 495 | }, | ||
| 496 | .mid = 0, /* TODO - what is it? */ | ||
| 497 | .decap_trans_type = WMI_DECAP_TYPE_802_3, | ||
| 498 | }; | ||
| 499 | struct { | ||
| 500 | struct wil6210_mbox_hdr_wmi wmi; | ||
| 501 | struct wmi_cfg_rx_chain_done_event evt; | ||
| 502 | } __packed evt; | ||
| 503 | |||
| 504 | vring->size = WIL6210_RX_RING_SIZE; | ||
| 505 | rc = wil_vring_alloc(wil, vring); | ||
| 506 | if (rc) | ||
| 507 | return rc; | ||
| 508 | |||
| 509 | cmd.rx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); | ||
| 510 | cmd.rx_sw_ring.ring_size = cpu_to_le16(vring->size); | ||
| 511 | if (wdev->iftype == NL80211_IFTYPE_MONITOR) { | ||
| 512 | struct ieee80211_channel *ch = wdev->preset_chandef.chan; | ||
| 513 | |||
| 514 | cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON); | ||
| 515 | if (ch) | ||
| 516 | cmd.sniffer_cfg.channel = ch->hw_value - 1; | ||
| 517 | cmd.sniffer_cfg.phy_info_mode = | ||
| 518 | cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP); | ||
| 519 | cmd.sniffer_cfg.phy_support = | ||
| 520 | cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL) | ||
| 521 | ? WMI_SNIFFER_CP : WMI_SNIFFER_DP); | ||
| 522 | } | ||
| 523 | /* typical time for secure PCP is 840ms */ | ||
| 524 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), | ||
| 525 | WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); | ||
| 526 | if (rc) | ||
| 527 | goto err_free; | ||
| 528 | |||
| 529 | vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr); | ||
| 530 | |||
| 531 | wil_dbg(wil, "Rx init: status %d tail 0x%08x\n", | ||
| 532 | le32_to_cpu(evt.evt.status), vring->hwtail); | ||
| 533 | |||
| 534 | rc = wil_rx_refill(wil, vring->size); | ||
| 535 | if (rc) | ||
| 536 | goto err_free; | ||
| 537 | |||
| 538 | return 0; | ||
| 539 | err_free: | ||
| 540 | wil_vring_free(wil, vring, 0); | ||
| 541 | |||
| 542 | return rc; | ||
| 543 | } | ||
| 544 | |||
| 545 | void wil_rx_fini(struct wil6210_priv *wil) | ||
| 546 | { | ||
| 547 | struct vring *vring = &wil->vring_rx; | ||
| 548 | |||
| 549 | if (vring->va) { | ||
| 550 | int rc; | ||
| 551 | struct wmi_cfg_rx_chain_cmd cmd = { | ||
| 552 | .action = cpu_to_le32(WMI_RX_CHAIN_DEL), | ||
| 553 | .rx_sw_ring = { | ||
| 554 | .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), | ||
| 555 | }, | ||
| 556 | }; | ||
| 557 | struct { | ||
| 558 | struct wil6210_mbox_hdr_wmi wmi; | ||
| 559 | struct wmi_cfg_rx_chain_done_event cfg; | ||
| 560 | } __packed wmi_rx_cfg_reply; | ||
| 561 | |||
| 562 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), | ||
| 563 | WMI_CFG_RX_CHAIN_DONE_EVENTID, | ||
| 564 | &wmi_rx_cfg_reply, sizeof(wmi_rx_cfg_reply), | ||
| 565 | 100); | ||
| 566 | wil_vring_free(wil, vring, 0); | ||
| 567 | } | ||
| 568 | } | ||
| 569 | |||
| 570 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | ||
| 571 | int cid, int tid) | ||
| 572 | { | ||
| 573 | int rc; | ||
| 574 | struct wmi_vring_cfg_cmd cmd = { | ||
| 575 | .action = cpu_to_le32(WMI_VRING_CMD_ADD), | ||
| 576 | .vring_cfg = { | ||
| 577 | .tx_sw_ring = { | ||
| 578 | .max_mpdu_size = cpu_to_le16(TX_BUF_LEN), | ||
| 579 | }, | ||
| 580 | .ringid = id, | ||
| 581 | .cidxtid = (cid & 0xf) | ((tid & 0xf) << 4), | ||
| 582 | .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, | ||
| 583 | .mac_ctrl = 0, | ||
| 584 | .to_resolution = 0, | ||
| 585 | .agg_max_wsize = 16, | ||
| 586 | .schd_params = { | ||
| 587 | .priority = cpu_to_le16(0), | ||
| 588 | .timeslot_us = cpu_to_le16(0xfff), | ||
| 589 | }, | ||
| 590 | }, | ||
| 591 | }; | ||
| 592 | struct { | ||
| 593 | struct wil6210_mbox_hdr_wmi wmi; | ||
| 594 | struct wmi_vring_cfg_done_event cmd; | ||
| 595 | } __packed reply; | ||
| 596 | struct vring *vring = &wil->vring_tx[id]; | ||
| 597 | |||
| 598 | if (vring->va) { | ||
| 599 | wil_err(wil, "Tx ring [%d] already allocated\n", id); | ||
| 600 | rc = -EINVAL; | ||
| 601 | goto out; | ||
| 602 | } | ||
| 603 | |||
| 604 | vring->size = size; | ||
| 605 | rc = wil_vring_alloc(wil, vring); | ||
| 606 | if (rc) | ||
| 607 | goto out; | ||
| 608 | |||
| 609 | cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); | ||
| 610 | cmd.vring_cfg.tx_sw_ring.ring_size = cpu_to_le16(vring->size); | ||
| 611 | |||
| 612 | rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd), | ||
| 613 | WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); | ||
| 614 | if (rc) | ||
| 615 | goto out_free; | ||
| 616 | |||
| 617 | if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) { | ||
| 618 | wil_err(wil, "Tx config failed, status 0x%02x\n", | ||
| 619 | reply.cmd.status); | ||
| 620 | goto out_free; | ||
| 621 | } | ||
| 622 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); | ||
| 623 | |||
| 624 | return 0; | ||
| 625 | out_free: | ||
| 626 | wil_vring_free(wil, vring, 1); | ||
| 627 | out: | ||
| 628 | |||
| 629 | return rc; | ||
| 630 | } | ||
| 631 | |||
| 632 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | ||
| 633 | { | ||
| 634 | struct vring *vring = &wil->vring_tx[id]; | ||
| 635 | |||
| 636 | if (!vring->va) | ||
| 637 | return; | ||
| 638 | |||
| 639 | wil_vring_free(wil, vring, 1); | ||
| 640 | } | ||
| 641 | |||
| 642 | static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, | ||
| 643 | struct sk_buff *skb) | ||
| 644 | { | ||
| 645 | struct vring *v = &wil->vring_tx[0]; | ||
| 646 | |||
| 647 | if (v->va) | ||
| 648 | return v; | ||
| 649 | |||
| 650 | return NULL; | ||
| 651 | } | ||
| 652 | |||
| 653 | static int wil_tx_desc_map(volatile struct vring_tx_desc *d, | ||
| 654 | dma_addr_t pa, u32 len) | ||
| 655 | { | ||
| 656 | d->dma.addr_low = lower_32_bits(pa); | ||
| 657 | d->dma.addr_high = (u16)upper_32_bits(pa); | ||
| 658 | d->dma.ip_length = 0; | ||
| 659 | /* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/ | ||
| 660 | d->dma.b11 = 0/*14 | BIT(7)*/; | ||
| 661 | d->dma.error = 0; | ||
| 662 | d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ | ||
| 663 | d->dma.length = len; | ||
| 664 | d->dma.d0 = 0; | ||
| 665 | d->mac.d[0] = 0; | ||
| 666 | d->mac.d[1] = 0; | ||
| 667 | d->mac.d[2] = 0; | ||
| 668 | d->mac.ucode_cmd = 0; | ||
| 669 | /* use dst index 0 */ | ||
| 670 | d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS) | | ||
| 671 | (0 << MAC_CFG_DESC_TX_1_DST_INDEX_POS); | ||
| 672 | /* translation type: 0 - bypass; 1 - 802.3; 2 - native wifi */ | ||
| 673 | d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) | | ||
| 674 | (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS); | ||
| 675 | |||
| 676 | return 0; | ||
| 677 | } | ||
| 678 | |||
| 679 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | ||
| 680 | struct sk_buff *skb) | ||
| 681 | { | ||
| 682 | struct device *dev = wil_to_dev(wil); | ||
| 683 | volatile struct vring_tx_desc *d; | ||
| 684 | u32 swhead = vring->swhead; | ||
| 685 | int avail = wil_vring_avail_tx(vring); | ||
| 686 | int nr_frags = skb_shinfo(skb)->nr_frags; | ||
| 687 | uint f; | ||
| 688 | int vring_index = vring - wil->vring_tx; | ||
| 689 | uint i = swhead; | ||
| 690 | dma_addr_t pa; | ||
| 691 | |||
| 692 | wil_dbg_TXRX(wil, "%s()\n", __func__); | ||
| 693 | |||
| 694 | if (avail < vring->size/8) | ||
| 695 | netif_tx_stop_all_queues(wil_to_ndev(wil)); | ||
| 696 | if (avail < 1 + nr_frags) { | ||
| 697 | wil_err(wil, "Tx ring full. No space for %d fragments\n", | ||
| 698 | 1 + nr_frags); | ||
| 699 | return -ENOMEM; | ||
| 700 | } | ||
| 701 | d = &(vring->va[i].tx); | ||
| 702 | |||
| 703 | /* FIXME FW can accept only unicast frames for the peer */ | ||
| 704 | memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN); | ||
| 705 | |||
| 706 | pa = dma_map_single(dev, skb->data, | ||
| 707 | skb_headlen(skb), DMA_TO_DEVICE); | ||
| 708 | |||
| 709 | wil_dbg_TXRX(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb), | ||
| 710 | skb->data, (unsigned long long)pa); | ||
| 711 | wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_OFFSET, 16, 1, | ||
| 712 | skb->data, skb_headlen(skb), false); | ||
| 713 | |||
| 714 | if (unlikely(dma_mapping_error(dev, pa))) | ||
| 715 | return -EINVAL; | ||
| 716 | /* 1-st segment */ | ||
| 717 | wil_tx_desc_map(d, pa, skb_headlen(skb)); | ||
| 718 | d->mac.d[2] |= ((nr_frags + 1) << | ||
| 719 | MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); | ||
| 720 | /* middle segments */ | ||
| 721 | for (f = 0; f < nr_frags; f++) { | ||
| 722 | const struct skb_frag_struct *frag = | ||
| 723 | &skb_shinfo(skb)->frags[f]; | ||
| 724 | int len = skb_frag_size(frag); | ||
| 725 | i = (swhead + f + 1) % vring->size; | ||
| 726 | d = &(vring->va[i].tx); | ||
| 727 | pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), | ||
| 728 | DMA_TO_DEVICE); | ||
| 729 | if (unlikely(dma_mapping_error(dev, pa))) | ||
| 730 | goto dma_error; | ||
| 731 | wil_tx_desc_map(d, pa, len); | ||
| 732 | vring->ctx[i] = NULL; | ||
| 733 | } | ||
| 734 | /* for the last seg only */ | ||
| 735 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); | ||
| 736 | d->dma.d0 |= BIT(9); /* BUG: undocumented bit */ | ||
| 737 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); | ||
| 738 | d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS); | ||
| 739 | |||
| 740 | wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_NONE, 32, 4, | ||
| 741 | (const void *)d, sizeof(*d), false); | ||
| 742 | |||
| 743 | /* advance swhead */ | ||
| 744 | wil_vring_advance_head(vring, nr_frags + 1); | ||
| 745 | wil_dbg_TXRX(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead); | ||
| 746 | iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail)); | ||
| 747 | /* hold reference to skb | ||
| 748 | * to prevent skb release before accounting | ||
| 749 | * in case of immediate "tx done" | ||
| 750 | */ | ||
| 751 | vring->ctx[i] = skb_get(skb); | ||
| 752 | |||
| 753 | return 0; | ||
| 754 | dma_error: | ||
| 755 | /* unmap what we have mapped */ | ||
| 756 | /* Note: increment @f to operate with positive index */ | ||
| 757 | for (f++; f > 0; f--) { | ||
| 758 | i = (swhead + f) % vring->size; | ||
| 759 | d = &(vring->va[i].tx); | ||
| 760 | d->dma.status = TX_DMA_STATUS_DU; | ||
| 761 | pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); | ||
| 762 | if (vring->ctx[i]) | ||
| 763 | dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
| 764 | else | ||
| 765 | dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
| 766 | } | ||
| 767 | |||
| 768 | return -EINVAL; | ||
| 769 | } | ||
| 770 | |||
| 771 | |||
| 772 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | ||
| 773 | { | ||
| 774 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
| 775 | struct vring *vring; | ||
| 776 | int rc; | ||
| 777 | |||
| 778 | wil_dbg_TXRX(wil, "%s()\n", __func__); | ||
| 779 | if (!test_bit(wil_status_fwready, &wil->status)) { | ||
| 780 | wil_err(wil, "FW not ready\n"); | ||
| 781 | goto drop; | ||
| 782 | } | ||
| 783 | if (!test_bit(wil_status_fwconnected, &wil->status)) { | ||
| 784 | wil_err(wil, "FW not connected\n"); | ||
| 785 | goto drop; | ||
| 786 | } | ||
| 787 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { | ||
| 788 | wil_err(wil, "Xmit in monitor mode not supported\n"); | ||
| 789 | goto drop; | ||
| 790 | } | ||
| 791 | if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { | ||
| 792 | rc = wmi_tx_eapol(wil, skb); | ||
| 793 | } else { | ||
| 794 | /* find vring */ | ||
| 795 | vring = wil_find_tx_vring(wil, skb); | ||
| 796 | if (!vring) { | ||
| 797 | wil_err(wil, "No Tx VRING available\n"); | ||
| 798 | goto drop; | ||
| 799 | } | ||
| 800 | /* set up vring entry */ | ||
| 801 | rc = wil_tx_vring(wil, vring, skb); | ||
| 802 | } | ||
| 803 | switch (rc) { | ||
| 804 | case 0: | ||
| 805 | ndev->stats.tx_packets++; | ||
| 806 | ndev->stats.tx_bytes += skb->len; | ||
| 807 | dev_kfree_skb_any(skb); | ||
| 808 | return NETDEV_TX_OK; | ||
| 809 | case -ENOMEM: | ||
| 810 | return NETDEV_TX_BUSY; | ||
| 811 | default: | ||
| 812 | ; /* goto drop; */ | ||
| 813 | break; | ||
| 814 | } | ||
| 815 | drop: | ||
| 816 | netif_tx_stop_all_queues(ndev); | ||
| 817 | ndev->stats.tx_dropped++; | ||
| 818 | dev_kfree_skb_any(skb); | ||
| 819 | |||
| 820 | return NET_XMIT_DROP; | ||
| 821 | } | ||
| 822 | |||
| 823 | /** | ||
| 824 | * Clean up transmitted skb's from the Tx VRING | ||
| 825 | * | ||
| 826 | * Safe to call from IRQ | ||
| 827 | */ | ||
| 828 | void wil_tx_complete(struct wil6210_priv *wil, int ringid) | ||
| 829 | { | ||
| 830 | struct device *dev = wil_to_dev(wil); | ||
| 831 | struct vring *vring = &wil->vring_tx[ringid]; | ||
| 832 | |||
| 833 | if (!vring->va) { | ||
| 834 | wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid); | ||
| 835 | return; | ||
| 836 | } | ||
| 837 | |||
| 838 | wil_dbg_TXRX(wil, "%s(%d)\n", __func__, ringid); | ||
| 839 | |||
| 840 | while (!wil_vring_is_empty(vring)) { | ||
| 841 | volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx; | ||
| 842 | dma_addr_t pa; | ||
| 843 | struct sk_buff *skb; | ||
| 844 | if (!(d->dma.status & TX_DMA_STATUS_DU)) | ||
| 845 | break; | ||
| 846 | |||
| 847 | wil_dbg_TXRX(wil, | ||
| 848 | "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", | ||
| 849 | vring->swtail, d->dma.length, d->dma.status, | ||
| 850 | d->dma.error); | ||
| 851 | wil_hex_dump_TXRX("TxC ", DUMP_PREFIX_NONE, 32, 4, | ||
| 852 | (const void *)d, sizeof(*d), false); | ||
| 853 | |||
| 854 | pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); | ||
| 855 | skb = vring->ctx[vring->swtail]; | ||
| 856 | if (skb) { | ||
| 857 | dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
| 858 | dev_kfree_skb_any(skb); | ||
| 859 | vring->ctx[vring->swtail] = NULL; | ||
| 860 | } else { | ||
| 861 | dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
| 862 | } | ||
| 863 | d->dma.addr_low = 0; | ||
| 864 | d->dma.addr_high = 0; | ||
| 865 | d->dma.length = 0; | ||
| 866 | d->dma.status = TX_DMA_STATUS_DU; | ||
| 867 | vring->swtail = wil_vring_next_tail(vring); | ||
| 868 | } | ||
| 869 | if (wil_vring_avail_tx(vring) > vring->size/4) | ||
| 870 | netif_tx_wake_all_queues(wil_to_ndev(wil)); | ||
| 871 | } | ||
| @@ -0,0 +1,362 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef WIL6210_TXRX_H | ||
| 18 | #define WIL6210_TXRX_H | ||
| 19 | |||
| 20 | #define BUF_SW_OWNED (1) | ||
| 21 | #define BUF_HW_OWNED (0) | ||
| 22 | |||
| 23 | /* size of max. Rx packet */ | ||
| 24 | #define RX_BUF_LEN (2048) | ||
| 25 | #define TX_BUF_LEN (2048) | ||
| 26 | /* how many bytes to reserve for rtap header? */ | ||
| 27 | #define WIL6210_RTAP_SIZE (128) | ||
| 28 | |||
| 29 | /* Tx/Rx path */ | ||
| 30 | /* | ||
| 31 | * Tx descriptor - MAC part | ||
| 32 | * [dword 0] | ||
| 33 | * bit 0.. 9 : lifetime_expiry_value:10 | ||
| 34 | * bit 10 : interrup_en:1 | ||
| 35 | * bit 11 : status_en:1 | ||
| 36 | * bit 12..13 : txss_override:2 | ||
| 37 | * bit 14 : timestamp_insertion:1 | ||
| 38 | * bit 15 : duration_preserve:1 | ||
| 39 | * bit 16..21 : reserved0:6 | ||
| 40 | * bit 22..26 : mcs_index:5 | ||
| 41 | * bit 27 : mcs_en:1 | ||
| 42 | * bit 28..29 : reserved1:2 | ||
| 43 | * bit 30 : reserved2:1 | ||
| 44 | * bit 31 : sn_preserved:1 | ||
| 45 | * [dword 1] | ||
| 46 | * bit 0.. 3 : pkt_mode:4 | ||
| 47 | * bit 4 : pkt_mode_en:1 | ||
| 48 | * bit 5.. 7 : reserved0:3 | ||
| 49 | * bit 8..13 : reserved1:6 | ||
| 50 | * bit 14 : reserved2:1 | ||
| 51 | * bit 15 : ack_policy_en:1 | ||
| 52 | * bit 16..19 : dst_index:4 | ||
| 53 | * bit 20 : dst_index_en:1 | ||
| 54 | * bit 21..22 : ack_policy:2 | ||
| 55 | * bit 23 : lifetime_en:1 | ||
| 56 | * bit 24..30 : max_retry:7 | ||
| 57 | * bit 31 : max_retry_en:1 | ||
| 58 | * [dword 2] | ||
| 59 | * bit 0.. 7 : num_of_descriptors:8 | ||
| 60 | * bit 8..17 : reserved:10 | ||
| 61 | * bit 18..19 : l2_translation_type:2 | ||
| 62 | * bit 20 : snap_hdr_insertion_en:1 | ||
| 63 | * bit 21 : vlan_removal_en:1 | ||
| 64 | * bit 22..31 : reserved0:10 | ||
| 65 | * [dword 3] | ||
| 66 | * bit 0.. 31: ucode_cmd:32 | ||
| 67 | */ | ||
| 68 | struct vring_tx_mac { | ||
| 69 | u32 d[3]; | ||
| 70 | u32 ucode_cmd; | ||
| 71 | } __packed; | ||
| 72 | |||
| 73 | /* TX MAC Dword 0 */ | ||
| 74 | #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_POS 0 | ||
| 75 | #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_LEN 10 | ||
| 76 | #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_MSK 0x3FF | ||
| 77 | |||
| 78 | #define MAC_CFG_DESC_TX_0_INTERRUP_EN_POS 10 | ||
| 79 | #define MAC_CFG_DESC_TX_0_INTERRUP_EN_LEN 1 | ||
| 80 | #define MAC_CFG_DESC_TX_0_INTERRUP_EN_MSK 0x400 | ||
| 81 | |||
| 82 | #define MAC_CFG_DESC_TX_0_STATUS_EN_POS 11 | ||
| 83 | #define MAC_CFG_DESC_TX_0_STATUS_EN_LEN 1 | ||
| 84 | #define MAC_CFG_DESC_TX_0_STATUS_EN_MSK 0x800 | ||
| 85 | |||
| 86 | #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_POS 12 | ||
| 87 | #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_LEN 2 | ||
| 88 | #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_MSK 0x3000 | ||
| 89 | |||
| 90 | #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_POS 14 | ||
| 91 | #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_LEN 1 | ||
| 92 | #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_MSK 0x4000 | ||
| 93 | |||
| 94 | #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_POS 15 | ||
| 95 | #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_LEN 1 | ||
| 96 | #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_MSK 0x8000 | ||
| 97 | |||
| 98 | #define MAC_CFG_DESC_TX_0_MCS_INDEX_POS 22 | ||
| 99 | #define MAC_CFG_DESC_TX_0_MCS_INDEX_LEN 5 | ||
| 100 | #define MAC_CFG_DESC_TX_0_MCS_INDEX_MSK 0x7C00000 | ||
| 101 | |||
| 102 | #define MAC_CFG_DESC_TX_0_MCS_EN_POS 27 | ||
| 103 | #define MAC_CFG_DESC_TX_0_MCS_EN_LEN 1 | ||
| 104 | #define MAC_CFG_DESC_TX_0_MCS_EN_MSK 0x8000000 | ||
| 105 | |||
| 106 | #define MAC_CFG_DESC_TX_0_SN_PRESERVED_POS 31 | ||
| 107 | #define MAC_CFG_DESC_TX_0_SN_PRESERVED_LEN 1 | ||
| 108 | #define MAC_CFG_DESC_TX_0_SN_PRESERVED_MSK 0x80000000 | ||
| 109 | |||
| 110 | /* TX MAC Dword 1 */ | ||
| 111 | #define MAC_CFG_DESC_TX_1_PKT_MODE_POS 0 | ||
| 112 | #define MAC_CFG_DESC_TX_1_PKT_MODE_LEN 4 | ||
| 113 | #define MAC_CFG_DESC_TX_1_PKT_MODE_MSK 0xF | ||
| 114 | |||
| 115 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_POS 4 | ||
| 116 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_LEN 1 | ||
| 117 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_MSK 0x10 | ||
| 118 | |||
| 119 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_POS 15 | ||
| 120 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_LEN 1 | ||
| 121 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_MSK 0x8000 | ||
| 122 | |||
| 123 | #define MAC_CFG_DESC_TX_1_DST_INDEX_POS 16 | ||
| 124 | #define MAC_CFG_DESC_TX_1_DST_INDEX_LEN 4 | ||
| 125 | #define MAC_CFG_DESC_TX_1_DST_INDEX_MSK 0xF0000 | ||
| 126 | |||
| 127 | #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS 20 | ||
| 128 | #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_LEN 1 | ||
| 129 | #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_MSK 0x100000 | ||
| 130 | |||
| 131 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_POS 21 | ||
| 132 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_LEN 2 | ||
| 133 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_MSK 0x600000 | ||
| 134 | |||
| 135 | #define MAC_CFG_DESC_TX_1_LIFETIME_EN_POS 23 | ||
| 136 | #define MAC_CFG_DESC_TX_1_LIFETIME_EN_LEN 1 | ||
| 137 | #define MAC_CFG_DESC_TX_1_LIFETIME_EN_MSK 0x800000 | ||
| 138 | |||
| 139 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_POS 24 | ||
| 140 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_LEN 7 | ||
| 141 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_MSK 0x7F000000 | ||
| 142 | |||
| 143 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_POS 31 | ||
| 144 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_LEN 1 | ||
| 145 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_MSK 0x80000000 | ||
| 146 | |||
| 147 | /* TX MAC Dword 2 */ | ||
| 148 | #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS 0 | ||
| 149 | #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_LEN 8 | ||
| 150 | #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_MSK 0xFF | ||
| 151 | |||
| 152 | #define MAC_CFG_DESC_TX_2_RESERVED_POS 8 | ||
| 153 | #define MAC_CFG_DESC_TX_2_RESERVED_LEN 10 | ||
| 154 | #define MAC_CFG_DESC_TX_2_RESERVED_MSK 0x3FF00 | ||
| 155 | |||
| 156 | #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS 18 | ||
| 157 | #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_LEN 2 | ||
| 158 | #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_MSK 0xC0000 | ||
| 159 | |||
| 160 | #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS 20 | ||
| 161 | #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_LEN 1 | ||
| 162 | #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_MSK 0x100000 | ||
| 163 | |||
| 164 | #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_POS 21 | ||
| 165 | #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_LEN 1 | ||
| 166 | #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_MSK 0x200000 | ||
| 167 | |||
| 168 | /* TX MAC Dword 3 */ | ||
| 169 | #define MAC_CFG_DESC_TX_3_UCODE_CMD_POS 0 | ||
| 170 | #define MAC_CFG_DESC_TX_3_UCODE_CMD_LEN 32 | ||
| 171 | #define MAC_CFG_DESC_TX_3_UCODE_CMD_MSK 0xFFFFFFFF | ||
| 172 | |||
| 173 | /* TX DMA Dword 0 */ | ||
| 174 | #define DMA_CFG_DESC_TX_0_L4_LENGTH_POS 0 | ||
| 175 | #define DMA_CFG_DESC_TX_0_L4_LENGTH_LEN 8 | ||
| 176 | #define DMA_CFG_DESC_TX_0_L4_LENGTH_MSK 0xFF | ||
| 177 | |||
| 178 | #define DMA_CFG_DESC_TX_0_CMD_EOP_POS 8 | ||
| 179 | #define DMA_CFG_DESC_TX_0_CMD_EOP_LEN 1 | ||
| 180 | #define DMA_CFG_DESC_TX_0_CMD_EOP_MSK 0x100 | ||
| 181 | |||
| 182 | #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS 10 | ||
| 183 | #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_LEN 1 | ||
| 184 | #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_MSK 0x400 | ||
| 185 | |||
| 186 | #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS 11 | ||
| 187 | #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_LEN 2 | ||
| 188 | #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_MSK 0x1800 | ||
| 189 | |||
| 190 | #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_POS 13 | ||
| 191 | #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_LEN 1 | ||
| 192 | #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_MSK 0x2000 | ||
| 193 | |||
| 194 | #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_POS 14 | ||
| 195 | #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_LEN 1 | ||
| 196 | #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_MSK 0x4000 | ||
| 197 | |||
| 198 | #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS 15 | ||
| 199 | #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_LEN 1 | ||
| 200 | #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_MSK 0x8000 | ||
| 201 | |||
| 202 | #define DMA_CFG_DESC_TX_0_QID_POS 16 | ||
| 203 | #define DMA_CFG_DESC_TX_0_QID_LEN 5 | ||
| 204 | #define DMA_CFG_DESC_TX_0_QID_MSK 0x1F0000 | ||
| 205 | |||
| 206 | #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS 21 | ||
| 207 | #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_LEN 1 | ||
| 208 | #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_MSK 0x200000 | ||
| 209 | |||
| 210 | #define DMA_CFG_DESC_TX_0_L4_TYPE_POS 30 | ||
| 211 | #define DMA_CFG_DESC_TX_0_L4_TYPE_LEN 2 | ||
| 212 | #define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000 | ||
| 213 | |||
| 214 | |||
| 215 | #define TX_DMA_STATUS_DU BIT(0) | ||
| 216 | |||
| 217 | struct vring_tx_dma { | ||
| 218 | u32 d0; | ||
| 219 | u32 addr_low; | ||
| 220 | u16 addr_high; | ||
| 221 | u8 ip_length; | ||
| 222 | u8 b11; /* 0..6: mac_length; 7:ip_version */ | ||
| 223 | u8 error; /* 0..2: err; 3..7: reserved; */ | ||
| 224 | u8 status; /* 0: used; 1..7; reserved */ | ||
| 225 | u16 length; | ||
| 226 | } __packed; | ||
| 227 | |||
| 228 | /* | ||
| 229 | * Rx descriptor - MAC part | ||
| 230 | * [dword 0] | ||
| 231 | * bit 0.. 3 : tid:4 The QoS (b3-0) TID Field | ||
| 232 | * bit 4.. 6 : connection_id:3 :The Source index that was found during | ||
| 233 | * Parsing the TA. This field is used to define the source of the packet | ||
| 234 | * bit 7 : reserved:1 | ||
| 235 | * bit 8.. 9 : mac_id:2 : The MAC virtual Ring number (always zero) | ||
| 236 | * bit 10..11 : frame_type:2 : The FC Control (b3-2) - MPDU Type | ||
| 237 | * (management, data, control and extension) | ||
| 238 | * bit 12..15 : frame_subtype:4 : The FC Control (b7-4) - Frame Subtype | ||
| 239 | * bit 16..27 : seq_number:12 The received Sequence number field | ||
| 240 | * bit 28..31 : extended:4 extended subtype | ||
| 241 | * [dword 1] | ||
| 242 | * bit 0.. 3 : reserved | ||
| 243 | * bit 4.. 5 : key_id:2 | ||
| 244 | * bit 6 : decrypt_bypass:1 | ||
| 245 | * bit 7 : security:1 | ||
| 246 | * bit 8.. 9 : ds_bits:2 | ||
| 247 | * bit 10 : a_msdu_present:1 from qos header | ||
| 248 | * bit 11 : a_msdu_type:1 from qos header | ||
| 249 | * bit 12 : a_mpdu:1 part of AMPDU aggregation | ||
| 250 | * bit 13 : broadcast:1 | ||
| 251 | * bit 14 : mutlicast:1 | ||
| 252 | * bit 15 : reserved:1 | ||
| 253 | * bit 16..20 : rx_mac_qid:5 The Queue Identifier that the packet | ||
| 254 | * is received from | ||
| 255 | * bit 21..24 : mcs:4 | ||
| 256 | * bit 25..28 : mic_icr:4 | ||
| 257 | * bit 29..31 : reserved:3 | ||
| 258 | * [dword 2] | ||
| 259 | * bit 0.. 2 : time_slot:3 The timeslot that the MPDU is received | ||
| 260 | * bit 3 : fc_protocol_ver:1 The FC Control (b0) - Protocol Version | ||
| 261 | * bit 4 : fc_order:1 The FC Control (b15) -Order | ||
| 262 | * bit 5.. 7 : qos_ack_policy:3 The QoS (b6-5) ack policy Field | ||
| 263 | * bit 8 : esop:1 The QoS (b4) ESOP field | ||
| 264 | * bit 9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG field | ||
| 265 | * bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved field | ||
| 266 | * bit 15 : qos_ac_constraint:1 | ||
| 267 | * bit 16..31 : pn_15_0:16 low 2 bytes of PN | ||
| 268 | * [dword 3] | ||
| 269 | * bit 0..31 : pn_47_16:32 high 4 bytes of PN | ||
| 270 | */ | ||
| 271 | struct vring_rx_mac { | ||
| 272 | u32 d0; | ||
| 273 | u32 d1; | ||
| 274 | u16 w4; | ||
| 275 | u16 pn_15_0; | ||
| 276 | u32 pn_47_16; | ||
| 277 | } __packed; | ||
| 278 | |||
| 279 | /* | ||
| 280 | * Rx descriptor - DMA part | ||
| 281 | * [dword 0] | ||
| 282 | * bit 0.. 7 : l4_length:8 layer 4 length | ||
| 283 | * bit 8.. 9 : reserved:2 | ||
| 284 | * bit 10 : cmd_dma_it:1 | ||
| 285 | * bit 11..15 : reserved:5 | ||
| 286 | * bit 16..29 : phy_info_length:14 | ||
| 287 | * bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field | ||
| 288 | * [dword 1] | ||
| 289 | * bit 0..31 : addr_low:32 The payload buffer low address | ||
| 290 | * [dword 2] | ||
| 291 | * bit 0..15 : addr_high:16 The payload buffer high address | ||
| 292 | * bit 16..23 : ip_length:8 | ||
| 293 | * bit 24..30 : mac_length:7 | ||
| 294 | * bit 31 : ip_version:1 | ||
| 295 | * [dword 3] | ||
| 296 | * [byte 12] error | ||
| 297 | * [byte 13] status | ||
| 298 | * bit 0 : du:1 | ||
| 299 | * bit 1 : eop:1 | ||
| 300 | * bit 2 : error:1 | ||
| 301 | * bit 3 : mi:1 | ||
| 302 | * bit 4 : l3_identified:1 | ||
| 303 | * bit 5 : l4_identified:1 | ||
| 304 | * bit 6 : phy_info_included:1 | ||
| 305 | * bit 7 : reserved:1 | ||
| 306 | * [word 7] length | ||
| 307 | * | ||
| 308 | */ | ||
| 309 | |||
| 310 | #define RX_DMA_D0_CMD_DMA_IT BIT(10) | ||
| 311 | |||
| 312 | #define RX_DMA_STATUS_DU BIT(0) | ||
| 313 | #define RX_DMA_STATUS_ERROR BIT(2) | ||
| 314 | #define RX_DMA_STATUS_PHY_INFO BIT(6) | ||
| 315 | |||
| 316 | struct vring_rx_dma { | ||
| 317 | u32 d0; | ||
| 318 | u32 addr_low; | ||
| 319 | u16 addr_high; | ||
| 320 | u8 ip_length; | ||
| 321 | u8 b11; | ||
| 322 | u8 error; | ||
| 323 | u8 status; | ||
| 324 | u16 length; | ||
| 325 | } __packed; | ||
| 326 | |||
| 327 | struct vring_tx_desc { | ||
| 328 | struct vring_tx_mac mac; | ||
| 329 | struct vring_tx_dma dma; | ||
| 330 | } __packed; | ||
| 331 | |||
| 332 | struct vring_rx_desc { | ||
| 333 | struct vring_rx_mac mac; | ||
| 334 | struct vring_rx_dma dma; | ||
| 335 | } __packed; | ||
| 336 | |||
| 337 | union vring_desc { | ||
| 338 | struct vring_tx_desc tx; | ||
| 339 | struct vring_rx_desc rx; | ||
| 340 | } __packed; | ||
| 341 | |||
| 342 | static inline int wil_rxdesc_phy_length(volatile struct vring_rx_desc *d) | ||
| 343 | { | ||
| 344 | return WIL_GET_BITS(d->dma.d0, 16, 29); | ||
| 345 | } | ||
| 346 | |||
| 347 | static inline int wil_rxdesc_mcs(volatile struct vring_rx_desc *d) | ||
| 348 | { | ||
| 349 | return WIL_GET_BITS(d->mac.d1, 21, 24); | ||
| 350 | } | ||
| 351 | |||
| 352 | static inline int wil_rxdesc_ds_bits(volatile struct vring_rx_desc *d) | ||
| 353 | { | ||
| 354 | return WIL_GET_BITS(d->mac.d1, 8, 9); | ||
| 355 | } | ||
| 356 | |||
| 357 | static inline int wil_rxdesc_ftype(volatile struct vring_rx_desc *d) | ||
| 358 | { | ||
| 359 | return WIL_GET_BITS(d->mac.d0, 10, 11); | ||
| 360 | } | ||
| 361 | |||
| 362 | #endif /* WIL6210_TXRX_H */ | ||
| @@ -0,0 +1,363 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef __WIL6210_H__ | ||
| 18 | #define __WIL6210_H__ | ||
| 19 | |||
| 20 | #include <linux/netdevice.h> | ||
| 21 | #include <linux/wireless.h> | ||
| 22 | #include <net/cfg80211.h> | ||
| 23 | |||
| 24 | #include "dbg_hexdump.h" | ||
| 25 | |||
| 26 | #define WIL_NAME "wil6210" | ||
| 27 | |||
| 28 | /** | ||
| 29 | * extract bits [@b0:@b1] (inclusive) from the value @x | ||
| 30 | * it should be @b0 <= @b1, or result is incorrect | ||
| 31 | */ | ||
| 32 | static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) | ||
| 33 | { | ||
| 34 | return (x >> b0) & ((1 << (b1 - b0 + 1)) - 1); | ||
| 35 | } | ||
| 36 | |||
| 37 | #define WIL6210_MEM_SIZE (2*1024*1024UL) | ||
| 38 | |||
| 39 | #define WIL6210_TX_QUEUES (4) | ||
| 40 | |||
| 41 | #define WIL6210_RX_RING_SIZE (128) | ||
| 42 | #define WIL6210_TX_RING_SIZE (128) | ||
| 43 | #define WIL6210_MAX_TX_RINGS (24) | ||
| 44 | |||
| 45 | /* Hardware definitions begin */ | ||
| 46 | |||
| 47 | /* | ||
| 48 | * Mapping | ||
| 49 | * RGF File | Host addr | FW addr | ||
| 50 | * | | | ||
| 51 | * user_rgf | 0x000000 | 0x880000 | ||
| 52 | * dma_rgf | 0x001000 | 0x881000 | ||
| 53 | * pcie_rgf | 0x002000 | 0x882000 | ||
| 54 | * | | | ||
| 55 | */ | ||
| 56 | |||
| 57 | /* Where various structures placed in host address space */ | ||
| 58 | #define WIL6210_FW_HOST_OFF (0x880000UL) | ||
| 59 | |||
| 60 | #define HOSTADDR(fwaddr) (fwaddr - WIL6210_FW_HOST_OFF) | ||
| 61 | |||
| 62 | /* | ||
| 63 | * Interrupt control registers block | ||
| 64 | * | ||
| 65 | * each interrupt controlled by the same bit in all registers | ||
| 66 | */ | ||
| 67 | struct RGF_ICR { | ||
| 68 | u32 ICC; /* Cause Control, RW: 0 - W1C, 1 - COR */ | ||
| 69 | u32 ICR; /* Cause, W1C/COR depending on ICC */ | ||
| 70 | u32 ICM; /* Cause masked (ICR & ~IMV), W1C/COR depending on ICC */ | ||
| 71 | u32 ICS; /* Cause Set, WO */ | ||
| 72 | u32 IMV; /* Mask, RW+S/C */ | ||
| 73 | u32 IMS; /* Mask Set, write 1 to set */ | ||
| 74 | u32 IMC; /* Mask Clear, write 1 to clear */ | ||
| 75 | } __packed; | ||
| 76 | |||
| 77 | /* registers - FW addresses */ | ||
| 78 | #define RGF_USER_USER_SCRATCH_PAD (0x8802bc) | ||
| 79 | #define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ | ||
| 80 | #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) | ||
| 81 | #define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) | ||
| 82 | #define RGF_USER_MAC_CPU_0 (0x8801fc) | ||
| 83 | #define RGF_USER_USER_CPU_0 (0x8801e0) | ||
| 84 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_0 (0x880b04) | ||
| 85 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_1 (0x880b08) | ||
| 86 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_2 (0x880b0c) | ||
| 87 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_3 (0x880b10) | ||
| 88 | |||
| 89 | #define RGF_DMA_PSEUDO_CAUSE (0x881c68) | ||
| 90 | #define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c) | ||
| 91 | #define RGF_DMA_PSEUDO_CAUSE_MASK_FW (0x881c70) | ||
| 92 | #define BIT_DMA_PSEUDO_CAUSE_RX BIT(0) | ||
| 93 | #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) | ||
| 94 | #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) | ||
| 95 | |||
| 96 | #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ | ||
| 97 | #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) | ||
| 98 | #define BIT_DMA_EP_TX_ICR_TX_DONE_N(n) BIT(n+1) /* n = [0..23] */ | ||
| 99 | #define RGF_DMA_EP_RX_ICR (0x881bd0) /* struct RGF_ICR */ | ||
| 100 | #define BIT_DMA_EP_RX_ICR_RX_DONE BIT(0) | ||
| 101 | #define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */ | ||
| 102 | #define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0) | ||
| 103 | #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1) | ||
| 104 | #define BIT_DMA_EP_MISC_ICR_FW_INT0 BIT(28) | ||
| 105 | #define BIT_DMA_EP_MISC_ICR_FW_INT1 BIT(29) | ||
| 106 | |||
| 107 | /* Interrupt moderation control */ | ||
| 108 | #define RGF_DMA_ITR_CNT_TRSH (0x881c5c) | ||
| 109 | #define RGF_DMA_ITR_CNT_DATA (0x881c60) | ||
| 110 | #define RGF_DMA_ITR_CNT_CRL (0x881C64) | ||
| 111 | #define BIT_DMA_ITR_CNT_CRL_EN BIT(0) | ||
| 112 | #define BIT_DMA_ITR_CNT_CRL_EXT_TICK BIT(1) | ||
| 113 | #define BIT_DMA_ITR_CNT_CRL_FOREVER BIT(2) | ||
| 114 | #define BIT_DMA_ITR_CNT_CRL_CLR BIT(3) | ||
| 115 | #define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4) | ||
| 116 | |||
| 117 | /* popular locations */ | ||
| 118 | #define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) | ||
| 119 | #define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \ | ||
| 120 | offsetof(struct RGF_ICR, ICS)) | ||
| 121 | #define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2 | ||
| 122 | |||
| 123 | /* ISR register bits */ | ||
| 124 | #define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT0 | ||
| 125 | #define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT1 | ||
| 126 | |||
| 127 | /* Hardware definitions end */ | ||
| 128 | |||
| 129 | struct wil6210_mbox_ring { | ||
| 130 | u32 base; | ||
| 131 | u16 entry_size; /* max. size of mbox entry, incl. all headers */ | ||
| 132 | u16 size; | ||
| 133 | u32 tail; | ||
| 134 | u32 head; | ||
| 135 | } __packed; | ||
| 136 | |||
| 137 | struct wil6210_mbox_ring_desc { | ||
| 138 | __le32 sync; | ||
| 139 | __le32 addr; | ||
| 140 | } __packed; | ||
| 141 | |||
| 142 | /* at HOST_OFF_WIL6210_MBOX_CTL */ | ||
| 143 | struct wil6210_mbox_ctl { | ||
| 144 | struct wil6210_mbox_ring tx; | ||
| 145 | struct wil6210_mbox_ring rx; | ||
| 146 | } __packed; | ||
| 147 | |||
| 148 | struct wil6210_mbox_hdr { | ||
| 149 | __le16 seq; | ||
| 150 | __le16 len; /* payload, bytes after this header */ | ||
| 151 | __le16 type; | ||
| 152 | u8 flags; | ||
| 153 | u8 reserved; | ||
| 154 | } __packed; | ||
| 155 | |||
| 156 | #define WIL_MBOX_HDR_TYPE_WMI (0) | ||
| 157 | |||
| 158 | /* max. value for wil6210_mbox_hdr.len */ | ||
| 159 | #define MAX_MBOXITEM_SIZE (240) | ||
| 160 | |||
| 161 | struct wil6210_mbox_hdr_wmi { | ||
| 162 | u8 reserved0[2]; | ||
| 163 | __le16 id; | ||
| 164 | __le16 info1; /* bits [0..3] - device_id, rest - unused */ | ||
| 165 | u8 reserved1[2]; | ||
| 166 | } __packed; | ||
| 167 | |||
| 168 | struct pending_wmi_event { | ||
| 169 | struct list_head list; | ||
| 170 | struct { | ||
| 171 | struct wil6210_mbox_hdr hdr; | ||
| 172 | struct wil6210_mbox_hdr_wmi wmi; | ||
| 173 | u8 data[0]; | ||
| 174 | } __packed event; | ||
| 175 | }; | ||
| 176 | |||
| 177 | union vring_desc; | ||
| 178 | |||
| 179 | struct vring { | ||
| 180 | dma_addr_t pa; | ||
| 181 | volatile union vring_desc *va; /* vring_desc[size], WriteBack by DMA */ | ||
| 182 | u16 size; /* number of vring_desc elements */ | ||
| 183 | u32 swtail; | ||
| 184 | u32 swhead; | ||
| 185 | u32 hwtail; /* write here to inform hw */ | ||
| 186 | void **ctx; /* void *ctx[size] - software context */ | ||
| 187 | }; | ||
| 188 | |||
| 189 | enum { /* for wil6210_priv.status */ | ||
| 190 | wil_status_fwready = 0, | ||
| 191 | wil_status_fwconnected, | ||
| 192 | wil_status_dontscan, | ||
| 193 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ | ||
| 194 | }; | ||
| 195 | |||
| 196 | struct pci_dev; | ||
| 197 | |||
| 198 | struct wil6210_stats { | ||
| 199 | u64 tsf; | ||
| 200 | u32 snr; | ||
| 201 | u16 last_mcs_rx; | ||
| 202 | u16 bf_mcs; /* last BF, used for Tx */ | ||
| 203 | u16 my_rx_sector; | ||
| 204 | u16 my_tx_sector; | ||
| 205 | u16 peer_rx_sector; | ||
| 206 | u16 peer_tx_sector; | ||
| 207 | }; | ||
| 208 | |||
| 209 | struct wil6210_priv { | ||
| 210 | struct pci_dev *pdev; | ||
| 211 | int n_msi; | ||
| 212 | struct wireless_dev *wdev; | ||
| 213 | void __iomem *csr; | ||
| 214 | ulong status; | ||
| 215 | /* profile */ | ||
| 216 | u32 monitor_flags; | ||
| 217 | u32 secure_pcp; /* create secure PCP? */ | ||
| 218 | int sinfo_gen; | ||
| 219 | /* cached ISR registers */ | ||
| 220 | u32 isr_misc; | ||
| 221 | /* mailbox related */ | ||
| 222 | struct mutex wmi_mutex; | ||
| 223 | struct wil6210_mbox_ctl mbox_ctl; | ||
| 224 | struct completion wmi_ready; | ||
| 225 | u16 wmi_seq; | ||
| 226 | u16 reply_id; /**< wait for this WMI event */ | ||
| 227 | void *reply_buf; | ||
| 228 | u16 reply_size; | ||
| 229 | struct workqueue_struct *wmi_wq; /* for deferred calls */ | ||
| 230 | struct work_struct wmi_event_worker; | ||
| 231 | struct workqueue_struct *wmi_wq_conn; /* for connect worker */ | ||
| 232 | struct work_struct wmi_connect_worker; | ||
| 233 | struct work_struct disconnect_worker; | ||
| 234 | struct timer_list connect_timer; | ||
| 235 | int pending_connect_cid; | ||
| 236 | struct list_head pending_wmi_ev; | ||
| 237 | /* | ||
| 238 | * protect pending_wmi_ev | ||
| 239 | * - fill in IRQ from wil6210_irq_misc, | ||
| 240 | * - consumed in thread by wmi_event_worker | ||
| 241 | */ | ||
| 242 | spinlock_t wmi_ev_lock; | ||
| 243 | /* DMA related */ | ||
| 244 | struct vring vring_rx; | ||
| 245 | struct vring vring_tx[WIL6210_MAX_TX_RINGS]; | ||
| 246 | u8 dst_addr[WIL6210_MAX_TX_RINGS][ETH_ALEN]; | ||
| 247 | /* scan */ | ||
| 248 | struct cfg80211_scan_request *scan_request; | ||
| 249 | |||
| 250 | struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */ | ||
| 251 | /* statistics */ | ||
| 252 | struct wil6210_stats stats; | ||
| 253 | /* debugfs */ | ||
| 254 | struct dentry *debug; | ||
| 255 | struct debugfs_blob_wrapper fw_code_blob; | ||
| 256 | struct debugfs_blob_wrapper fw_data_blob; | ||
| 257 | struct debugfs_blob_wrapper fw_peri_blob; | ||
| 258 | struct debugfs_blob_wrapper uc_code_blob; | ||
| 259 | struct debugfs_blob_wrapper uc_data_blob; | ||
| 260 | struct debugfs_blob_wrapper rgf_blob; | ||
| 261 | }; | ||
| 262 | |||
| 263 | #define wil_to_wiphy(i) (i->wdev->wiphy) | ||
| 264 | #define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i))) | ||
| 265 | #define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w)) | ||
| 266 | #define wil_to_wdev(i) (i->wdev) | ||
| 267 | #define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w)) | ||
| 268 | #define wil_to_ndev(i) (wil_to_wdev(i)->netdev) | ||
| 269 | #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) | ||
| 270 | |||
| 271 | #define wil_dbg(wil, fmt, arg...) netdev_dbg(wil_to_ndev(wil), fmt, ##arg) | ||
| 272 | #define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg) | ||
| 273 | #define wil_err(wil, fmt, arg...) netdev_err(wil_to_ndev(wil), fmt, ##arg) | ||
| 274 | |||
| 275 | #define wil_dbg_IRQ(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg) | ||
| 276 | #define wil_dbg_TXRX(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg) | ||
| 277 | #define wil_dbg_WMI(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg) | ||
| 278 | |||
| 279 | #define wil_hex_dump_TXRX(prefix_str, prefix_type, rowsize, \ | ||
| 280 | groupsize, buf, len, ascii) \ | ||
| 281 | wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\ | ||
| 282 | prefix_type, rowsize, \ | ||
| 283 | groupsize, buf, len, ascii) | ||
| 284 | |||
| 285 | #define wil_hex_dump_WMI(prefix_str, prefix_type, rowsize, \ | ||
| 286 | groupsize, buf, len, ascii) \ | ||
| 287 | wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\ | ||
| 288 | prefix_type, rowsize, \ | ||
| 289 | groupsize, buf, len, ascii) | ||
| 290 | |||
| 291 | void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, | ||
| 292 | size_t count); | ||
| 293 | void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | ||
| 294 | size_t count); | ||
| 295 | |||
| 296 | void *wil_if_alloc(struct device *dev, void __iomem *csr); | ||
| 297 | void wil_if_free(struct wil6210_priv *wil); | ||
| 298 | int wil_if_add(struct wil6210_priv *wil); | ||
| 299 | void wil_if_remove(struct wil6210_priv *wil); | ||
| 300 | int wil_priv_init(struct wil6210_priv *wil); | ||
| 301 | void wil_priv_deinit(struct wil6210_priv *wil); | ||
| 302 | int wil_reset(struct wil6210_priv *wil); | ||
| 303 | void wil_link_on(struct wil6210_priv *wil); | ||
| 304 | void wil_link_off(struct wil6210_priv *wil); | ||
| 305 | int wil_up(struct wil6210_priv *wil); | ||
| 306 | int wil_down(struct wil6210_priv *wil); | ||
| 307 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); | ||
| 308 | |||
| 309 | void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); | ||
| 310 | void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); | ||
| 311 | int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, | ||
| 312 | struct wil6210_mbox_hdr *hdr); | ||
| 313 | int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len); | ||
| 314 | void wmi_recv_cmd(struct wil6210_priv *wil); | ||
| 315 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | ||
| 316 | u16 reply_id, void *reply, u8 reply_size, int to_msec); | ||
| 317 | void wmi_connect_worker(struct work_struct *work); | ||
| 318 | void wmi_event_worker(struct work_struct *work); | ||
| 319 | void wmi_event_flush(struct wil6210_priv *wil); | ||
| 320 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); | ||
| 321 | int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid); | ||
| 322 | int wmi_set_channel(struct wil6210_priv *wil, int channel); | ||
| 323 | int wmi_get_channel(struct wil6210_priv *wil, int *channel); | ||
| 324 | int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb); | ||
| 325 | int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
| 326 | const void *mac_addr); | ||
| 327 | int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
| 328 | const void *mac_addr, int key_len, const void *key); | ||
| 329 | int wmi_echo(struct wil6210_priv *wil); | ||
| 330 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); | ||
| 331 | |||
| 332 | int wil6210_init_irq(struct wil6210_priv *wil, int irq); | ||
| 333 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq); | ||
| 334 | void wil6210_disable_irq(struct wil6210_priv *wil); | ||
| 335 | void wil6210_enable_irq(struct wil6210_priv *wil); | ||
| 336 | |||
| 337 | int wil6210_debugfs_init(struct wil6210_priv *wil); | ||
| 338 | void wil6210_debugfs_remove(struct wil6210_priv *wil); | ||
| 339 | |||
| 340 | struct wireless_dev *wil_cfg80211_init(struct device *dev); | ||
| 341 | void wil_wdev_free(struct wil6210_priv *wil); | ||
| 342 | |||
| 343 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); | ||
| 344 | int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype); | ||
| 345 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); | ||
| 346 | |||
| 347 | int wil_rx_init(struct wil6210_priv *wil); | ||
| 348 | void wil_rx_fini(struct wil6210_priv *wil); | ||
| 349 | |||
| 350 | /* TX API */ | ||
| 351 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | ||
| 352 | int cid, int tid); | ||
| 353 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id); | ||
| 354 | |||
| 355 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); | ||
| 356 | void wil_tx_complete(struct wil6210_priv *wil, int ringid); | ||
| 357 | |||
| 358 | /* RX API */ | ||
| 359 | void wil_rx_handle(struct wil6210_priv *wil); | ||
| 360 | |||
| 361 | int wil_iftype_nl2wmi(enum nl80211_iftype type); | ||
| 362 | |||
| 363 | #endif /* __WIL6210_H__ */ | ||
| @@ -0,0 +1,975 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/pci.h> | ||
| 18 | #include <linux/io.h> | ||
| 19 | #include <linux/list.h> | ||
| 20 | #include <linux/etherdevice.h> | ||
| 21 | |||
| 22 | #include "wil6210.h" | ||
| 23 | #include "wmi.h" | ||
| 24 | |||
| 25 | /** | ||
| 26 | * WMI event receiving - theory of operations | ||
| 27 | * | ||
| 28 | * When firmware about to report WMI event, it fills memory area | ||
| 29 | * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for | ||
| 30 | * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler. | ||
| 31 | * | ||
| 32 | * @wmi_recv_cmd reads event, allocates memory chunk and attaches it to the | ||
| 33 | * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up | ||
| 34 | * and handles events within the @wmi_event_worker. Every event get detached | ||
| 35 | * from list, processed and deleted. | ||
| 36 | * | ||
| 37 | * Purpose for this mechanism is to release IRQ thread; otherwise, | ||
| 38 | * if WMI event handling involves another WMI command flow, this 2-nd flow | ||
| 39 | * won't be completed because of blocked IRQ thread. | ||
| 40 | */ | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Addressing - theory of operations | ||
| 44 | * | ||
| 45 | * There are several buses present on the WIL6210 card. | ||
| 46 | * Same memory areas are visible at different address on | ||
| 47 | * the different busses. There are 3 main bus masters: | ||
| 48 | * - MAC CPU (ucode) | ||
| 49 | * - User CPU (firmware) | ||
| 50 | * - AHB (host) | ||
| 51 | * | ||
| 52 | * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing | ||
| 53 | * AHB addresses starting from 0x880000 | ||
| 54 | * | ||
| 55 | * Internally, firmware uses addresses that allows faster access but | ||
| 56 | * are invisible from the host. To read from these addresses, alternative | ||
| 57 | * AHB address must be used. | ||
| 58 | * | ||
| 59 | * Memory mapping | ||
| 60 | * Linker address PCI/Host address | ||
| 61 | * 0x880000 .. 0xa80000 2Mb BAR0 | ||
| 62 | * 0x800000 .. 0x807000 0x900000 .. 0x907000 28k DCCM | ||
| 63 | * 0x840000 .. 0x857000 0x908000 .. 0x91f000 92k PERIPH | ||
| 64 | */ | ||
| 65 | |||
| 66 | /** | ||
| 67 | * @fw_mapping provides memory remapping table | ||
| 68 | */ | ||
| 69 | static const struct { | ||
| 70 | u32 from; /* linker address - from, inclusive */ | ||
| 71 | u32 to; /* linker address - to, exclusive */ | ||
| 72 | u32 host; /* PCI/Host address - BAR0 + 0x880000 */ | ||
| 73 | } fw_mapping[] = { | ||
| 74 | {0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */ | ||
| 75 | {0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */ | ||
| 76 | {0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */ | ||
| 77 | {0x880000, 0x88a000, 0x880000}, /* various RGF */ | ||
| 78 | {0x8c0000, 0x932000, 0x8c0000}, /* trivial mapping for upper area */ | ||
| 79 | /* | ||
| 80 | * 920000..930000 ucode code RAM | ||
| 81 | * 930000..932000 ucode data RAM | ||
| 82 | */ | ||
| 83 | }; | ||
| 84 | |||
| 85 | /** | ||
| 86 | * return AHB address for given firmware/ucode internal (linker) address | ||
| 87 | * @x - internal address | ||
| 88 | * If address have no valid AHB mapping, return 0 | ||
| 89 | */ | ||
| 90 | static u32 wmi_addr_remap(u32 x) | ||
| 91 | { | ||
| 92 | uint i; | ||
| 93 | |||
| 94 | for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { | ||
| 95 | if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)) | ||
| 96 | return x + fw_mapping[i].host - fw_mapping[i].from; | ||
| 97 | } | ||
| 98 | |||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | /** | ||
| 103 | * Check address validity for WMI buffer; remap if needed | ||
| 104 | * @ptr - internal (linker) fw/ucode address | ||
| 105 | * | ||
| 106 | * Valid buffer should be DWORD aligned | ||
| 107 | * | ||
| 108 | * return address for accessing buffer from the host; | ||
| 109 | * if buffer is not valid, return NULL. | ||
| 110 | */ | ||
| 111 | void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) | ||
| 112 | { | ||
| 113 | u32 off; | ||
| 114 | u32 ptr = le32_to_cpu(ptr_); | ||
| 115 | |||
| 116 | if (ptr % 4) | ||
| 117 | return NULL; | ||
| 118 | |||
| 119 | ptr = wmi_addr_remap(ptr); | ||
| 120 | if (ptr < WIL6210_FW_HOST_OFF) | ||
| 121 | return NULL; | ||
| 122 | |||
| 123 | off = HOSTADDR(ptr); | ||
| 124 | if (off > WIL6210_MEM_SIZE - 4) | ||
| 125 | return NULL; | ||
| 126 | |||
| 127 | return wil->csr + off; | ||
| 128 | } | ||
| 129 | |||
| 130 | /** | ||
| 131 | * Check address validity | ||
| 132 | */ | ||
| 133 | void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr) | ||
| 134 | { | ||
| 135 | u32 off; | ||
| 136 | |||
| 137 | if (ptr % 4) | ||
| 138 | return NULL; | ||
| 139 | |||
| 140 | if (ptr < WIL6210_FW_HOST_OFF) | ||
| 141 | return NULL; | ||
| 142 | |||
| 143 | off = HOSTADDR(ptr); | ||
| 144 | if (off > WIL6210_MEM_SIZE - 4) | ||
| 145 | return NULL; | ||
| 146 | |||
| 147 | return wil->csr + off; | ||
| 148 | } | ||
| 149 | |||
| 150 | int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, | ||
| 151 | struct wil6210_mbox_hdr *hdr) | ||
| 152 | { | ||
| 153 | void __iomem *src = wmi_buffer(wil, ptr); | ||
| 154 | if (!src) | ||
| 155 | return -EINVAL; | ||
| 156 | |||
| 157 | wil_memcpy_fromio_32(hdr, src, sizeof(*hdr)); | ||
| 158 | |||
| 159 | return 0; | ||
| 160 | } | ||
| 161 | |||
| 162 | static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | ||
| 163 | { | ||
| 164 | struct { | ||
| 165 | struct wil6210_mbox_hdr hdr; | ||
| 166 | struct wil6210_mbox_hdr_wmi wmi; | ||
| 167 | } __packed cmd = { | ||
| 168 | .hdr = { | ||
| 169 | .type = WIL_MBOX_HDR_TYPE_WMI, | ||
| 170 | .flags = 0, | ||
| 171 | .len = cpu_to_le16(sizeof(cmd.wmi) + len), | ||
| 172 | }, | ||
| 173 | .wmi = { | ||
| 174 | .id = cpu_to_le16(cmdid), | ||
| 175 | .info1 = 0, | ||
| 176 | }, | ||
| 177 | }; | ||
| 178 | struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx; | ||
| 179 | struct wil6210_mbox_ring_desc d_head; | ||
| 180 | u32 next_head; | ||
| 181 | void __iomem *dst; | ||
| 182 | void __iomem *head = wmi_addr(wil, r->head); | ||
| 183 | uint retry; | ||
| 184 | |||
| 185 | if (sizeof(cmd) + len > r->entry_size) { | ||
| 186 | wil_err(wil, "WMI size too large: %d bytes, max is %d\n", | ||
| 187 | (int)(sizeof(cmd) + len), r->entry_size); | ||
| 188 | return -ERANGE; | ||
| 189 | |||
| 190 | } | ||
| 191 | |||
| 192 | might_sleep(); | ||
| 193 | |||
| 194 | if (!test_bit(wil_status_fwready, &wil->status)) { | ||
| 195 | wil_err(wil, "FW not ready\n"); | ||
| 196 | return -EAGAIN; | ||
| 197 | } | ||
| 198 | |||
| 199 | if (!head) { | ||
| 200 | wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head); | ||
| 201 | return -EINVAL; | ||
| 202 | } | ||
| 203 | /* read Tx head till it is not busy */ | ||
| 204 | for (retry = 5; retry > 0; retry--) { | ||
| 205 | wil_memcpy_fromio_32(&d_head, head, sizeof(d_head)); | ||
| 206 | if (d_head.sync == 0) | ||
| 207 | break; | ||
| 208 | msleep(20); | ||
| 209 | } | ||
| 210 | if (d_head.sync != 0) { | ||
| 211 | wil_err(wil, "WMI head busy\n"); | ||
| 212 | return -EBUSY; | ||
| 213 | } | ||
| 214 | /* next head */ | ||
| 215 | next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size); | ||
| 216 | wil_dbg_WMI(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head); | ||
| 217 | /* wait till FW finish with previous command */ | ||
| 218 | for (retry = 5; retry > 0; retry--) { | ||
| 219 | r->tail = ioread32(wil->csr + HOST_MBOX + | ||
| 220 | offsetof(struct wil6210_mbox_ctl, tx.tail)); | ||
| 221 | if (next_head != r->tail) | ||
| 222 | break; | ||
| 223 | msleep(20); | ||
| 224 | } | ||
| 225 | if (next_head == r->tail) { | ||
| 226 | wil_err(wil, "WMI ring full\n"); | ||
| 227 | return -EBUSY; | ||
| 228 | } | ||
| 229 | dst = wmi_buffer(wil, d_head.addr); | ||
| 230 | if (!dst) { | ||
| 231 | wil_err(wil, "invalid WMI buffer: 0x%08x\n", | ||
| 232 | le32_to_cpu(d_head.addr)); | ||
| 233 | return -EINVAL; | ||
| 234 | } | ||
| 235 | cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq); | ||
| 236 | /* set command */ | ||
| 237 | wil_dbg_WMI(wil, "WMI command 0x%04x [%d]\n", cmdid, len); | ||
| 238 | wil_hex_dump_WMI("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd, | ||
| 239 | sizeof(cmd), true); | ||
| 240 | wil_hex_dump_WMI("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf, | ||
| 241 | len, true); | ||
| 242 | wil_memcpy_toio_32(dst, &cmd, sizeof(cmd)); | ||
| 243 | wil_memcpy_toio_32(dst + sizeof(cmd), buf, len); | ||
| 244 | /* mark entry as full */ | ||
| 245 | iowrite32(1, wil->csr + HOSTADDR(r->head) + | ||
| 246 | offsetof(struct wil6210_mbox_ring_desc, sync)); | ||
| 247 | /* advance next ptr */ | ||
| 248 | iowrite32(r->head = next_head, wil->csr + HOST_MBOX + | ||
| 249 | offsetof(struct wil6210_mbox_ctl, tx.head)); | ||
| 250 | |||
| 251 | /* interrupt to FW */ | ||
| 252 | iowrite32(SW_INT_MBOX, wil->csr + HOST_SW_INT); | ||
| 253 | |||
| 254 | return 0; | ||
| 255 | } | ||
| 256 | |||
| 257 | int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | ||
| 258 | { | ||
| 259 | int rc; | ||
| 260 | |||
| 261 | mutex_lock(&wil->wmi_mutex); | ||
| 262 | rc = __wmi_send(wil, cmdid, buf, len); | ||
| 263 | mutex_unlock(&wil->wmi_mutex); | ||
| 264 | |||
| 265 | return rc; | ||
| 266 | } | ||
| 267 | |||
| 268 | /*=== Event handlers ===*/ | ||
| 269 | static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) | ||
| 270 | { | ||
| 271 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 272 | struct wireless_dev *wdev = wil->wdev; | ||
| 273 | struct wmi_ready_event *evt = d; | ||
| 274 | u32 ver = le32_to_cpu(evt->sw_version); | ||
| 275 | |||
| 276 | wil_dbg_WMI(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac); | ||
| 277 | |||
| 278 | if (!is_valid_ether_addr(ndev->dev_addr)) { | ||
| 279 | memcpy(ndev->dev_addr, evt->mac, ETH_ALEN); | ||
| 280 | memcpy(ndev->perm_addr, evt->mac, ETH_ALEN); | ||
| 281 | } | ||
| 282 | snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), | ||
| 283 | "%d", ver); | ||
| 284 | } | ||
| 285 | |||
| 286 | static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, | ||
| 287 | int len) | ||
| 288 | { | ||
| 289 | wil_dbg_WMI(wil, "WMI: FW ready\n"); | ||
| 290 | |||
| 291 | set_bit(wil_status_fwready, &wil->status); | ||
| 292 | /* reuse wmi_ready for the firmware ready indication */ | ||
| 293 | complete(&wil->wmi_ready); | ||
| 294 | } | ||
| 295 | |||
| 296 | static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | ||
| 297 | { | ||
| 298 | struct wmi_rx_mgmt_packet_event *data = d; | ||
| 299 | struct wiphy *wiphy = wil_to_wiphy(wil); | ||
| 300 | struct ieee80211_mgmt *rx_mgmt_frame = | ||
| 301 | (struct ieee80211_mgmt *)data->payload; | ||
| 302 | int ch_no = data->info.channel+1; | ||
| 303 | u32 freq = ieee80211_channel_to_frequency(ch_no, | ||
| 304 | IEEE80211_BAND_60GHZ); | ||
| 305 | struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq); | ||
| 306 | /* TODO convert LE to CPU */ | ||
| 307 | s32 signal = 0; /* TODO */ | ||
| 308 | __le16 fc = rx_mgmt_frame->frame_control; | ||
| 309 | u32 d_len = le32_to_cpu(data->info.len); | ||
| 310 | u16 d_status = le16_to_cpu(data->info.status); | ||
| 311 | |||
| 312 | wil_dbg_WMI(wil, "MGMT: channel %d MCS %d SNR %d\n", | ||
| 313 | data->info.channel, data->info.mcs, data->info.snr); | ||
| 314 | wil_dbg_WMI(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len, | ||
| 315 | le16_to_cpu(data->info.stype)); | ||
| 316 | wil_dbg_WMI(wil, "qid %d mid %d cid %d\n", | ||
| 317 | data->info.qid, data->info.mid, data->info.cid); | ||
| 318 | |||
| 319 | if (!channel) { | ||
| 320 | wil_err(wil, "Frame on unsupported channel\n"); | ||
| 321 | return; | ||
| 322 | } | ||
| 323 | |||
| 324 | if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) { | ||
| 325 | struct cfg80211_bss *bss; | ||
| 326 | u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp); | ||
| 327 | u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info); | ||
| 328 | u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int); | ||
| 329 | const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable; | ||
| 330 | size_t ie_len = d_len - offsetof(struct ieee80211_mgmt, | ||
| 331 | u.beacon.variable); | ||
| 332 | wil_dbg_WMI(wil, "Capability info : 0x%04x\n", cap); | ||
| 333 | |||
| 334 | bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid, | ||
| 335 | tsf, cap, bi, ie_buf, ie_len, | ||
| 336 | signal, GFP_KERNEL); | ||
| 337 | if (bss) { | ||
| 338 | wil_dbg_WMI(wil, "Added BSS %pM\n", | ||
| 339 | rx_mgmt_frame->bssid); | ||
| 340 | cfg80211_put_bss(bss); | ||
| 341 | } else { | ||
| 342 | wil_err(wil, "cfg80211_inform_bss() failed\n"); | ||
| 343 | } | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, | ||
| 348 | void *d, int len) | ||
| 349 | { | ||
| 350 | if (wil->scan_request) { | ||
| 351 | struct wmi_scan_complete_event *data = d; | ||
| 352 | bool aborted = (data->status != 0); | ||
| 353 | |||
| 354 | wil_dbg_WMI(wil, "SCAN_COMPLETE(0x%08x)\n", data->status); | ||
| 355 | cfg80211_scan_done(wil->scan_request, aborted); | ||
| 356 | wil->scan_request = NULL; | ||
| 357 | } else { | ||
| 358 | wil_err(wil, "SCAN_COMPLETE while not scanning\n"); | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | ||
| 363 | { | ||
| 364 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 365 | struct wireless_dev *wdev = wil->wdev; | ||
| 366 | struct wmi_connect_event *evt = d; | ||
| 367 | int ch; /* channel number */ | ||
| 368 | struct station_info sinfo; | ||
| 369 | u8 *assoc_req_ie, *assoc_resp_ie; | ||
| 370 | size_t assoc_req_ielen, assoc_resp_ielen; | ||
| 371 | /* capinfo(u16) + listen_interval(u16) + IEs */ | ||
| 372 | const size_t assoc_req_ie_offset = sizeof(u16) * 2; | ||
| 373 | /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */ | ||
| 374 | const size_t assoc_resp_ie_offset = sizeof(u16) * 3; | ||
| 375 | |||
| 376 | if (len < sizeof(*evt)) { | ||
| 377 | wil_err(wil, "Connect event too short : %d bytes\n", len); | ||
| 378 | return; | ||
| 379 | } | ||
| 380 | if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len + | ||
| 381 | evt->assoc_resp_len) { | ||
| 382 | wil_err(wil, | ||
| 383 | "Connect event corrupted : %d != %d + %d + %d + %d\n", | ||
| 384 | len, (int)sizeof(*evt), evt->beacon_ie_len, | ||
| 385 | evt->assoc_req_len, evt->assoc_resp_len); | ||
| 386 | return; | ||
| 387 | } | ||
| 388 | ch = evt->channel + 1; | ||
| 389 | wil_dbg_WMI(wil, "Connect %pM channel [%d] cid %d\n", | ||
| 390 | evt->bssid, ch, evt->cid); | ||
| 391 | wil_hex_dump_WMI("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, | ||
| 392 | evt->assoc_info, len - sizeof(*evt), true); | ||
| 393 | |||
| 394 | /* figure out IE's */ | ||
| 395 | assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len + | ||
| 396 | assoc_req_ie_offset]; | ||
| 397 | assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset; | ||
| 398 | if (evt->assoc_req_len <= assoc_req_ie_offset) { | ||
| 399 | assoc_req_ie = NULL; | ||
| 400 | assoc_req_ielen = 0; | ||
| 401 | } | ||
| 402 | |||
| 403 | assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len + | ||
| 404 | evt->assoc_req_len + | ||
| 405 | assoc_resp_ie_offset]; | ||
| 406 | assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset; | ||
| 407 | if (evt->assoc_resp_len <= assoc_resp_ie_offset) { | ||
| 408 | assoc_resp_ie = NULL; | ||
| 409 | assoc_resp_ielen = 0; | ||
| 410 | } | ||
| 411 | |||
| 412 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || | ||
| 413 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { | ||
| 414 | if (wdev->sme_state != CFG80211_SME_CONNECTING) { | ||
| 415 | wil_err(wil, "Not in connecting state\n"); | ||
| 416 | return; | ||
| 417 | } | ||
| 418 | del_timer_sync(&wil->connect_timer); | ||
| 419 | cfg80211_connect_result(ndev, evt->bssid, | ||
| 420 | assoc_req_ie, assoc_req_ielen, | ||
| 421 | assoc_resp_ie, assoc_resp_ielen, | ||
| 422 | WLAN_STATUS_SUCCESS, GFP_KERNEL); | ||
| 423 | |||
| 424 | } else if ((wdev->iftype == NL80211_IFTYPE_AP) || | ||
| 425 | (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { | ||
| 426 | memset(&sinfo, 0, sizeof(sinfo)); | ||
| 427 | |||
| 428 | sinfo.generation = wil->sinfo_gen++; | ||
| 429 | |||
| 430 | if (assoc_req_ie) { | ||
| 431 | sinfo.assoc_req_ies = assoc_req_ie; | ||
| 432 | sinfo.assoc_req_ies_len = assoc_req_ielen; | ||
| 433 | sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; | ||
| 434 | } | ||
| 435 | |||
| 436 | cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); | ||
| 437 | } | ||
| 438 | set_bit(wil_status_fwconnected, &wil->status); | ||
| 439 | |||
| 440 | /* FIXME FW can transmit only ucast frames to peer */ | ||
| 441 | /* FIXME real ring_id instead of hard coded 0 */ | ||
| 442 | memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN); | ||
| 443 | |||
| 444 | wil->pending_connect_cid = evt->cid; | ||
| 445 | queue_work(wil->wmi_wq_conn, &wil->wmi_connect_worker); | ||
| 446 | } | ||
| 447 | |||
| 448 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | ||
| 449 | void *d, int len) | ||
| 450 | { | ||
| 451 | struct wmi_disconnect_event *evt = d; | ||
| 452 | |||
| 453 | wil_dbg_WMI(wil, "Disconnect %pM reason %d proto %d wmi\n", | ||
| 454 | evt->bssid, | ||
| 455 | evt->protocol_reason_status, evt->disconnect_reason); | ||
| 456 | |||
| 457 | wil->sinfo_gen++; | ||
| 458 | |||
| 459 | wil6210_disconnect(wil, evt->bssid); | ||
| 460 | clear_bit(wil_status_dontscan, &wil->status); | ||
| 461 | } | ||
| 462 | |||
| 463 | static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len) | ||
| 464 | { | ||
| 465 | struct wmi_notify_req_done_event *evt = d; | ||
| 466 | |||
| 467 | if (len < sizeof(*evt)) { | ||
| 468 | wil_err(wil, "Short NOTIFY event\n"); | ||
| 469 | return; | ||
| 470 | } | ||
| 471 | |||
| 472 | wil->stats.tsf = le64_to_cpu(evt->tsf); | ||
| 473 | wil->stats.snr = le32_to_cpu(evt->snr_val); | ||
| 474 | wil->stats.bf_mcs = le16_to_cpu(evt->bf_mcs); | ||
| 475 | wil->stats.my_rx_sector = le16_to_cpu(evt->my_rx_sector); | ||
| 476 | wil->stats.my_tx_sector = le16_to_cpu(evt->my_tx_sector); | ||
| 477 | wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector); | ||
| 478 | wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector); | ||
| 479 | wil_dbg_WMI(wil, "Link status, MCS %d TSF 0x%016llx\n" | ||
| 480 | "BF status 0x%08x SNR 0x%08x\n" | ||
| 481 | "Tx Tpt %d goodput %d Rx goodput %d\n" | ||
| 482 | "Sectors(rx:tx) my %d:%d peer %d:%d\n", | ||
| 483 | wil->stats.bf_mcs, wil->stats.tsf, evt->status, | ||
| 484 | wil->stats.snr, le32_to_cpu(evt->tx_tpt), | ||
| 485 | le32_to_cpu(evt->tx_goodput), le32_to_cpu(evt->rx_goodput), | ||
| 486 | wil->stats.my_rx_sector, wil->stats.my_tx_sector, | ||
| 487 | wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); | ||
| 488 | } | ||
| 489 | |||
| 490 | /* | ||
| 491 | * Firmware reports EAPOL frame using WME event. | ||
| 492 | * Reconstruct Ethernet frame and deliver it via normal Rx | ||
| 493 | */ | ||
| 494 | static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, | ||
| 495 | void *d, int len) | ||
| 496 | { | ||
| 497 | struct net_device *ndev = wil_to_ndev(wil); | ||
| 498 | struct wmi_eapol_rx_event *evt = d; | ||
| 499 | u16 eapol_len = le16_to_cpu(evt->eapol_len); | ||
| 500 | int sz = eapol_len + ETH_HLEN; | ||
| 501 | struct sk_buff *skb; | ||
| 502 | struct ethhdr *eth; | ||
| 503 | |||
| 504 | wil_dbg_WMI(wil, "EAPOL len %d from %pM\n", eapol_len, | ||
| 505 | evt->src_mac); | ||
| 506 | |||
| 507 | if (eapol_len > 196) { /* TODO: revisit size limit */ | ||
| 508 | wil_err(wil, "EAPOL too large\n"); | ||
| 509 | return; | ||
| 510 | } | ||
| 511 | |||
| 512 | skb = alloc_skb(sz, GFP_KERNEL); | ||
| 513 | if (!skb) { | ||
| 514 | wil_err(wil, "Failed to allocate skb\n"); | ||
| 515 | return; | ||
| 516 | } | ||
| 517 | eth = (struct ethhdr *)skb_put(skb, ETH_HLEN); | ||
| 518 | memcpy(eth->h_dest, ndev->dev_addr, ETH_ALEN); | ||
| 519 | memcpy(eth->h_source, evt->src_mac, ETH_ALEN); | ||
| 520 | eth->h_proto = cpu_to_be16(ETH_P_PAE); | ||
| 521 | memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len); | ||
| 522 | skb->protocol = eth_type_trans(skb, ndev); | ||
| 523 | if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) { | ||
| 524 | ndev->stats.rx_packets++; | ||
| 525 | ndev->stats.rx_bytes += skb->len; | ||
| 526 | } else { | ||
| 527 | ndev->stats.rx_dropped++; | ||
| 528 | } | ||
| 529 | } | ||
| 530 | |||
| 531 | static const struct { | ||
| 532 | int eventid; | ||
| 533 | void (*handler)(struct wil6210_priv *wil, int eventid, | ||
| 534 | void *data, int data_len); | ||
| 535 | } wmi_evt_handlers[] = { | ||
| 536 | {WMI_READY_EVENTID, wmi_evt_ready}, | ||
| 537 | {WMI_FW_READY_EVENTID, wmi_evt_fw_ready}, | ||
| 538 | {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt}, | ||
| 539 | {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete}, | ||
| 540 | {WMI_CONNECT_EVENTID, wmi_evt_connect}, | ||
| 541 | {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect}, | ||
| 542 | {WMI_NOTIFY_REQ_DONE_EVENTID, wmi_evt_notify}, | ||
| 543 | {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx}, | ||
| 544 | }; | ||
| 545 | |||
| 546 | /* | ||
| 547 | * Run in IRQ context | ||
| 548 | * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev | ||
| 549 | * that will be eventually handled by the @wmi_event_worker in the thread | ||
| 550 | * context of thread "wil6210_wmi" | ||
| 551 | */ | ||
| 552 | void wmi_recv_cmd(struct wil6210_priv *wil) | ||
| 553 | { | ||
| 554 | struct wil6210_mbox_ring_desc d_tail; | ||
| 555 | struct wil6210_mbox_hdr hdr; | ||
| 556 | struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx; | ||
| 557 | struct pending_wmi_event *evt; | ||
| 558 | u8 *cmd; | ||
| 559 | void __iomem *src; | ||
| 560 | ulong flags; | ||
| 561 | |||
| 562 | for (;;) { | ||
| 563 | u16 len; | ||
| 564 | |||
| 565 | r->head = ioread32(wil->csr + HOST_MBOX + | ||
| 566 | offsetof(struct wil6210_mbox_ctl, rx.head)); | ||
| 567 | if (r->tail == r->head) | ||
| 568 | return; | ||
| 569 | |||
| 570 | /* read cmd from tail */ | ||
| 571 | wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail), | ||
| 572 | sizeof(struct wil6210_mbox_ring_desc)); | ||
| 573 | if (d_tail.sync == 0) { | ||
| 574 | wil_err(wil, "Mbox evt not owned by FW?\n"); | ||
| 575 | return; | ||
| 576 | } | ||
| 577 | |||
| 578 | if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) { | ||
| 579 | wil_err(wil, "Mbox evt at 0x%08x?\n", | ||
| 580 | le32_to_cpu(d_tail.addr)); | ||
| 581 | return; | ||
| 582 | } | ||
| 583 | |||
| 584 | len = le16_to_cpu(hdr.len); | ||
| 585 | src = wmi_buffer(wil, d_tail.addr) + | ||
| 586 | sizeof(struct wil6210_mbox_hdr); | ||
| 587 | evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event, | ||
| 588 | event.wmi) + len, 4), | ||
| 589 | GFP_KERNEL); | ||
| 590 | if (!evt) { | ||
| 591 | wil_err(wil, "kmalloc for WMI event (%d) failed\n", | ||
| 592 | len); | ||
| 593 | return; | ||
| 594 | } | ||
| 595 | evt->event.hdr = hdr; | ||
| 596 | cmd = (void *)&evt->event.wmi; | ||
| 597 | wil_memcpy_fromio_32(cmd, src, len); | ||
| 598 | /* mark entry as empty */ | ||
| 599 | iowrite32(0, wil->csr + HOSTADDR(r->tail) + | ||
| 600 | offsetof(struct wil6210_mbox_ring_desc, sync)); | ||
| 601 | /* indicate */ | ||
| 602 | wil_dbg_WMI(wil, "Mbox evt %04x %04x %04x %02x\n", | ||
| 603 | le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type), | ||
| 604 | hdr.flags); | ||
| 605 | if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) && | ||
| 606 | (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { | ||
| 607 | wil_dbg_WMI(wil, "WMI event 0x%04x\n", | ||
| 608 | evt->event.wmi.id); | ||
| 609 | } | ||
| 610 | wil_hex_dump_WMI("evt ", DUMP_PREFIX_OFFSET, 16, 1, | ||
| 611 | &evt->event.hdr, sizeof(hdr) + len, true); | ||
| 612 | |||
| 613 | /* advance tail */ | ||
| 614 | r->tail = r->base + ((r->tail - r->base + | ||
| 615 | sizeof(struct wil6210_mbox_ring_desc)) % r->size); | ||
| 616 | iowrite32(r->tail, wil->csr + HOST_MBOX + | ||
| 617 | offsetof(struct wil6210_mbox_ctl, rx.tail)); | ||
| 618 | |||
| 619 | /* add to the pending list */ | ||
| 620 | spin_lock_irqsave(&wil->wmi_ev_lock, flags); | ||
| 621 | list_add_tail(&evt->list, &wil->pending_wmi_ev); | ||
| 622 | spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); | ||
| 623 | { | ||
| 624 | int q = queue_work(wil->wmi_wq, | ||
| 625 | &wil->wmi_event_worker); | ||
| 626 | wil_dbg_WMI(wil, "queue_work -> %d\n", q); | ||
| 627 | } | ||
| 628 | } | ||
| 629 | } | ||
| 630 | |||
| 631 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | ||
| 632 | u16 reply_id, void *reply, u8 reply_size, int to_msec) | ||
| 633 | { | ||
| 634 | int rc; | ||
| 635 | int remain; | ||
| 636 | |||
| 637 | mutex_lock(&wil->wmi_mutex); | ||
| 638 | |||
| 639 | rc = __wmi_send(wil, cmdid, buf, len); | ||
| 640 | if (rc) | ||
| 641 | goto out; | ||
| 642 | |||
| 643 | wil->reply_id = reply_id; | ||
| 644 | wil->reply_buf = reply; | ||
| 645 | wil->reply_size = reply_size; | ||
| 646 | remain = wait_for_completion_timeout(&wil->wmi_ready, | ||
| 647 | msecs_to_jiffies(to_msec)); | ||
| 648 | if (0 == remain) { | ||
| 649 | wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n", | ||
| 650 | cmdid, reply_id, to_msec); | ||
| 651 | rc = -ETIME; | ||
| 652 | } else { | ||
| 653 | wil_dbg_WMI(wil, | ||
| 654 | "wmi_call(0x%04x->0x%04x) completed in %d msec\n", | ||
| 655 | cmdid, reply_id, | ||
| 656 | to_msec - jiffies_to_msecs(remain)); | ||
| 657 | } | ||
| 658 | wil->reply_id = 0; | ||
| 659 | wil->reply_buf = NULL; | ||
| 660 | wil->reply_size = 0; | ||
| 661 | out: | ||
| 662 | mutex_unlock(&wil->wmi_mutex); | ||
| 663 | |||
| 664 | return rc; | ||
| 665 | } | ||
| 666 | |||
| 667 | int wmi_echo(struct wil6210_priv *wil) | ||
| 668 | { | ||
| 669 | struct wmi_echo_cmd cmd = { | ||
| 670 | .value = cpu_to_le32(0x12345678), | ||
| 671 | }; | ||
| 672 | |||
| 673 | return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd), | ||
| 674 | WMI_ECHO_RSP_EVENTID, NULL, 0, 20); | ||
| 675 | } | ||
| 676 | |||
| 677 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) | ||
| 678 | { | ||
| 679 | struct wmi_set_mac_address_cmd cmd; | ||
| 680 | |||
| 681 | memcpy(cmd.mac, addr, ETH_ALEN); | ||
| 682 | |||
| 683 | wil_dbg_WMI(wil, "Set MAC %pM\n", addr); | ||
| 684 | |||
| 685 | return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); | ||
| 686 | } | ||
| 687 | |||
| 688 | int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype) | ||
| 689 | { | ||
| 690 | struct wmi_bcon_ctrl_cmd cmd = { | ||
| 691 | .bcon_interval = cpu_to_le16(bi), | ||
| 692 | .network_type = wmi_nettype, | ||
| 693 | .disable_sec_offload = 1, | ||
| 694 | }; | ||
| 695 | |||
| 696 | if (!wil->secure_pcp) | ||
| 697 | cmd.disable_sec = 1; | ||
| 698 | |||
| 699 | return wmi_send(wil, WMI_BCON_CTRL_CMDID, &cmd, sizeof(cmd)); | ||
| 700 | } | ||
| 701 | |||
| 702 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) | ||
| 703 | { | ||
| 704 | struct wmi_set_ssid_cmd cmd = { | ||
| 705 | .ssid_len = cpu_to_le32(ssid_len), | ||
| 706 | }; | ||
| 707 | |||
| 708 | if (ssid_len > sizeof(cmd.ssid)) | ||
| 709 | return -EINVAL; | ||
| 710 | |||
| 711 | memcpy(cmd.ssid, ssid, ssid_len); | ||
| 712 | |||
| 713 | return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd)); | ||
| 714 | } | ||
| 715 | |||
| 716 | int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) | ||
| 717 | { | ||
| 718 | int rc; | ||
| 719 | struct { | ||
| 720 | struct wil6210_mbox_hdr_wmi wmi; | ||
| 721 | struct wmi_set_ssid_cmd cmd; | ||
| 722 | } __packed reply; | ||
| 723 | int len; /* reply.cmd.ssid_len in CPU order */ | ||
| 724 | |||
| 725 | rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID, | ||
| 726 | &reply, sizeof(reply), 20); | ||
| 727 | if (rc) | ||
| 728 | return rc; | ||
| 729 | |||
| 730 | len = le32_to_cpu(reply.cmd.ssid_len); | ||
| 731 | if (len > sizeof(reply.cmd.ssid)) | ||
| 732 | return -EINVAL; | ||
| 733 | |||
| 734 | *ssid_len = len; | ||
| 735 | memcpy(ssid, reply.cmd.ssid, len); | ||
| 736 | |||
| 737 | return 0; | ||
| 738 | } | ||
| 739 | |||
| 740 | int wmi_set_channel(struct wil6210_priv *wil, int channel) | ||
| 741 | { | ||
| 742 | struct wmi_set_pcp_channel_cmd cmd = { | ||
| 743 | .channel = channel - 1, | ||
| 744 | }; | ||
| 745 | |||
| 746 | return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd)); | ||
| 747 | } | ||
| 748 | |||
| 749 | int wmi_get_channel(struct wil6210_priv *wil, int *channel) | ||
| 750 | { | ||
| 751 | int rc; | ||
| 752 | struct { | ||
| 753 | struct wil6210_mbox_hdr_wmi wmi; | ||
| 754 | struct wmi_set_pcp_channel_cmd cmd; | ||
| 755 | } __packed reply; | ||
| 756 | |||
| 757 | rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0, | ||
| 758 | WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20); | ||
| 759 | if (rc) | ||
| 760 | return rc; | ||
| 761 | |||
| 762 | if (reply.cmd.channel > 3) | ||
| 763 | return -EINVAL; | ||
| 764 | |||
| 765 | *channel = reply.cmd.channel + 1; | ||
| 766 | |||
| 767 | return 0; | ||
| 768 | } | ||
| 769 | |||
| 770 | int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb) | ||
| 771 | { | ||
| 772 | struct wmi_eapol_tx_cmd *cmd; | ||
| 773 | struct ethhdr *eth; | ||
| 774 | u16 eapol_len = skb->len - ETH_HLEN; | ||
| 775 | void *eapol = skb->data + ETH_HLEN; | ||
| 776 | uint i; | ||
| 777 | int rc; | ||
| 778 | |||
| 779 | skb_set_mac_header(skb, 0); | ||
| 780 | eth = eth_hdr(skb); | ||
| 781 | wil_dbg_WMI(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest); | ||
| 782 | for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { | ||
| 783 | if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0) | ||
| 784 | goto found_dest; | ||
| 785 | } | ||
| 786 | |||
| 787 | return -EINVAL; | ||
| 788 | |||
| 789 | found_dest: | ||
| 790 | /* find out eapol data & len */ | ||
| 791 | cmd = kzalloc(sizeof(*cmd) + eapol_len, GFP_KERNEL); | ||
| 792 | if (!cmd) | ||
| 793 | return -EINVAL; | ||
| 794 | |||
| 795 | memcpy(cmd->dst_mac, eth->h_dest, ETH_ALEN); | ||
| 796 | cmd->eapol_len = cpu_to_le16(eapol_len); | ||
| 797 | memcpy(cmd->eapol, eapol, eapol_len); | ||
| 798 | rc = wmi_send(wil, WMI_EAPOL_TX_CMDID, cmd, sizeof(*cmd) + eapol_len); | ||
| 799 | kfree(cmd); | ||
| 800 | |||
| 801 | return rc; | ||
| 802 | } | ||
| 803 | |||
| 804 | int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
| 805 | const void *mac_addr) | ||
| 806 | { | ||
| 807 | struct wmi_delete_cipher_key_cmd cmd = { | ||
| 808 | .key_index = key_index, | ||
| 809 | }; | ||
| 810 | |||
| 811 | if (mac_addr) | ||
| 812 | memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); | ||
| 813 | |||
| 814 | return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); | ||
| 815 | } | ||
| 816 | |||
| 817 | int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
| 818 | const void *mac_addr, int key_len, const void *key) | ||
| 819 | { | ||
| 820 | struct wmi_add_cipher_key_cmd cmd = { | ||
| 821 | .key_index = key_index, | ||
| 822 | .key_usage = WMI_KEY_USE_PAIRWISE, | ||
| 823 | .key_len = key_len, | ||
| 824 | }; | ||
| 825 | |||
| 826 | if (!key || (key_len > sizeof(cmd.key))) | ||
| 827 | return -EINVAL; | ||
| 828 | |||
| 829 | memcpy(cmd.key, key, key_len); | ||
| 830 | if (mac_addr) | ||
| 831 | memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); | ||
| 832 | |||
| 833 | return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); | ||
| 834 | } | ||
| 835 | |||
| 836 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) | ||
| 837 | { | ||
| 838 | int rc; | ||
| 839 | u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len; | ||
| 840 | struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL); | ||
| 841 | if (!cmd) { | ||
| 842 | wil_err(wil, "kmalloc(%d) failed\n", len); | ||
| 843 | return -ENOMEM; | ||
| 844 | } | ||
| 845 | |||
| 846 | cmd->mgmt_frm_type = type; | ||
| 847 | /* BUG: FW API define ieLen as u8. Will fix FW */ | ||
| 848 | cmd->ie_len = cpu_to_le16(ie_len); | ||
| 849 | memcpy(cmd->ie_info, ie, ie_len); | ||
| 850 | rc = wmi_send(wil, WMI_SET_APPIE_CMDID, &cmd, len); | ||
| 851 | kfree(cmd); | ||
| 852 | |||
| 853 | return rc; | ||
| 854 | } | ||
| 855 | |||
| 856 | void wmi_event_flush(struct wil6210_priv *wil) | ||
| 857 | { | ||
| 858 | struct pending_wmi_event *evt, *t; | ||
| 859 | |||
| 860 | wil_dbg_WMI(wil, "%s()\n", __func__); | ||
| 861 | |||
| 862 | list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) { | ||
| 863 | list_del(&evt->list); | ||
| 864 | kfree(evt); | ||
| 865 | } | ||
| 866 | } | ||
| 867 | |||
| 868 | static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id, | ||
| 869 | void *d, int len) | ||
| 870 | { | ||
| 871 | uint i; | ||
| 872 | |||
| 873 | for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) { | ||
| 874 | if (wmi_evt_handlers[i].eventid == id) { | ||
| 875 | wmi_evt_handlers[i].handler(wil, id, d, len); | ||
| 876 | return true; | ||
| 877 | } | ||
| 878 | } | ||
| 879 | |||
| 880 | return false; | ||
| 881 | } | ||
| 882 | |||
| 883 | static void wmi_event_handle(struct wil6210_priv *wil, | ||
| 884 | struct wil6210_mbox_hdr *hdr) | ||
| 885 | { | ||
| 886 | u16 len = le16_to_cpu(hdr->len); | ||
| 887 | |||
| 888 | if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) && | ||
| 889 | (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { | ||
| 890 | struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]); | ||
| 891 | void *evt_data = (void *)(&wmi[1]); | ||
| 892 | u16 id = le16_to_cpu(wmi->id); | ||
| 893 | /* check if someone waits for this event */ | ||
| 894 | if (wil->reply_id && wil->reply_id == id) { | ||
| 895 | if (wil->reply_buf) { | ||
| 896 | memcpy(wil->reply_buf, wmi, | ||
| 897 | min(len, wil->reply_size)); | ||
| 898 | } else { | ||
| 899 | wmi_evt_call_handler(wil, id, evt_data, | ||
| 900 | len - sizeof(*wmi)); | ||
| 901 | } | ||
| 902 | wil_dbg_WMI(wil, "Complete WMI 0x%04x\n", id); | ||
| 903 | complete(&wil->wmi_ready); | ||
| 904 | return; | ||
| 905 | } | ||
| 906 | /* unsolicited event */ | ||
| 907 | /* search for handler */ | ||
| 908 | if (!wmi_evt_call_handler(wil, id, evt_data, | ||
| 909 | len - sizeof(*wmi))) { | ||
| 910 | wil_err(wil, "Unhandled event 0x%04x\n", id); | ||
| 911 | } | ||
| 912 | } else { | ||
| 913 | wil_err(wil, "Unknown event type\n"); | ||
| 914 | print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1, | ||
| 915 | hdr, sizeof(*hdr) + len, true); | ||
| 916 | } | ||
| 917 | } | ||
| 918 | |||
| 919 | /* | ||
| 920 | * Retrieve next WMI event from the pending list | ||
| 921 | */ | ||
| 922 | static struct list_head *next_wmi_ev(struct wil6210_priv *wil) | ||
| 923 | { | ||
| 924 | ulong flags; | ||
| 925 | struct list_head *ret = NULL; | ||
| 926 | |||
| 927 | spin_lock_irqsave(&wil->wmi_ev_lock, flags); | ||
| 928 | |||
| 929 | if (!list_empty(&wil->pending_wmi_ev)) { | ||
| 930 | ret = wil->pending_wmi_ev.next; | ||
| 931 | list_del(ret); | ||
| 932 | } | ||
| 933 | |||
| 934 | spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); | ||
| 935 | |||
| 936 | return ret; | ||
| 937 | } | ||
| 938 | |||
| 939 | /* | ||
| 940 | * Handler for the WMI events | ||
| 941 | */ | ||
| 942 | void wmi_event_worker(struct work_struct *work) | ||
| 943 | { | ||
| 944 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
| 945 | wmi_event_worker); | ||
| 946 | struct pending_wmi_event *evt; | ||
| 947 | struct list_head *lh; | ||
| 948 | |||
| 949 | while ((lh = next_wmi_ev(wil)) != NULL) { | ||
| 950 | evt = list_entry(lh, struct pending_wmi_event, list); | ||
| 951 | wmi_event_handle(wil, &evt->event.hdr); | ||
| 952 | kfree(evt); | ||
| 953 | } | ||
| 954 | } | ||
| 955 | |||
| 956 | void wmi_connect_worker(struct work_struct *work) | ||
| 957 | { | ||
| 958 | int rc; | ||
| 959 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
| 960 | wmi_connect_worker); | ||
| 961 | |||
| 962 | if (wil->pending_connect_cid < 0) { | ||
| 963 | wil_err(wil, "No connection pending\n"); | ||
| 964 | return; | ||
| 965 | } | ||
| 966 | |||
| 967 | wil_dbg_WMI(wil, "Configure for connection CID %d\n", | ||
| 968 | wil->pending_connect_cid); | ||
| 969 | |||
| 970 | rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, | ||
| 971 | wil->pending_connect_cid, 0); | ||
| 972 | wil->pending_connect_cid = -1; | ||
| 973 | if (rc == 0) | ||
| 974 | wil_link_on(wil); | ||
| 975 | } | ||
| @@ -0,0 +1,1116 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
| 3 | * Copyright (c) 2006-2012 Wilocity . | ||
| 4 | * | ||
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 6 | * purpose with or without fee is hereby granted, provided that the above | ||
| 7 | * copyright notice and this permission notice appear in all copies. | ||
| 8 | * | ||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 16 | */ | ||
| 17 | |||
| 18 | /* | ||
| 19 | * This file contains the definitions of the WMI protocol specified in the | ||
| 20 | * Wireless Module Interface (WMI) for the Wilocity | ||
| 21 | * MARLON 60 Gigabit wireless solution. | ||
| 22 | * It includes definitions of all the commands and events. | ||
| 23 | * Commands are messages from the host to the WM. | ||
| 24 | * Events are messages from the WM to the host. | ||
| 25 | */ | ||
| 26 | |||
| 27 | #ifndef __WILOCITY_WMI_H__ | ||
| 28 | #define __WILOCITY_WMI_H__ | ||
| 29 | |||
| 30 | /* General */ | ||
| 31 | |||
| 32 | #define WMI_MAC_LEN (6) | ||
| 33 | #define WMI_PROX_RANGE_NUM (3) | ||
| 34 | |||
| 35 | /* List of Commands */ | ||
| 36 | enum wmi_command_id { | ||
| 37 | WMI_CONNECT_CMDID = 0x0001, | ||
| 38 | WMI_DISCONNECT_CMDID = 0x0003, | ||
| 39 | WMI_START_SCAN_CMDID = 0x0007, | ||
| 40 | WMI_SET_BSS_FILTER_CMDID = 0x0009, | ||
| 41 | WMI_SET_PROBED_SSID_CMDID = 0x000a, | ||
| 42 | WMI_SET_LISTEN_INT_CMDID = 0x000b, | ||
| 43 | WMI_BCON_CTRL_CMDID = 0x000f, | ||
| 44 | WMI_ADD_CIPHER_KEY_CMDID = 0x0016, | ||
| 45 | WMI_DELETE_CIPHER_KEY_CMDID = 0x0017, | ||
| 46 | WMI_SET_APPIE_CMDID = 0x003f, | ||
| 47 | WMI_GET_APPIE_CMDID = 0x0040, | ||
| 48 | WMI_SET_WSC_STATUS_CMDID = 0x0041, | ||
| 49 | WMI_PXMT_RANGE_CFG_CMDID = 0x0042, | ||
| 50 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, | ||
| 51 | WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, | ||
| 52 | WMI_MEM_READ_CMDID = 0x0800, | ||
| 53 | WMI_MEM_WR_CMDID = 0x0801, | ||
| 54 | WMI_ECHO_CMDID = 0x0803, | ||
| 55 | WMI_DEEP_ECHO_CMDID = 0x0804, | ||
| 56 | WMI_CONFIG_MAC_CMDID = 0x0805, | ||
| 57 | WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806, | ||
| 58 | WMI_ADD_STATION_CMDID = 0x0807, | ||
| 59 | WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808, | ||
| 60 | WMI_PHY_GET_STATISTICS_CMDID = 0x0809, | ||
| 61 | WMI_FS_TUNE_CMDID = 0x080a, | ||
| 62 | WMI_CORR_MEASURE_CMDID = 0x080b, | ||
| 63 | WMI_TEMP_SENSE_CMDID = 0x080e, | ||
| 64 | WMI_DC_CALIB_CMDID = 0x080f, | ||
| 65 | WMI_SEND_TONE_CMDID = 0x0810, | ||
| 66 | WMI_IQ_TX_CALIB_CMDID = 0x0811, | ||
| 67 | WMI_IQ_RX_CALIB_CMDID = 0x0812, | ||
| 68 | WMI_SET_UCODE_IDLE_CMDID = 0x0813, | ||
| 69 | WMI_SET_WORK_MODE_CMDID = 0x0815, | ||
| 70 | WMI_LO_LEAKAGE_CALIB_CMDID = 0x0816, | ||
| 71 | WMI_MARLON_R_ACTIVATE_CMDID = 0x0817, | ||
| 72 | WMI_MARLON_R_READ_CMDID = 0x0818, | ||
| 73 | WMI_MARLON_R_WRITE_CMDID = 0x0819, | ||
| 74 | WMI_MARLON_R_TXRX_SEL_CMDID = 0x081a, | ||
| 75 | MAC_IO_STATIC_PARAMS_CMDID = 0x081b, | ||
| 76 | MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c, | ||
| 77 | WMI_SILENT_RSSI_CALIB_CMDID = 0x081d, | ||
| 78 | WMI_CFG_RX_CHAIN_CMDID = 0x0820, | ||
| 79 | WMI_VRING_CFG_CMDID = 0x0821, | ||
| 80 | WMI_RX_ON_CMDID = 0x0822, | ||
| 81 | WMI_VRING_BA_EN_CMDID = 0x0823, | ||
| 82 | WMI_VRING_BA_DIS_CMDID = 0x0824, | ||
| 83 | WMI_RCP_ADDBA_RESP_CMDID = 0x0825, | ||
| 84 | WMI_RCP_DELBA_CMDID = 0x0826, | ||
| 85 | WMI_SET_SSID_CMDID = 0x0827, | ||
| 86 | WMI_GET_SSID_CMDID = 0x0828, | ||
| 87 | WMI_SET_PCP_CHANNEL_CMDID = 0x0829, | ||
| 88 | WMI_GET_PCP_CHANNEL_CMDID = 0x082a, | ||
| 89 | WMI_SW_TX_REQ_CMDID = 0x082b, | ||
| 90 | WMI_RX_OFF_CMDID = 0x082c, | ||
| 91 | WMI_READ_MAC_RXQ_CMDID = 0x0830, | ||
| 92 | WMI_READ_MAC_TXQ_CMDID = 0x0831, | ||
| 93 | WMI_WRITE_MAC_RXQ_CMDID = 0x0832, | ||
| 94 | WMI_WRITE_MAC_TXQ_CMDID = 0x0833, | ||
| 95 | WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x0834, | ||
| 96 | WMI_MLME_PUSH_CMDID = 0x0835, | ||
| 97 | WMI_BEAMFORMING_MGMT_CMDID = 0x0836, | ||
| 98 | WMI_BF_TXSS_MGMT_CMDID = 0x0837, | ||
| 99 | WMI_BF_SM_MGMT_CMDID = 0x0838, | ||
| 100 | WMI_BF_RXSS_MGMT_CMDID = 0x0839, | ||
| 101 | WMI_SET_SECTORS_CMDID = 0x0849, | ||
| 102 | WMI_MAINTAIN_PAUSE_CMDID = 0x0850, | ||
| 103 | WMI_MAINTAIN_RESUME_CMDID = 0x0851, | ||
| 104 | WMI_RS_MGMT_CMDID = 0x0852, | ||
| 105 | WMI_RF_MGMT_CMDID = 0x0853, | ||
| 106 | /* Performance monitoring commands */ | ||
| 107 | WMI_BF_CTRL_CMDID = 0x0862, | ||
| 108 | WMI_NOTIFY_REQ_CMDID = 0x0863, | ||
| 109 | WMI_GET_STATUS_CMDID = 0x0864, | ||
| 110 | WMI_UNIT_TEST_CMDID = 0x0900, | ||
| 111 | WMI_HICCUP_CMDID = 0x0901, | ||
| 112 | WMI_FLASH_READ_CMDID = 0x0902, | ||
| 113 | WMI_FLASH_WRITE_CMDID = 0x0903, | ||
| 114 | WMI_SECURITY_UNIT_TEST_CMDID = 0x0904, | ||
| 115 | |||
| 116 | WMI_SET_MAC_ADDRESS_CMDID = 0xf003, | ||
| 117 | WMI_ABORT_SCAN_CMDID = 0xf007, | ||
| 118 | WMI_SET_PMK_CMDID = 0xf028, | ||
| 119 | |||
| 120 | WMI_SET_PROMISCUOUS_MODE_CMDID = 0xf041, | ||
| 121 | WMI_GET_PMK_CMDID = 0xf048, | ||
| 122 | WMI_SET_PASSPHRASE_CMDID = 0xf049, | ||
| 123 | WMI_SEND_ASSOC_RES_CMDID = 0xf04a, | ||
| 124 | WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xf04b, | ||
| 125 | WMI_EAPOL_TX_CMDID = 0xf04c, | ||
| 126 | WMI_MAC_ADDR_REQ_CMDID = 0xf04d, | ||
| 127 | WMI_FW_VER_CMDID = 0xf04e, | ||
| 128 | }; | ||
| 129 | |||
| 130 | /* | ||
| 131 | * Commands data structures | ||
| 132 | */ | ||
| 133 | |||
| 134 | /* | ||
| 135 | * Frame Types | ||
| 136 | */ | ||
| 137 | enum wmi_mgmt_frame_type { | ||
| 138 | WMI_FRAME_BEACON = 0, | ||
| 139 | WMI_FRAME_PROBE_REQ = 1, | ||
| 140 | WMI_FRAME_PROBE_RESP = 2, | ||
| 141 | WMI_FRAME_ASSOC_REQ = 3, | ||
| 142 | WMI_FRAME_ASSOC_RESP = 4, | ||
| 143 | WMI_NUM_MGMT_FRAME, | ||
| 144 | }; | ||
| 145 | |||
| 146 | /* | ||
| 147 | * WMI_CONNECT_CMDID | ||
| 148 | */ | ||
| 149 | enum wmi_network_type { | ||
| 150 | WMI_NETTYPE_INFRA = 0x01, | ||
| 151 | WMI_NETTYPE_ADHOC = 0x02, | ||
| 152 | WMI_NETTYPE_ADHOC_CREATOR = 0x04, | ||
| 153 | WMI_NETTYPE_AP = 0x10, | ||
| 154 | WMI_NETTYPE_P2P = 0x20, | ||
| 155 | WMI_NETTYPE_WBE = 0x40, /* PCIE over 60g */ | ||
| 156 | }; | ||
| 157 | |||
| 158 | enum wmi_dot11_auth_mode { | ||
| 159 | WMI_AUTH11_OPEN = 0x01, | ||
| 160 | WMI_AUTH11_SHARED = 0x02, | ||
| 161 | WMI_AUTH11_LEAP = 0x04, | ||
| 162 | WMI_AUTH11_WSC = 0x08, | ||
| 163 | }; | ||
| 164 | |||
| 165 | enum wmi_auth_mode { | ||
| 166 | WMI_AUTH_NONE = 0x01, | ||
| 167 | WMI_AUTH_WPA = 0x02, | ||
| 168 | WMI_AUTH_WPA2 = 0x04, | ||
| 169 | WMI_AUTH_WPA_PSK = 0x08, | ||
| 170 | WMI_AUTH_WPA2_PSK = 0x10, | ||
| 171 | WMI_AUTH_WPA_CCKM = 0x20, | ||
| 172 | WMI_AUTH_WPA2_CCKM = 0x40, | ||
| 173 | }; | ||
| 174 | |||
| 175 | enum wmi_crypto_type { | ||
| 176 | WMI_CRYPT_NONE = 0x01, | ||
| 177 | WMI_CRYPT_WEP = 0x02, | ||
| 178 | WMI_CRYPT_TKIP = 0x04, | ||
| 179 | WMI_CRYPT_AES = 0x08, | ||
| 180 | WMI_CRYPT_AES_GCMP = 0x20, | ||
| 181 | }; | ||
| 182 | |||
| 183 | |||
| 184 | enum wmi_connect_ctrl_flag_bits { | ||
| 185 | WMI_CONNECT_ASSOC_POLICY_USER = 0x0001, | ||
| 186 | WMI_CONNECT_SEND_REASSOC = 0x0002, | ||
| 187 | WMI_CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, | ||
| 188 | WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008, | ||
| 189 | WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010, | ||
| 190 | WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020, | ||
| 191 | WMI_CONNECT_DO_WPA_OFFLOAD = 0x0040, | ||
| 192 | WMI_CONNECT_DO_NOT_DEAUTH = 0x0080, | ||
| 193 | }; | ||
| 194 | |||
| 195 | #define WMI_MAX_SSID_LEN (32) | ||
| 196 | |||
| 197 | struct wmi_connect_cmd { | ||
| 198 | u8 network_type; | ||
| 199 | u8 dot11_auth_mode; | ||
| 200 | u8 auth_mode; | ||
| 201 | u8 pairwise_crypto_type; | ||
| 202 | u8 pairwise_crypto_len; | ||
| 203 | u8 group_crypto_type; | ||
| 204 | u8 group_crypto_len; | ||
| 205 | u8 ssid_len; | ||
| 206 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
| 207 | u8 channel; | ||
| 208 | u8 reserved0; | ||
| 209 | u8 bssid[WMI_MAC_LEN]; | ||
| 210 | __le32 ctrl_flags; | ||
| 211 | u8 dst_mac[WMI_MAC_LEN]; | ||
| 212 | u8 reserved1[2]; | ||
| 213 | } __packed; | ||
| 214 | |||
| 215 | |||
| 216 | /* | ||
| 217 | * WMI_RECONNECT_CMDID | ||
| 218 | */ | ||
| 219 | struct wmi_reconnect_cmd { | ||
| 220 | u8 channel; /* hint */ | ||
| 221 | u8 reserved; | ||
| 222 | u8 bssid[WMI_MAC_LEN]; /* mandatory if set */ | ||
| 223 | } __packed; | ||
| 224 | |||
| 225 | |||
| 226 | /* | ||
| 227 | * WMI_SET_PMK_CMDID | ||
| 228 | */ | ||
| 229 | |||
| 230 | #define WMI_MIN_KEY_INDEX (0) | ||
| 231 | #define WMI_MAX_KEY_INDEX (3) | ||
| 232 | #define WMI_MAX_KEY_LEN (32) | ||
| 233 | #define WMI_PASSPHRASE_LEN (64) | ||
| 234 | #define WMI_PMK_LEN (32) | ||
| 235 | |||
| 236 | struct wmi_set_pmk_cmd { | ||
| 237 | u8 pmk[WMI_PMK_LEN]; | ||
| 238 | } __packed; | ||
| 239 | |||
| 240 | |||
| 241 | /* | ||
| 242 | * WMI_SET_PASSPHRASE_CMDID | ||
| 243 | */ | ||
| 244 | struct wmi_set_passphrase_cmd { | ||
| 245 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
| 246 | u8 passphrase[WMI_PASSPHRASE_LEN]; | ||
| 247 | u8 ssid_len; | ||
| 248 | u8 passphrase_len; | ||
| 249 | } __packed; | ||
| 250 | |||
| 251 | /* | ||
| 252 | * WMI_ADD_CIPHER_KEY_CMDID | ||
| 253 | */ | ||
| 254 | enum wmi_key_usage { | ||
| 255 | WMI_KEY_USE_PAIRWISE = 0, | ||
| 256 | WMI_KEY_USE_GROUP = 1, | ||
| 257 | WMI_KEY_USE_TX = 2, /* default Tx Key - Static WEP only */ | ||
| 258 | }; | ||
| 259 | |||
| 260 | struct wmi_add_cipher_key_cmd { | ||
| 261 | u8 key_index; | ||
| 262 | u8 key_type; | ||
| 263 | u8 key_usage; /* enum wmi_key_usage */ | ||
| 264 | u8 key_len; | ||
| 265 | u8 key_rsc[8]; /* key replay sequence counter */ | ||
| 266 | u8 key[WMI_MAX_KEY_LEN]; | ||
| 267 | u8 key_op_ctrl; /* Additional Key Control information */ | ||
| 268 | u8 mac[WMI_MAC_LEN]; | ||
| 269 | } __packed; | ||
| 270 | |||
| 271 | /* | ||
| 272 | * WMI_DELETE_CIPHER_KEY_CMDID | ||
| 273 | */ | ||
| 274 | struct wmi_delete_cipher_key_cmd { | ||
| 275 | u8 key_index; | ||
| 276 | u8 mac[WMI_MAC_LEN]; | ||
| 277 | } __packed; | ||
| 278 | |||
| 279 | |||
| 280 | /* | ||
| 281 | * WMI_START_SCAN_CMDID | ||
| 282 | * | ||
| 283 | * Start L1 scan operation | ||
| 284 | * | ||
| 285 | * Returned events: | ||
| 286 | * - WMI_RX_MGMT_PACKET_EVENTID - for every probe resp. | ||
| 287 | * - WMI_SCAN_COMPLETE_EVENTID | ||
| 288 | */ | ||
| 289 | enum wmi_scan_type { | ||
| 290 | WMI_LONG_SCAN = 0, | ||
| 291 | WMI_SHORT_SCAN = 1, | ||
| 292 | }; | ||
| 293 | |||
| 294 | struct wmi_start_scan_cmd { | ||
| 295 | u8 reserved[8]; | ||
| 296 | __le32 home_dwell_time; /* Max duration in the home channel(ms) */ | ||
| 297 | __le32 force_scan_interval; /* Time interval between scans (ms)*/ | ||
| 298 | u8 scan_type; /* wmi_scan_type */ | ||
| 299 | u8 num_channels; /* how many channels follow */ | ||
| 300 | struct { | ||
| 301 | u8 channel; | ||
| 302 | u8 reserved; | ||
| 303 | } channel_list[0]; /* channels ID's */ | ||
| 304 | /* 0 - 58320 MHz */ | ||
| 305 | /* 1 - 60480 MHz */ | ||
| 306 | /* 2 - 62640 MHz */ | ||
| 307 | } __packed; | ||
| 308 | |||
| 309 | /* | ||
| 310 | * WMI_SET_PROBED_SSID_CMDID | ||
| 311 | */ | ||
| 312 | #define MAX_PROBED_SSID_INDEX (15) | ||
| 313 | |||
| 314 | enum wmi_ssid_flag { | ||
| 315 | WMI_SSID_FLAG_DISABLE = 0, /* disables entry */ | ||
| 316 | WMI_SSID_FLAG_SPECIFIC = 1, /* probes specified ssid */ | ||
| 317 | WMI_SSID_FLAG_ANY = 2, /* probes for any ssid */ | ||
| 318 | }; | ||
| 319 | |||
| 320 | struct wmi_probed_ssid_cmd { | ||
| 321 | u8 entry_index; /* 0 to MAX_PROBED_SSID_INDEX */ | ||
| 322 | u8 flag; /* enum wmi_ssid_flag */ | ||
| 323 | u8 ssid_len; | ||
| 324 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
| 325 | } __packed; | ||
| 326 | |||
| 327 | /* | ||
| 328 | * WMI_SET_APPIE_CMDID | ||
| 329 | * Add Application specified IE to a management frame | ||
| 330 | */ | ||
| 331 | struct wmi_set_appie_cmd { | ||
| 332 | u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ | ||
| 333 | u8 reserved; | ||
| 334 | __le16 ie_len; /* Length of the IE to be added to MGMT frame */ | ||
| 335 | u8 ie_info[0]; | ||
| 336 | } __packed; | ||
| 337 | |||
| 338 | #define WMI_MAX_IE_LEN (1024) | ||
| 339 | |||
| 340 | struct wmi_pxmt_range_cfg_cmd { | ||
| 341 | u8 dst_mac[WMI_MAC_LEN]; | ||
| 342 | __le16 range; | ||
| 343 | } __packed; | ||
| 344 | |||
| 345 | struct wmi_pxmt_snr2_range_cfg_cmd { | ||
| 346 | s8 snr2range_arr[WMI_PROX_RANGE_NUM-1]; | ||
| 347 | } __packed; | ||
| 348 | |||
| 349 | /* | ||
| 350 | * WMI_RF_MGMT_CMDID | ||
| 351 | */ | ||
| 352 | enum wmi_rf_mgmt_type { | ||
| 353 | WMI_RF_MGMT_W_DISABLE = 0, | ||
| 354 | WMI_RF_MGMT_W_ENABLE = 1, | ||
| 355 | WMI_RF_MGMT_GET_STATUS = 2, | ||
| 356 | }; | ||
| 357 | |||
| 358 | struct wmi_rf_mgmt_cmd { | ||
| 359 | __le32 rf_mgmt_type; | ||
| 360 | } __packed; | ||
| 361 | |||
| 362 | /* | ||
| 363 | * WMI_SET_SSID_CMDID | ||
| 364 | */ | ||
| 365 | struct wmi_set_ssid_cmd { | ||
| 366 | __le32 ssid_len; | ||
| 367 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
| 368 | } __packed; | ||
| 369 | |||
| 370 | /* | ||
| 371 | * WMI_SET_PCP_CHANNEL_CMDID | ||
| 372 | */ | ||
| 373 | struct wmi_set_pcp_channel_cmd { | ||
| 374 | u8 channel; | ||
| 375 | u8 reserved[3]; | ||
| 376 | } __packed; | ||
| 377 | |||
| 378 | /* | ||
| 379 | * WMI_BCON_CTRL_CMDID | ||
| 380 | */ | ||
| 381 | struct wmi_bcon_ctrl_cmd { | ||
| 382 | __le16 bcon_interval; | ||
| 383 | __le16 frag_num; | ||
| 384 | __le64 ss_mask; | ||
| 385 | u8 network_type; | ||
| 386 | u8 reserved; | ||
| 387 | u8 disable_sec_offload; | ||
| 388 | u8 disable_sec; | ||
| 389 | } __packed; | ||
| 390 | |||
| 391 | /* | ||
| 392 | * WMI_SW_TX_REQ_CMDID | ||
| 393 | */ | ||
| 394 | struct wmi_sw_tx_req_cmd { | ||
| 395 | u8 dst_mac[WMI_MAC_LEN]; | ||
| 396 | __le16 len; | ||
| 397 | u8 payload[0]; | ||
| 398 | } __packed; | ||
| 399 | |||
| 400 | /* | ||
| 401 | * WMI_VRING_CFG_CMDID | ||
| 402 | */ | ||
| 403 | |||
| 404 | struct wmi_sw_ring_cfg { | ||
| 405 | __le64 ring_mem_base; | ||
| 406 | __le16 ring_size; | ||
| 407 | __le16 max_mpdu_size; | ||
| 408 | } __packed; | ||
| 409 | |||
| 410 | struct wmi_vring_cfg_schd { | ||
| 411 | __le16 priority; | ||
| 412 | __le16 timeslot_us; | ||
| 413 | } __packed; | ||
| 414 | |||
| 415 | enum wmi_vring_cfg_encap_trans_type { | ||
| 416 | WMI_VRING_ENC_TYPE_802_3 = 0, | ||
| 417 | WMI_VRING_ENC_TYPE_NATIVE_WIFI = 1, | ||
| 418 | }; | ||
| 419 | |||
| 420 | enum wmi_vring_cfg_ds_cfg { | ||
| 421 | WMI_VRING_DS_PBSS = 0, | ||
| 422 | WMI_VRING_DS_STATION = 1, | ||
| 423 | WMI_VRING_DS_AP = 2, | ||
| 424 | WMI_VRING_DS_ADDR4 = 3, | ||
| 425 | }; | ||
| 426 | |||
| 427 | enum wmi_vring_cfg_nwifi_ds_trans_type { | ||
| 428 | WMI_NWIFI_TX_TRANS_MODE_NO = 0, | ||
| 429 | WMI_NWIFI_TX_TRANS_MODE_AP2PBSS = 1, | ||
| 430 | WMI_NWIFI_TX_TRANS_MODE_STA2PBSS = 2, | ||
| 431 | }; | ||
| 432 | |||
| 433 | enum wmi_vring_cfg_schd_params_priority { | ||
| 434 | WMI_SCH_PRIO_REGULAR = 0, | ||
| 435 | WMI_SCH_PRIO_HIGH = 1, | ||
| 436 | }; | ||
| 437 | |||
| 438 | struct wmi_vring_cfg { | ||
| 439 | struct wmi_sw_ring_cfg tx_sw_ring; | ||
| 440 | u8 ringid; /* 0-23 vrings */ | ||
| 441 | |||
| 442 | #define CIDXTID_CID_POS (0) | ||
| 443 | #define CIDXTID_CID_LEN (4) | ||
| 444 | #define CIDXTID_CID_MSK (0xF) | ||
| 445 | #define CIDXTID_TID_POS (4) | ||
| 446 | #define CIDXTID_TID_LEN (4) | ||
| 447 | #define CIDXTID_TID_MSK (0xF0) | ||
| 448 | u8 cidxtid; | ||
| 449 | |||
| 450 | u8 encap_trans_type; | ||
| 451 | u8 ds_cfg; /* 802.3 DS cfg */ | ||
| 452 | u8 nwifi_ds_trans_type; | ||
| 453 | |||
| 454 | #define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0) | ||
| 455 | #define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1) | ||
| 456 | #define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1) | ||
| 457 | #define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1) | ||
| 458 | #define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1) | ||
| 459 | #define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2) | ||
| 460 | u8 mac_ctrl; | ||
| 461 | |||
| 462 | #define VRING_CFG_TO_RESOLUTION_VALUE_POS (0) | ||
| 463 | #define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6) | ||
| 464 | #define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F) | ||
| 465 | u8 to_resolution; | ||
| 466 | u8 agg_max_wsize; | ||
| 467 | struct wmi_vring_cfg_schd schd_params; | ||
| 468 | } __packed; | ||
| 469 | |||
| 470 | enum wmi_vring_cfg_cmd_action { | ||
| 471 | WMI_VRING_CMD_ADD = 0, | ||
| 472 | WMI_VRING_CMD_MODIFY = 1, | ||
| 473 | WMI_VRING_CMD_DELETE = 2, | ||
| 474 | }; | ||
| 475 | |||
| 476 | struct wmi_vring_cfg_cmd { | ||
| 477 | __le32 action; | ||
| 478 | struct wmi_vring_cfg vring_cfg; | ||
| 479 | } __packed; | ||
| 480 | |||
| 481 | /* | ||
| 482 | * WMI_VRING_BA_EN_CMDID | ||
| 483 | */ | ||
| 484 | struct wmi_vring_ba_en_cmd { | ||
| 485 | u8 ringid; | ||
| 486 | u8 agg_max_wsize; | ||
| 487 | __le16 ba_timeout; | ||
| 488 | } __packed; | ||
| 489 | |||
| 490 | /* | ||
| 491 | * WMI_VRING_BA_DIS_CMDID | ||
| 492 | */ | ||
| 493 | struct wmi_vring_ba_dis_cmd { | ||
| 494 | u8 ringid; | ||
| 495 | u8 reserved; | ||
| 496 | __le16 reason; | ||
| 497 | } __packed; | ||
| 498 | |||
| 499 | /* | ||
| 500 | * WMI_NOTIFY_REQ_CMDID | ||
| 501 | */ | ||
| 502 | struct wmi_notify_req_cmd { | ||
| 503 | u8 cid; | ||
| 504 | u8 reserved[3]; | ||
| 505 | __le32 interval_usec; | ||
| 506 | } __packed; | ||
| 507 | |||
| 508 | /* | ||
| 509 | * WMI_CFG_RX_CHAIN_CMDID | ||
| 510 | */ | ||
| 511 | enum wmi_sniffer_cfg_mode { | ||
| 512 | WMI_SNIFFER_OFF = 0, | ||
| 513 | WMI_SNIFFER_ON = 1, | ||
| 514 | }; | ||
| 515 | |||
| 516 | enum wmi_sniffer_cfg_phy_info_mode { | ||
| 517 | WMI_SNIFFER_PHY_INFO_DISABLED = 0, | ||
| 518 | WMI_SNIFFER_PHY_INFO_ENABLED = 1, | ||
| 519 | }; | ||
| 520 | |||
| 521 | enum wmi_sniffer_cfg_phy_support { | ||
| 522 | WMI_SNIFFER_CP = 0, | ||
| 523 | WMI_SNIFFER_DP = 1, | ||
| 524 | WMI_SNIFFER_BOTH_PHYS = 2, | ||
| 525 | }; | ||
| 526 | |||
| 527 | struct wmi_sniffer_cfg { | ||
| 528 | __le32 mode; /* enum wmi_sniffer_cfg_mode */ | ||
| 529 | __le32 phy_info_mode; /* enum wmi_sniffer_cfg_phy_info_mode */ | ||
| 530 | __le32 phy_support; /* enum wmi_sniffer_cfg_phy_support */ | ||
| 531 | u8 channel; | ||
| 532 | u8 reserved[3]; | ||
| 533 | } __packed; | ||
| 534 | |||
| 535 | enum wmi_cfg_rx_chain_cmd_action { | ||
| 536 | WMI_RX_CHAIN_ADD = 0, | ||
| 537 | WMI_RX_CHAIN_DEL = 1, | ||
| 538 | }; | ||
| 539 | |||
| 540 | enum wmi_cfg_rx_chain_cmd_decap_trans_type { | ||
| 541 | WMI_DECAP_TYPE_802_3 = 0, | ||
| 542 | WMI_DECAP_TYPE_NATIVE_WIFI = 1, | ||
| 543 | }; | ||
| 544 | |||
| 545 | enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { | ||
| 546 | WMI_NWIFI_RX_TRANS_MODE_NO = 0, | ||
| 547 | WMI_NWIFI_RX_TRANS_MODE_PBSS2AP = 1, | ||
| 548 | WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2, | ||
| 549 | }; | ||
| 550 | |||
| 551 | struct wmi_cfg_rx_chain_cmd { | ||
| 552 | __le32 action; | ||
| 553 | struct wmi_sw_ring_cfg rx_sw_ring; | ||
| 554 | u8 mid; | ||
| 555 | u8 decap_trans_type; | ||
| 556 | |||
| 557 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) | ||
| 558 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) | ||
| 559 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) | ||
| 560 | u8 l2_802_3_offload_ctrl; | ||
| 561 | |||
| 562 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) | ||
| 563 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1) | ||
| 564 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1) | ||
| 565 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1) | ||
| 566 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1) | ||
| 567 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2) | ||
| 568 | u8 l2_nwifi_offload_ctrl; | ||
| 569 | |||
| 570 | u8 vlan_id; | ||
| 571 | u8 nwifi_ds_trans_type; | ||
| 572 | |||
| 573 | #define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0) | ||
| 574 | #define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1) | ||
| 575 | #define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1) | ||
| 576 | #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1) | ||
| 577 | #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1) | ||
| 578 | #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2) | ||
| 579 | u8 l3_l4_ctrl; | ||
| 580 | |||
| 581 | #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0) | ||
| 582 | #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1) | ||
| 583 | #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1) | ||
| 584 | #define RING_CTRL_OVERRIDE_WB_THRSH_POS (1) | ||
| 585 | #define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1) | ||
| 586 | #define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2) | ||
| 587 | #define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2) | ||
| 588 | #define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1) | ||
| 589 | #define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4) | ||
| 590 | #define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3) | ||
| 591 | #define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1) | ||
| 592 | #define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8) | ||
| 593 | u8 ring_ctrl; | ||
| 594 | |||
| 595 | __le16 prefetch_thrsh; | ||
| 596 | __le16 wb_thrsh; | ||
| 597 | __le32 itr_value; | ||
| 598 | __le16 host_thrsh; | ||
| 599 | u8 reserved[2]; | ||
| 600 | struct wmi_sniffer_cfg sniffer_cfg; | ||
| 601 | } __packed; | ||
| 602 | |||
| 603 | /* | ||
| 604 | * WMI_RCP_ADDBA_RESP_CMDID | ||
| 605 | */ | ||
| 606 | struct wmi_rcp_addba_resp_cmd { | ||
| 607 | |||
| 608 | #define CIDXTID_CID_POS (0) | ||
| 609 | #define CIDXTID_CID_LEN (4) | ||
| 610 | #define CIDXTID_CID_MSK (0xF) | ||
| 611 | #define CIDXTID_TID_POS (4) | ||
| 612 | #define CIDXTID_TID_LEN (4) | ||
| 613 | #define CIDXTID_TID_MSK (0xF0) | ||
| 614 | u8 cidxtid; | ||
| 615 | |||
| 616 | u8 dialog_token; | ||
| 617 | __le16 status_code; | ||
| 618 | __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */ | ||
| 619 | __le16 ba_timeout; | ||
| 620 | } __packed; | ||
| 621 | |||
| 622 | /* | ||
| 623 | * WMI_RCP_DELBA_CMDID | ||
| 624 | */ | ||
| 625 | struct wmi_rcp_delba_cmd { | ||
| 626 | |||
| 627 | #define CIDXTID_CID_POS (0) | ||
| 628 | #define CIDXTID_CID_LEN (4) | ||
| 629 | #define CIDXTID_CID_MSK (0xF) | ||
| 630 | #define CIDXTID_TID_POS (4) | ||
| 631 | #define CIDXTID_TID_LEN (4) | ||
| 632 | #define CIDXTID_TID_MSK (0xF0) | ||
| 633 | u8 cidxtid; | ||
| 634 | |||
| 635 | u8 reserved; | ||
| 636 | __le16 reason; | ||
| 637 | } __packed; | ||
| 638 | |||
| 639 | /* | ||
| 640 | * WMI_RCP_ADDBA_REQ_CMDID | ||
| 641 | */ | ||
| 642 | struct wmi_rcp_addba_req_cmd { | ||
| 643 | |||
| 644 | #define CIDXTID_CID_POS (0) | ||
| 645 | #define CIDXTID_CID_LEN (4) | ||
| 646 | #define CIDXTID_CID_MSK (0xF) | ||
| 647 | #define CIDXTID_TID_POS (4) | ||
| 648 | #define CIDXTID_TID_LEN (4) | ||
| 649 | #define CIDXTID_TID_MSK (0xF0) | ||
| 650 | u8 cidxtid; | ||
| 651 | |||
| 652 | u8 dialog_token; | ||
| 653 | /* ieee80211_ba_parameterset field as it received */ | ||
| 654 | __le16 ba_param_set; | ||
| 655 | __le16 ba_timeout; | ||
| 656 | /* ieee80211_ba_seqstrl field as it received */ | ||
| 657 | __le16 ba_seq_ctrl; | ||
| 658 | } __packed; | ||
| 659 | |||
| 660 | /* | ||
| 661 | * WMI_SET_MAC_ADDRESS_CMDID | ||
| 662 | */ | ||
| 663 | struct wmi_set_mac_address_cmd { | ||
| 664 | u8 mac[WMI_MAC_LEN]; | ||
| 665 | u8 reserved[2]; | ||
| 666 | } __packed; | ||
| 667 | |||
| 668 | |||
| 669 | /* | ||
| 670 | * WMI_EAPOL_TX_CMDID | ||
| 671 | */ | ||
| 672 | struct wmi_eapol_tx_cmd { | ||
| 673 | u8 dst_mac[WMI_MAC_LEN]; | ||
| 674 | __le16 eapol_len; | ||
| 675 | u8 eapol[0]; | ||
| 676 | } __packed; | ||
| 677 | |||
| 678 | /* | ||
| 679 | * WMI_ECHO_CMDID | ||
| 680 | * | ||
| 681 | * Check FW is alive | ||
| 682 | * | ||
| 683 | * WMI_DEEP_ECHO_CMDID | ||
| 684 | * | ||
| 685 | * Check FW and ucode are alive | ||
| 686 | * | ||
| 687 | * Returned event: WMI_ECHO_RSP_EVENTID | ||
| 688 | * same event for both commands | ||
| 689 | */ | ||
| 690 | struct wmi_echo_cmd { | ||
| 691 | __le32 value; | ||
| 692 | } __packed; | ||
| 693 | |||
| 694 | /* | ||
| 695 | * WMI Events | ||
| 696 | */ | ||
| 697 | |||
| 698 | /* | ||
| 699 | * List of Events (target to host) | ||
| 700 | */ | ||
| 701 | enum wmi_event_id { | ||
| 702 | WMI_IMM_RSP_EVENTID = 0x0000, | ||
| 703 | WMI_READY_EVENTID = 0x1001, | ||
| 704 | WMI_CONNECT_EVENTID = 0x1002, | ||
| 705 | WMI_DISCONNECT_EVENTID = 0x1003, | ||
| 706 | WMI_SCAN_COMPLETE_EVENTID = 0x100a, | ||
| 707 | WMI_REPORT_STATISTICS_EVENTID = 0x100b, | ||
| 708 | WMI_RD_MEM_RSP_EVENTID = 0x1800, | ||
| 709 | WMI_FW_READY_EVENTID = 0x1801, | ||
| 710 | WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200, | ||
| 711 | WMI_ECHO_RSP_EVENTID = 0x1803, | ||
| 712 | WMI_CONFIG_MAC_DONE_EVENTID = 0x1805, | ||
| 713 | WMI_CONFIG_PHY_DEBUG_DONE_EVENTID = 0x1806, | ||
| 714 | WMI_ADD_STATION_DONE_EVENTID = 0x1807, | ||
| 715 | WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID = 0x1808, | ||
| 716 | WMI_PHY_GET_STATISTICS_EVENTID = 0x1809, | ||
| 717 | WMI_FS_TUNE_DONE_EVENTID = 0x180a, | ||
| 718 | WMI_CORR_MEASURE_DONE_EVENTID = 0x180b, | ||
| 719 | WMI_TEMP_SENSE_DONE_EVENTID = 0x180e, | ||
| 720 | WMI_DC_CALIB_DONE_EVENTID = 0x180f, | ||
| 721 | WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, | ||
| 722 | WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812, | ||
| 723 | WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815, | ||
| 724 | WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816, | ||
| 725 | WMI_MARLON_R_ACTIVATE_DONE_EVENTID = 0x1817, | ||
| 726 | WMI_MARLON_R_READ_DONE_EVENTID = 0x1818, | ||
| 727 | WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, | ||
| 728 | WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, | ||
| 729 | WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d, | ||
| 730 | |||
| 731 | WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, | ||
| 732 | WMI_VRING_CFG_DONE_EVENTID = 0x1821, | ||
| 733 | WMI_RX_ON_DONE_EVENTID = 0x1822, | ||
| 734 | WMI_BA_STATUS_EVENTID = 0x1823, | ||
| 735 | WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, | ||
| 736 | WMI_ADDBA_RESP_SENT_EVENTID = 0x1825, | ||
| 737 | WMI_DELBA_EVENTID = 0x1826, | ||
| 738 | WMI_GET_SSID_EVENTID = 0x1828, | ||
| 739 | WMI_GET_PCP_CHANNEL_EVENTID = 0x182a, | ||
| 740 | WMI_SW_TX_COMPLETE_EVENTID = 0x182b, | ||
| 741 | WMI_RX_OFF_DONE_EVENTID = 0x182c, | ||
| 742 | |||
| 743 | WMI_READ_MAC_RXQ_EVENTID = 0x1830, | ||
| 744 | WMI_READ_MAC_TXQ_EVENTID = 0x1831, | ||
| 745 | WMI_WRITE_MAC_RXQ_EVENTID = 0x1832, | ||
| 746 | WMI_WRITE_MAC_TXQ_EVENTID = 0x1833, | ||
| 747 | WMI_WRITE_MAC_XQ_FIELD_EVENTID = 0x1834, | ||
| 748 | |||
| 749 | WMI_BEAFORMING_MGMT_DONE_EVENTID = 0x1836, | ||
| 750 | WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837, | ||
| 751 | WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, | ||
| 752 | WMI_RS_MGMT_DONE_EVENTID = 0x1852, | ||
| 753 | WMI_RF_MGMT_STATUS_EVENTID = 0x1853, | ||
| 754 | WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, | ||
| 755 | WMI_RX_MGMT_PACKET_EVENTID = 0x1840, | ||
| 756 | |||
| 757 | /* Performance monitoring events */ | ||
| 758 | WMI_DATA_PORT_OPEN_EVENTID = 0x1860, | ||
| 759 | WMI_WBE_LINKDOWN_EVENTID = 0x1861, | ||
| 760 | |||
| 761 | WMI_BF_CTRL_DONE_EVENTID = 0x1862, | ||
| 762 | WMI_NOTIFY_REQ_DONE_EVENTID = 0x1863, | ||
| 763 | WMI_GET_STATUS_DONE_EVENTID = 0x1864, | ||
| 764 | |||
| 765 | WMI_UNIT_TEST_EVENTID = 0x1900, | ||
| 766 | WMI_FLASH_READ_DONE_EVENTID = 0x1902, | ||
| 767 | WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, | ||
| 768 | |||
| 769 | WMI_SET_CHANNEL_EVENTID = 0x9000, | ||
| 770 | WMI_ASSOC_REQ_EVENTID = 0x9001, | ||
| 771 | WMI_EAPOL_RX_EVENTID = 0x9002, | ||
| 772 | WMI_MAC_ADDR_RESP_EVENTID = 0x9003, | ||
| 773 | WMI_FW_VER_EVENTID = 0x9004, | ||
| 774 | }; | ||
| 775 | |||
| 776 | /* | ||
| 777 | * Events data structures | ||
| 778 | */ | ||
| 779 | |||
| 780 | /* | ||
| 781 | * WMI_RF_MGMT_STATUS_EVENTID | ||
| 782 | */ | ||
| 783 | enum wmi_rf_status { | ||
| 784 | WMI_RF_ENABLED = 0, | ||
| 785 | WMI_RF_DISABLED_HW = 1, | ||
| 786 | WMI_RF_DISABLED_SW = 2, | ||
| 787 | WMI_RF_DISABLED_HW_SW = 3, | ||
| 788 | }; | ||
| 789 | |||
| 790 | struct wmi_rf_mgmt_status_event { | ||
| 791 | __le32 rf_status; | ||
| 792 | } __packed; | ||
| 793 | |||
| 794 | /* | ||
| 795 | * WMI_GET_STATUS_DONE_EVENTID | ||
| 796 | */ | ||
| 797 | struct wmi_get_status_done_event { | ||
| 798 | __le32 is_associated; | ||
| 799 | u8 cid; | ||
| 800 | u8 reserved0[3]; | ||
| 801 | u8 bssid[WMI_MAC_LEN]; | ||
| 802 | u8 channel; | ||
| 803 | u8 reserved1; | ||
| 804 | u8 network_type; | ||
| 805 | u8 reserved2[3]; | ||
| 806 | __le32 ssid_len; | ||
| 807 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
| 808 | __le32 rf_status; | ||
| 809 | __le32 is_secured; | ||
| 810 | } __packed; | ||
| 811 | |||
| 812 | /* | ||
| 813 | * WMI_FW_VER_EVENTID | ||
| 814 | */ | ||
| 815 | struct wmi_fw_ver_event { | ||
| 816 | u8 major; | ||
| 817 | u8 minor; | ||
| 818 | __le16 subminor; | ||
| 819 | __le16 build; | ||
| 820 | } __packed; | ||
| 821 | |||
| 822 | /* | ||
| 823 | * WMI_MAC_ADDR_RESP_EVENTID | ||
| 824 | */ | ||
| 825 | struct wmi_mac_addr_resp_event { | ||
| 826 | u8 mac[WMI_MAC_LEN]; | ||
| 827 | u8 auth_mode; | ||
| 828 | u8 crypt_mode; | ||
| 829 | __le32 offload_mode; | ||
| 830 | } __packed; | ||
| 831 | |||
| 832 | /* | ||
| 833 | * WMI_EAPOL_RX_EVENTID | ||
| 834 | */ | ||
| 835 | struct wmi_eapol_rx_event { | ||
| 836 | u8 src_mac[WMI_MAC_LEN]; | ||
| 837 | __le16 eapol_len; | ||
| 838 | u8 eapol[0]; | ||
| 839 | } __packed; | ||
| 840 | |||
| 841 | /* | ||
| 842 | * WMI_READY_EVENTID | ||
| 843 | */ | ||
| 844 | enum wmi_phy_capability { | ||
| 845 | WMI_11A_CAPABILITY = 1, | ||
| 846 | WMI_11G_CAPABILITY = 2, | ||
| 847 | WMI_11AG_CAPABILITY = 3, | ||
| 848 | WMI_11NA_CAPABILITY = 4, | ||
| 849 | WMI_11NG_CAPABILITY = 5, | ||
| 850 | WMI_11NAG_CAPABILITY = 6, | ||
| 851 | WMI_11AD_CAPABILITY = 7, | ||
| 852 | WMI_11N_CAPABILITY_OFFSET = WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY, | ||
| 853 | }; | ||
| 854 | |||
| 855 | struct wmi_ready_event { | ||
| 856 | __le32 sw_version; | ||
| 857 | __le32 abi_version; | ||
| 858 | u8 mac[WMI_MAC_LEN]; | ||
| 859 | u8 phy_capability; /* enum wmi_phy_capability */ | ||
| 860 | u8 reserved; | ||
| 861 | } __packed; | ||
| 862 | |||
| 863 | /* | ||
| 864 | * WMI_NOTIFY_REQ_DONE_EVENTID | ||
| 865 | */ | ||
| 866 | struct wmi_notify_req_done_event { | ||
| 867 | __le32 status; | ||
| 868 | __le64 tsf; | ||
| 869 | __le32 snr_val; | ||
| 870 | __le32 tx_tpt; | ||
| 871 | __le32 tx_goodput; | ||
| 872 | __le32 rx_goodput; | ||
| 873 | __le16 bf_mcs; | ||
| 874 | __le16 my_rx_sector; | ||
| 875 | __le16 my_tx_sector; | ||
| 876 | __le16 other_rx_sector; | ||
| 877 | __le16 other_tx_sector; | ||
| 878 | __le16 range; | ||
| 879 | } __packed; | ||
| 880 | |||
| 881 | /* | ||
| 882 | * WMI_CONNECT_EVENTID | ||
| 883 | */ | ||
| 884 | struct wmi_connect_event { | ||
| 885 | u8 channel; | ||
| 886 | u8 reserved0; | ||
| 887 | u8 bssid[WMI_MAC_LEN]; | ||
| 888 | __le16 listen_interval; | ||
| 889 | __le16 beacon_interval; | ||
| 890 | u8 network_type; | ||
| 891 | u8 reserved1[3]; | ||
| 892 | u8 beacon_ie_len; | ||
| 893 | u8 assoc_req_len; | ||
| 894 | u8 assoc_resp_len; | ||
| 895 | u8 cid; | ||
| 896 | u8 reserved2[3]; | ||
| 897 | u8 assoc_info[0]; | ||
| 898 | } __packed; | ||
| 899 | |||
| 900 | /* | ||
| 901 | * WMI_DISCONNECT_EVENTID | ||
| 902 | */ | ||
| 903 | enum wmi_disconnect_reason { | ||
| 904 | WMI_DIS_REASON_NO_NETWORK_AVAIL = 1, | ||
| 905 | WMI_DIS_REASON_LOST_LINK = 2, /* bmiss */ | ||
| 906 | WMI_DIS_REASON_DISCONNECT_CMD = 3, | ||
| 907 | WMI_DIS_REASON_BSS_DISCONNECTED = 4, | ||
| 908 | WMI_DIS_REASON_AUTH_FAILED = 5, | ||
| 909 | WMI_DIS_REASON_ASSOC_FAILED = 6, | ||
| 910 | WMI_DIS_REASON_NO_RESOURCES_AVAIL = 7, | ||
| 911 | WMI_DIS_REASON_CSERV_DISCONNECT = 8, | ||
| 912 | WMI_DIS_REASON_INVALID_PROFILE = 10, | ||
| 913 | WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH = 11, | ||
| 914 | WMI_DIS_REASON_PROFILE_MISMATCH = 12, | ||
| 915 | WMI_DIS_REASON_CONNECTION_EVICTED = 13, | ||
| 916 | WMI_DIS_REASON_IBSS_MERGE = 14, | ||
| 917 | }; | ||
| 918 | |||
| 919 | struct wmi_disconnect_event { | ||
| 920 | __le16 protocol_reason_status; /* reason code, see 802.11 spec. */ | ||
| 921 | u8 bssid[WMI_MAC_LEN]; /* set if known */ | ||
| 922 | u8 disconnect_reason; /* see wmi_disconnect_reason_e */ | ||
| 923 | u8 assoc_resp_len; | ||
| 924 | u8 assoc_info[0]; | ||
| 925 | } __packed; | ||
| 926 | |||
| 927 | /* | ||
| 928 | * WMI_SCAN_COMPLETE_EVENTID | ||
| 929 | */ | ||
| 930 | struct wmi_scan_complete_event { | ||
| 931 | __le32 status; | ||
| 932 | } __packed; | ||
| 933 | |||
| 934 | /* | ||
| 935 | * WMI_BA_STATUS_EVENTID | ||
| 936 | */ | ||
| 937 | enum wmi_vring_ba_status { | ||
| 938 | WMI_BA_AGREED = 0, | ||
| 939 | WMI_BA_NON_AGREED = 1, | ||
| 940 | }; | ||
| 941 | |||
| 942 | struct wmi_vring_ba_status_event { | ||
| 943 | __le16 status; | ||
| 944 | u8 reserved[2]; | ||
| 945 | u8 ringid; | ||
| 946 | u8 agg_wsize; | ||
| 947 | __le16 ba_timeout; | ||
| 948 | } __packed; | ||
| 949 | |||
| 950 | /* | ||
| 951 | * WMI_DELBA_EVENTID | ||
| 952 | */ | ||
| 953 | struct wmi_delba_event { | ||
| 954 | |||
| 955 | #define CIDXTID_CID_POS (0) | ||
| 956 | #define CIDXTID_CID_LEN (4) | ||
| 957 | #define CIDXTID_CID_MSK (0xF) | ||
| 958 | #define CIDXTID_TID_POS (4) | ||
| 959 | #define CIDXTID_TID_LEN (4) | ||
| 960 | #define CIDXTID_TID_MSK (0xF0) | ||
| 961 | u8 cidxtid; | ||
| 962 | |||
| 963 | u8 from_initiator; | ||
| 964 | __le16 reason; | ||
| 965 | } __packed; | ||
| 966 | |||
| 967 | /* | ||
| 968 | * WMI_VRING_CFG_DONE_EVENTID | ||
| 969 | */ | ||
| 970 | enum wmi_vring_cfg_done_event_status { | ||
| 971 | WMI_VRING_CFG_SUCCESS = 0, | ||
| 972 | WMI_VRING_CFG_FAILURE = 1, | ||
| 973 | }; | ||
| 974 | |||
| 975 | struct wmi_vring_cfg_done_event { | ||
| 976 | u8 ringid; | ||
| 977 | u8 status; | ||
| 978 | u8 reserved[2]; | ||
| 979 | __le32 tx_vring_tail_ptr; | ||
| 980 | } __packed; | ||
| 981 | |||
| 982 | /* | ||
| 983 | * WMI_ADDBA_RESP_SENT_EVENTID | ||
| 984 | */ | ||
| 985 | enum wmi_rcp_addba_resp_sent_event_status { | ||
| 986 | WMI_ADDBA_SUCCESS = 0, | ||
| 987 | WMI_ADDBA_FAIL = 1, | ||
| 988 | }; | ||
| 989 | |||
| 990 | struct wmi_rcp_addba_resp_sent_event { | ||
| 991 | |||
| 992 | #define CIDXTID_CID_POS (0) | ||
| 993 | #define CIDXTID_CID_LEN (4) | ||
| 994 | #define CIDXTID_CID_MSK (0xF) | ||
| 995 | #define CIDXTID_TID_POS (4) | ||
| 996 | #define CIDXTID_TID_LEN (4) | ||
| 997 | #define CIDXTID_TID_MSK (0xF0) | ||
| 998 | u8 cidxtid; | ||
| 999 | |||
| 1000 | u8 reserved; | ||
| 1001 | __le16 status; | ||
| 1002 | } __packed; | ||
| 1003 | |||
| 1004 | /* | ||
| 1005 | * WMI_RCP_ADDBA_REQ_EVENTID | ||
| 1006 | */ | ||
| 1007 | struct wmi_rcp_addba_req_event { | ||
| 1008 | |||
| 1009 | #define CIDXTID_CID_POS (0) | ||
| 1010 | #define CIDXTID_CID_LEN (4) | ||
| 1011 | #define CIDXTID_CID_MSK (0xF) | ||
| 1012 | #define CIDXTID_TID_POS (4) | ||
| 1013 | #define CIDXTID_TID_LEN (4) | ||
| 1014 | #define CIDXTID_TID_MSK (0xF0) | ||
| 1015 | u8 cidxtid; | ||
| 1016 | |||
| 1017 | u8 dialog_token; | ||
| 1018 | __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */ | ||
| 1019 | __le16 ba_timeout; | ||
| 1020 | __le16 ba_seq_ctrl; /* ieee80211_ba_seqstrl field as it received */ | ||
| 1021 | } __packed; | ||
| 1022 | |||
| 1023 | /* | ||
| 1024 | * WMI_CFG_RX_CHAIN_DONE_EVENTID | ||
| 1025 | */ | ||
| 1026 | enum wmi_cfg_rx_chain_done_event_status { | ||
| 1027 | WMI_CFG_RX_CHAIN_SUCCESS = 1, | ||
| 1028 | }; | ||
| 1029 | |||
| 1030 | struct wmi_cfg_rx_chain_done_event { | ||
| 1031 | __le32 rx_ring_tail_ptr; /* Rx V-Ring Tail pointer */ | ||
| 1032 | __le32 status; | ||
| 1033 | } __packed; | ||
| 1034 | |||
| 1035 | /* | ||
| 1036 | * WMI_WBE_LINKDOWN_EVENTID | ||
| 1037 | */ | ||
| 1038 | enum wmi_wbe_link_down_event_reason { | ||
| 1039 | WMI_WBE_REASON_USER_REQUEST = 0, | ||
| 1040 | WMI_WBE_REASON_RX_DISASSOC = 1, | ||
| 1041 | WMI_WBE_REASON_BAD_PHY_LINK = 2, | ||
| 1042 | }; | ||
| 1043 | |||
| 1044 | struct wmi_wbe_link_down_event { | ||
| 1045 | u8 cid; | ||
| 1046 | u8 reserved[3]; | ||
| 1047 | __le32 reason; | ||
| 1048 | } __packed; | ||
| 1049 | |||
| 1050 | /* | ||
| 1051 | * WMI_DATA_PORT_OPEN_EVENTID | ||
| 1052 | */ | ||
| 1053 | struct wmi_data_port_open_event { | ||
| 1054 | u8 cid; | ||
| 1055 | u8 reserved[3]; | ||
| 1056 | } __packed; | ||
| 1057 | |||
| 1058 | /* | ||
| 1059 | * WMI_GET_PCP_CHANNEL_EVENTID | ||
| 1060 | */ | ||
| 1061 | struct wmi_get_pcp_channel_event { | ||
| 1062 | u8 channel; | ||
| 1063 | u8 reserved[3]; | ||
| 1064 | } __packed; | ||
| 1065 | |||
| 1066 | /* | ||
| 1067 | * WMI_SW_TX_COMPLETE_EVENTID | ||
| 1068 | */ | ||
| 1069 | enum wmi_sw_tx_status { | ||
| 1070 | WMI_TX_SW_STATUS_SUCCESS = 0, | ||
| 1071 | WMI_TX_SW_STATUS_FAILED_NO_RESOURCES = 1, | ||
| 1072 | WMI_TX_SW_STATUS_FAILED_TX = 2, | ||
| 1073 | }; | ||
| 1074 | |||
| 1075 | struct wmi_sw_tx_complete_event { | ||
| 1076 | u8 status; /* enum wmi_sw_tx_status */ | ||
| 1077 | u8 reserved[3]; | ||
| 1078 | } __packed; | ||
| 1079 | |||
| 1080 | /* | ||
| 1081 | * WMI_GET_SSID_EVENTID | ||
| 1082 | */ | ||
| 1083 | struct wmi_get_ssid_event { | ||
| 1084 | __le32 ssid_len; | ||
| 1085 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
| 1086 | } __packed; | ||
| 1087 | |||
| 1088 | /* | ||
| 1089 | * WMI_RX_MGMT_PACKET_EVENTID | ||
| 1090 | */ | ||
| 1091 | struct wmi_rx_mgmt_info { | ||
| 1092 | u8 mcs; | ||
| 1093 | s8 snr; | ||
| 1094 | __le16 range; | ||
| 1095 | __le16 stype; | ||
| 1096 | __le16 status; | ||
| 1097 | __le32 len; | ||
| 1098 | u8 qid; | ||
| 1099 | u8 mid; | ||
| 1100 | u8 cid; | ||
| 1101 | u8 channel; /* From Radio MNGR */ | ||
| 1102 | } __packed; | ||
| 1103 | |||
| 1104 | struct wmi_rx_mgmt_packet_event { | ||
| 1105 | struct wmi_rx_mgmt_info info; | ||
| 1106 | u8 payload[0]; | ||
| 1107 | } __packed; | ||
| 1108 | |||
| 1109 | /* | ||
| 1110 | * WMI_ECHO_RSP_EVENTID | ||
| 1111 | */ | ||
| 1112 | struct wmi_echo_event { | ||
| 1113 | __le32 echoed_value; | ||
| 1114 | } __packed; | ||
| 1115 | |||
| 1116 | #endif /* __WILOCITY_WMI_H__ */ | ||
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/hw_random.h> | 7 | #include <linux/hw_random.h> |
| 8 | #include <linux/bcma/bcma.h> | 8 | #include <linux/bcma/bcma.h> |
| 9 | #include <linux/ssb/ssb.h> | 9 | #include <linux/ssb/ssb.h> |
| 10 | #include <linux/completion.h> | ||
| 10 | #include <net/mac80211.h> | 11 | #include <net/mac80211.h> |
| 11 | 12 | ||
| 12 | #include "debugfs.h" | 13 | #include "debugfs.h" |
| @@ -722,6 +723,10 @@ enum b43_firmware_file_type { · 709 unmodified lines | |||
| 722 | struct b43_request_fw_context { | 723 | struct b43_request_fw_context { |
| 723 | /* The device we are requesting the fw for. */ | 724 | /* The device we are requesting the fw for. */ |
| 724 | struct b43_wldev *dev; | 725 | struct b43_wldev *dev; |
| 726 | /* a completion event structure needed if this call is asynchronous */ | ||
| 727 | struct completion fw_load_complete; | ||
| 728 | /* a pointer to the firmware object */ | ||
| 729 | const struct firmware *blob; | ||
| 725 | /* The type of firmware to request. */ | 730 | /* The type of firmware to request. */ |
| 726 | enum b43_firmware_file_type req_type; | 731 | enum b43_firmware_file_type req_type; |
| 727 | /* Error messages for each firmware type. */ | 732 | /* Error messages for each firmware type. */ |
| @@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) · 2087 unmodified lines | |||
| 2088 | b43warn(wl, text); | 2088 | b43warn(wl, text); |
| 2089 | } | 2089 | } |
| 2090 | 2090 | ||
| 2091 | static void b43_fw_cb(const struct firmware *firmware, void *context) | ||
| 2092 | { | ||
| 2093 | struct b43_request_fw_context *ctx = context; | ||
| 2094 | |||
| 2095 | ctx->blob = firmware; | ||
| 2096 | complete(&ctx->fw_load_complete); | ||
| 2097 | } | ||
| 2098 | |||
| 2091 | int b43_do_request_fw(struct b43_request_fw_context *ctx, | 2099 | int b43_do_request_fw(struct b43_request_fw_context *ctx, |
| 2092 | const char *name, | 2100 | const char *name, |
| 2093 | struct b43_firmware_file *fw) | 2101 | struct b43_firmware_file *fw, bool async) |
| 2094 | { | 2102 | { |
| 2095 | const struct firmware *blob; | ||
| 2096 | struct b43_fw_header *hdr; | 2103 | struct b43_fw_header *hdr; |
| 2097 | u32 size; | 2104 | u32 size; |
| 2098 | int err; | 2105 | int err; |
| @@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, · 32 unmodified lines | |||
| 2131 | B43_WARN_ON(1); | 2138 | B43_WARN_ON(1); |
| 2132 | return -ENOSYS; | 2139 | return -ENOSYS; |
| 2133 | } | 2140 | } |
| 2134 | err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); | 2141 | if (async) { |
| 2142 | /* do this part asynchronously */ | ||
| 2143 | init_completion(&ctx->fw_load_complete); | ||
| 2144 | err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, | ||
| 2145 | ctx->dev->dev->dev, GFP_KERNEL, | ||
| 2146 | ctx, b43_fw_cb); | ||
| 2147 | if (err < 0) { | ||
| 2148 | pr_err("Unable to load firmware\n"); | ||
| 2149 | return err; | ||
| 2150 | } | ||
| 2151 | /* stall here until fw ready */ | ||
| 2152 | wait_for_completion(&ctx->fw_load_complete); | ||
| 2153 | if (ctx->blob) | ||
| 2154 | goto fw_ready; | ||
| 2155 | /* On some ARM systems, the async request will fail, but the next sync | ||
| 2156 | * request works. For this reason, we dall through here | ||
| 2157 | */ | ||
| 2158 | } | ||
| 2159 | err = request_firmware(&ctx->blob, ctx->fwname, | ||
| 2160 | ctx->dev->dev->dev); | ||
| 2135 | if (err == -ENOENT) { | 2161 | if (err == -ENOENT) { |
| 2136 | snprintf(ctx->errors[ctx->req_type], | 2162 | snprintf(ctx->errors[ctx->req_type], |
| 2137 | sizeof(ctx->errors[ctx->req_type]), | 2163 | sizeof(ctx->errors[ctx->req_type]), |
| 2138 | "Firmware file \"%s\" not found\n", ctx->fwname); | 2164 | "Firmware file \"%s\" not found\n", |
| 2165 | ctx->fwname); | ||
| 2139 | return err; | 2166 | return err; |
| 2140 | } else if (err) { | 2167 | } else if (err) { |
| 2141 | snprintf(ctx->errors[ctx->req_type], | 2168 | snprintf(ctx->errors[ctx->req_type], |
| @@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, · 2 unmodified lines | |||
| 2144 | ctx->fwname, err); | 2171 | ctx->fwname, err); |
| 2145 | return err; | 2172 | return err; |
| 2146 | } | 2173 | } |
| 2147 | if (blob->size < sizeof(struct b43_fw_header)) | 2174 | fw_ready: |
| 2175 | if (ctx->blob->size < sizeof(struct b43_fw_header)) | ||
| 2148 | goto err_format; | 2176 | goto err_format; |
| 2149 | hdr = (struct b43_fw_header *)(blob->data); | 2177 | hdr = (struct b43_fw_header *)(ctx->blob->data); |
| 2150 | switch (hdr->type) { | 2178 | switch (hdr->type) { |
| 2151 | case B43_FW_TYPE_UCODE: | 2179 | case B43_FW_TYPE_UCODE: |
| 2152 | case B43_FW_TYPE_PCM: | 2180 | case B43_FW_TYPE_PCM: |
| 2153 | size = be32_to_cpu(hdr->size); | 2181 | size = be32_to_cpu(hdr->size); |
| 2154 | if (size != blob->size - sizeof(struct b43_fw_header)) | 2182 | if (size != ctx->blob->size - sizeof(struct b43_fw_header)) |
| 2155 | goto err_format; | 2183 | goto err_format; |
| 2156 | /* fallthrough */ | 2184 | /* fallthrough */ |
| 2157 | case B43_FW_TYPE_IV: | 2185 | case B43_FW_TYPE_IV: |
| @@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, · 4 unmodified lines | |||
| 2162 | goto err_format; | 2190 | goto err_format; |
| 2163 | } | 2191 | } |
| 2164 | 2192 | ||
| 2165 | fw->data = blob; | 2193 | fw->data = ctx->blob; |
| 2166 | fw->filename = name; | 2194 | fw->filename = name; |
| 2167 | fw->type = ctx->req_type; | 2195 | fw->type = ctx->req_type; |
| 2168 | 2196 | ||
| @@ -2172,7 +2200,7 @@ err_format: · 3 unmodified lines | |||
| 2172 | snprintf(ctx->errors[ctx->req_type], | 2200 | snprintf(ctx->errors[ctx->req_type], |
| 2173 | sizeof(ctx->errors[ctx->req_type]), | 2201 | sizeof(ctx->errors[ctx->req_type]), |
| 2174 | "Firmware file \"%s\" format error.\n", ctx->fwname); | 2202 | "Firmware file \"%s\" format error.\n", ctx->fwname); |
| 2175 | release_firmware(blob); | 2203 | release_firmware(ctx->blob); |
| 2176 | 2204 | ||
| 2177 | return -EPROTO; | 2205 | return -EPROTO; |
| 2178 | } | 2206 | } |
| @@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) · 44 unmodified lines | |||
| 2223 | goto err_no_ucode; | 2251 | goto err_no_ucode; |
| 2224 | } | 2252 | } |
| 2225 | } | 2253 | } |
| 2226 | err = b43_do_request_fw(ctx, filename, &fw->ucode); | 2254 | err = b43_do_request_fw(ctx, filename, &fw->ucode, true); |
| 2227 | if (err) | 2255 | if (err) |
| 2228 | goto err_load; | 2256 | goto err_load; |
| 2229 | 2257 | ||
| @@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) · 5 unmodified lines | |||
| 2235 | else | 2263 | else |
| 2236 | goto err_no_pcm; | 2264 | goto err_no_pcm; |
| 2237 | fw->pcm_request_failed = false; | 2265 | fw->pcm_request_failed = false; |
| 2238 | err = b43_do_request_fw(ctx, filename, &fw->pcm); | 2266 | err = b43_do_request_fw(ctx, filename, &fw->pcm, false); |
| 2239 | if (err == -ENOENT) { | 2267 | if (err == -ENOENT) { |
| 2240 | /* We did not find a PCM file? Not fatal, but | 2268 | /* We did not find a PCM file? Not fatal, but |
| 2241 | * core rev <= 10 must do without hwcrypto then. */ | 2269 | * core rev <= 10 must do without hwcrypto then. */ |
| @@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) · 54 unmodified lines | |||
| 2296 | default: | 2324 | default: |
| 2297 | goto err_no_initvals; | 2325 | goto err_no_initvals; |
| 2298 | } | 2326 | } |
| 2299 | err = b43_do_request_fw(ctx, filename, &fw->initvals); | 2327 | err = b43_do_request_fw(ctx, filename, &fw->initvals, false); |
| 2300 | if (err) | 2328 | if (err) |
| 2301 | goto err_load; | 2329 | goto err_load; |
| 2302 | 2330 | ||
| @@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) · 52 unmodified lines | |||
| 2355 | default: | 2383 | default: |
| 2356 | goto err_no_initvals; | 2384 | goto err_no_initvals; |
| 2357 | } | 2385 | } |
| 2358 | err = b43_do_request_fw(ctx, filename, &fw->initvals_band); | 2386 | err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); |
| 2359 | if (err) | 2387 | if (err) |
| 2360 | goto err_load; | 2388 | goto err_load; |
| 2361 | 2389 | ||
| @@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); · 136 unmodified lines | |||
| 137 | 137 | ||
| 138 | 138 | ||
| 139 | struct b43_request_fw_context; | 139 | struct b43_request_fw_context; |
| 140 | int b43_do_request_fw(struct b43_request_fw_context *ctx, | 140 | int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, |
| 141 | const char *name, | 141 | struct b43_firmware_file *fw, bool async); |
| 142 | struct b43_firmware_file *fw); | ||
| 143 | void b43_do_release_fw(struct b43_firmware_file *fw); | 142 | void b43_do_release_fw(struct b43_firmware_file *fw); |
| 144 | 143 | ||
| 145 | #endif /* B43_MAIN_H_ */ | 144 | #endif /* B43_MAIN_H_ */ |
| @@ -3226,8 +3226,6 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent( · 3225 unmodified lines | |||
| 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( · 15 unmodified lines | |||
| 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( · 1 unmodified line | |||
| 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; |
| @@ -15,8 +15,6 @@ · 14 unmodified lines | |||
| 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> |
| @@ -14,8 +14,6 @@ · 13 unmodified lines | |||
| 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> |
| @@ -39,6 +39,7 @@ · 38 unmodified lines | |||
| 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 { · 435 unmodified lines | |||
| 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 { · 3 unmodified lines | |||
| 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 { · 27 unmodified lines | |||
| 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, · 6 unmodified lines | |||
| 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); |
| @@ -130,31 +130,18 @@ int brcmf_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint len) · 129 unmodified lines | |||
| 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 | ||
| @@ -19,8 +19,6 @@ · 18 unmodified lines | |||
| 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 { · 67 unmodified lines | |||
| 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) · 5 unmodified lines | |||
| 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) · 11 unmodified lines | |||
| 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, · 15 unmodified lines | |||
| 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: · 43 unmodified lines | |||
| 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, · 7 unmodified lines | |||
| 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, · 26 unmodified lines | |||
| 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, · 14 unmodified lines | |||
| 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, · 11 unmodified lines | |||
| 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, · 19 unmodified lines | |||
| 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, · 3 unmodified lines | |||
| 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 | ||
| @@ -14,8 +14,6 @@ · 13 unmodified lines | |||
| 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> |
| @@ -18,21 +18,26 @@ · 17 unmodified lines | |||
| 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 |
| @@ -14,8 +14,6 @@ · 13 unmodified lines | |||
| 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) · 140 unmodified lines | |||
| 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) · 14 unmodified lines | |||
| 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: · 7 unmodified lines | |||
| 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) · 15 unmodified lines | |||
| 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, · 1 unmodified line | |||
| 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, · 57 unmodified lines | |||
| 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); |
| @@ -450,7 +465,7 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr) · 109 unmodified lines | |||
| 450 | sprintf(info.version, "%lu", drvr->drv_version); | 465 | sprintf(info.version, "%lu", drvr->drv_version); |
| 451 | if (copy_to_user(uaddr, &info, sizeof(info))) | 466 | if (copy_to_user(uaddr, &info, sizeof(info))) |
| 452 | return -EFAULT; | 467 | return -EFAULT; |
| 453 | brcmf_dbg(CTL, "given %*s, returning %s\n", | 468 | brcmf_dbg(TRACE, "given %*s, returning %s\n", |
| 454 | (int)sizeof(drvname), drvname, info.driver); | 469 | (int)sizeof(drvname), drvname, info.driver); |
| 455 | break; | 470 | break; |
| 456 | 471 | ||
| @@ -570,14 +585,9 @@ static int brcmf_netdev_open(struct net_device *ndev) · 113 unmodified lines | |||
| 570 | /* Get current TOE mode from dongle */ | 585 | /* Get current TOE mode from dongle */ |
| 571 | if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0 | 586 | if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0 |
| 572 | && (toe_ol & TOE_TX_CSUM_OL) != 0) | 587 | && (toe_ol & TOE_TX_CSUM_OL) != 0) |
| 573 | drvr->iflist[ifp->idx]->ndev->features |= | 588 | ndev->features |= NETIF_F_IP_CSUM; |
| 574 | NETIF_F_IP_CSUM; | ||
| 575 | else | 589 | else |
| 576 | drvr->iflist[ifp->idx]->ndev->features &= | 590 | ndev->features &= ~NETIF_F_IP_CSUM; |
| 577 | ~NETIF_F_IP_CSUM; | ||
| 578 | |||
| 579 | /* make sure RF is ready for work */ | ||
| 580 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0); | ||
| 581 | 591 | ||
| 582 | /* Allow transmit calls */ | 592 | /* Allow transmit calls */ |
| 583 | netif_start_queue(ndev); | 593 | netif_start_queue(ndev); |
| @@ -845,6 +855,17 @@ static void brcmf_bus_detach(struct brcmf_pub *drvr) · 261 unmodified lines | |||
| 845 | } | 855 | } |
| 846 | } | 856 | } |
| 847 | 857 | ||
| 858 | void brcmf_dev_reset(struct device *dev) | ||
| 859 | { | ||
| 860 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
| 861 | struct brcmf_pub *drvr = bus_if->drvr; | ||
| 862 | |||
| 863 | if (drvr == NULL) | ||
| 864 | return; | ||
| 865 | |||
| 866 | brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1); | ||
| 867 | } | ||
| 868 | |||
| 848 | void brcmf_detach(struct device *dev) | 869 | void brcmf_detach(struct device *dev) |
| 849 | { | 870 | { |
| 850 | int i; | 871 | int i; |
| @@ -866,9 +887,8 @@ void brcmf_detach(struct device *dev) · 15 unmodified lines | |||
| 866 | 887 | ||
| 867 | brcmf_bus_detach(drvr); | 888 | brcmf_bus_detach(drvr); |
| 868 | 889 | ||
| 869 | if (drvr->prot) { | 890 | if (drvr->prot) |
| 870 | brcmf_proto_detach(drvr); | 891 | brcmf_proto_detach(drvr); |
| 871 | } | ||
| 872 | 892 | ||
| 873 | brcmf_debugfs_detach(drvr); | 893 | brcmf_debugfs_detach(drvr); |
| 874 | bus_if->drvr = NULL; | 894 | bus_if->drvr = NULL; |
| @@ -14,8 +14,6 @@ · 13 unmodified lines | |||
| 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) · 1147 unmodified lines | |||
| 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) · 212 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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) · 144 unmodified lines | |||
| 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) · 192 unmodified lines | |||
| 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; |
| @@ -15,8 +15,6 @@ · 14 unmodified lines | |||
| 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> |
| @@ -443,14 +443,15 @@ static void brcmf_usb_rx_complete(struct urb *urb) · 442 unmodified lines | |||
| 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) · 3 unmodified lines | |||
| 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) · 1047 unmodified lines | |||
| 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 | } |
| @@ -16,8 +16,6 @@ · 15 unmodified lines | |||
| 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: · 1987 unmodified lines | |||
| 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 | { |
| @@ -3091,10 +3028,11 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, · 1013 unmodified lines | |||
| 3091 | 3028 | ||
| 3092 | len = wpa_ie->len + TLV_HDR_LEN; | 3029 | len = wpa_ie->len + TLV_HDR_LEN; |
| 3093 | data = (u8 *)wpa_ie; | 3030 | data = (u8 *)wpa_ie; |
| 3094 | offset = 0; | 3031 | offset = TLV_HDR_LEN; |
| 3095 | if (!is_rsn_ie) | 3032 | if (!is_rsn_ie) |
| 3096 | offset += VS_IE_FIXED_HDR_LEN; | 3033 | offset += VS_IE_FIXED_HDR_LEN; |
| 3097 | offset += WPA_IE_VERSION_LEN; | 3034 | else |
| 3035 | offset += WPA_IE_VERSION_LEN; | ||
| 3098 | 3036 | ||
| 3099 | /* check for multicast cipher suite */ | 3037 | /* check for multicast cipher suite */ |
| 3100 | if (offset + WPA_IE_MIN_OUI_LEN > len) { | 3038 | if (offset + WPA_IE_MIN_OUI_LEN > len) { |
| @@ -3703,7 +3641,6 @@ static struct cfg80211_ops wl_cfg80211_ops = { · 602 unmodified lines | |||
| 3703 | .set_default_key = brcmf_cfg80211_config_default_key, | 3641 | .set_default_key = brcmf_cfg80211_config_default_key, |
| 3704 | .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key, | 3642 | .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key, |
| 3705 | .set_power_mgmt = brcmf_cfg80211_set_power_mgmt, | 3643 | .set_power_mgmt = brcmf_cfg80211_set_power_mgmt, |
| 3706 | .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask, | ||
| 3707 | .connect = brcmf_cfg80211_connect, | 3644 | .connect = brcmf_cfg80211_connect, |
| 3708 | .disconnect = brcmf_cfg80211_disconnect, | 3645 | .disconnect = brcmf_cfg80211_disconnect, |
| 3709 | .suspend = brcmf_cfg80211_suspend, | 3646 | .suspend = brcmf_cfg80211_suspend, |
| @@ -4329,9 +4266,8 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) · 619 unmodified lines | |||
| 4329 | } | 4266 | } |
| 4330 | 4267 | ||
| 4331 | static s32 | 4268 | static s32 |
| 4332 | 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) |
| 4333 | { | 4270 | { |
| 4334 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
| 4335 | s32 err = 0; | 4271 | s32 err = 0; |
| 4336 | __le32 roamtrigger[2]; | 4272 | __le32 roamtrigger[2]; |
| 4337 | __le32 roam_delta[2]; | 4273 | __le32 roam_delta[2]; |
| @@ -4382,10 +4318,9 @@ dongle_rom_out: · 44 unmodified lines | |||
| 4382 | } | 4318 | } |
| 4383 | 4319 | ||
| 4384 | static s32 | 4320 | static s32 |
| 4385 | brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, | 4321 | brcmf_dongle_scantime(struct brcmf_if *ifp, s32 scan_assoc_time, |
| 4386 | s32 scan_unassoc_time, s32 scan_passive_time) | 4322 | s32 scan_unassoc_time, s32 scan_passive_time) |
| 4387 | { | 4323 | { |
| 4388 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
| 4389 | s32 err = 0; | 4324 | s32 err = 0; |
| 4390 | 4325 | ||
| 4391 | 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, |
| @@ -4455,6 +4390,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) · 63 unmodified lines | |||
| 4455 | { | 4390 | { |
| 4456 | struct net_device *ndev; | 4391 | struct net_device *ndev; |
| 4457 | struct wireless_dev *wdev; | 4392 | struct wireless_dev *wdev; |
| 4393 | struct brcmf_if *ifp; | ||
| 4458 | s32 power_mode; | 4394 | s32 power_mode; |
| 4459 | s32 err = 0; | 4395 | s32 err = 0; |
| 4460 | 4396 | ||
| @@ -4463,35 +4399,34 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) · 2 unmodified lines | |||
| 4463 | 4399 | ||
| 4464 | ndev = cfg_to_ndev(cfg); | 4400 | ndev = cfg_to_ndev(cfg); |
| 4465 | wdev = ndev->ieee80211_ptr; | 4401 | wdev = ndev->ieee80211_ptr; |
| 4402 | ifp = netdev_priv(ndev); | ||
| 4466 | 4403 | ||
| 4467 | brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME, | 4404 | /* make sure RF is ready for work */ |
| 4468 | 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); | ||
| 4469 | 4409 | ||
| 4470 | power_mode = cfg->pwr_save ? PM_FAST : PM_OFF; | 4410 | power_mode = cfg->pwr_save ? PM_FAST : PM_OFF; |
| 4471 | 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); |
| 4472 | power_mode); | ||
| 4473 | if (err) | 4412 | if (err) |
| 4474 | goto default_conf_out; | 4413 | goto default_conf_out; |
| 4475 | brcmf_dbg(INFO, "power save set to %s\n", | 4414 | brcmf_dbg(INFO, "power save set to %s\n", |
| 4476 | (power_mode ? "enabled" : "disabled")); | 4415 | (power_mode ? "enabled" : "disabled")); |
| 4477 | 4416 | ||
| 4478 | err = brcmf_dongle_roam(ndev, (cfg->roam_on ? 0 : 1), | 4417 | err = brcmf_dongle_roam(ifp, (cfg->roam_on ? 0 : 1), WL_BEACON_TIMEOUT); |
| 4479 | WL_BEACON_TIMEOUT); | ||
| 4480 | if (err) | 4418 | if (err) |
| 4481 | goto default_conf_out; | 4419 | goto default_conf_out; |
| 4482 | err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, | 4420 | err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, |
| 4483 | NULL, NULL); | 4421 | NULL, NULL); |
| 4484 | if (err && err != -EINPROGRESS) | 4422 | if (err) |
| 4485 | goto default_conf_out; | 4423 | goto default_conf_out; |
| 4486 | err = brcmf_dongle_probecap(cfg); | 4424 | err = brcmf_dongle_probecap(cfg); |
| 4487 | if (err) | 4425 | if (err) |
| 4488 | goto default_conf_out; | 4426 | goto default_conf_out; |
| 4489 | 4427 | ||
| 4490 | /* -EINPROGRESS: Call commit handler */ | ||
| 4491 | |||
| 4492 | default_conf_out: | ||
| 4493 | |||
| 4494 | cfg->dongle_up = true; | 4428 | cfg->dongle_up = true; |
| 4429 | default_conf_out: | ||
| 4495 | 4430 | ||
| 4496 | return err; | 4431 | return err; |
| 4497 | 4432 | ||
| @@ -4500,8 +4435,6 @@ default_conf_out: · 2 unmodified lines | |||
| 4500 | static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp) | 4435 | static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp) |
| 4501 | { | 4436 | { |
| 4502 | set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state); | 4437 | set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state); |
| 4503 | if (ifp->idx) | ||
| 4504 | return 0; | ||
| 4505 | 4438 | ||
| 4506 | return brcmf_config_dongle(ifp->drvr->config); | 4439 | return brcmf_config_dongle(ifp->drvr->config); |
| 4507 | } | 4440 | } |
| @@ -961,7 +961,6 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, · 960 unmodified lines | |||
| 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, · 22 unmodified lines | |||
| 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, · 3 unmodified lines | |||
| 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, · 2 unmodified lines | |||
| 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 | } |
| @@ -1,5 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012 Broadcom Corporation | 2 | * Copyright (c) 2012 Broadcom Corporation |
| 3 | * Copyright (c) 2012 Canonical Ltd. | ||
| 3 | * | 4 | * |
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -362,8 +362,11 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) · 361 unmodified lines | |||
| 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 | } |
| @@ -1408,9 +1411,10 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) · 1038 unmodified lines | |||
| 1408 | #endif | 1411 | #endif |
| 1409 | t->ms = ms; | 1412 | t->ms = ms; |
| 1410 | t->periodic = (bool) periodic; | 1413 | t->periodic = (bool) periodic; |
| 1411 | t->set = true; | 1414 | if (!t->set) { |
| 1412 | 1415 | t->set = true; | |
| 1413 | atomic_inc(&t->wl->callbacks); | 1416 | atomic_inc(&t->wl->callbacks); |
| 1417 | } | ||
| 1414 | 1418 | ||
| 1415 | ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); | 1419 | ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); |
| 1416 | } | 1420 | } |
| @@ -2473,6 +2473,7 @@ static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw, · 2472 unmodified lines | |||
| 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) · 3 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 5133 unmodified lines | |||
| 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 | ||
| @@ -1343,13 +1343,13 @@ static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain, · 1342 unmodified lines | |||
| 1343 | 1343 | ||
| 1344 | wlc_lcnphy_rx_gain_override_enable(pi, true); | 1344 | wlc_lcnphy_rx_gain_override_enable(pi, true); |
| 1345 | wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0); | 1345 | wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0); |
| 1346 | usleep_range(500, 500); | 1346 | udelay(500); |
| 1347 | write_radio_reg(pi, RADIO_2064_REG112, 0); | 1347 | write_radio_reg(pi, RADIO_2064_REG112, 0); |
| 1348 | if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l)) | 1348 | if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l)) |
| 1349 | return false; | 1349 | return false; |
| 1350 | 1350 | ||
| 1351 | wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0); | 1351 | wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0); |
| 1352 | usleep_range(500, 500); | 1352 | udelay(500); |
| 1353 | write_radio_reg(pi, RADIO_2064_REG112, 0); | 1353 | write_radio_reg(pi, RADIO_2064_REG112, 0); |
| 1354 | if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h)) | 1354 | if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h)) |
| 1355 | return false; | 1355 | return false; |
| @@ -36,7 +36,6 @@ · 35 unmodified lines | |||
| 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]; |
| @@ -3273,7 +3273,7 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr, · 3272 unmodified lines | |||
| 3273 | 3273 | ||
| 3274 | if (count) { | 3274 | if (count) { |
| 3275 | char *p = buffer; | 3275 | char *p = buffer; |
| 3276 | strncpy(buffer, buf, min(sizeof(buffer), count)); | 3276 | strlcpy(buffer, buf, sizeof(buffer)); |
| 3277 | channel = simple_strtoul(p, NULL, 0); | 3277 | channel = simple_strtoul(p, NULL, 0); |
| 3278 | if (channel) | 3278 | if (channel) |
| 3279 | params.channel = channel; | 3279 | params.channel = channel; |
| @@ -3474,6 +3474,7 @@ struct ieee80211_ops il3945_mac_ops = { · 194 unmodified lines | |||
| 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) · 68 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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; |
| @@ -5712,8 +5712,8 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) · 5711 unmodified lines | |||
| 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 | |
| @@ -6308,6 +6308,7 @@ const struct ieee80211_ops il4965_mac_ops = { · 588 unmodified lines | |||
| 6308 | .sta_remove = il_mac_sta_remove, | 6308 | .sta_remove = il_mac_sta_remove, |
| 6309 | .channel_switch = il4965_mac_channel_switch, | 6309 | .channel_switch = il4965_mac_channel_switch, |
| 6310 | .tx_last_beacon = il_mac_tx_last_beacon, | 6310 | .tx_last_beacon = il_mac_tx_last_beacon, |
| 6311 | .flush = il_mac_flush, | ||
| 6311 | }; | 6312 | }; |
| 6312 | 6313 | ||
| 6313 | static int | 6314 | static int |
| @@ -6555,6 +6556,7 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 241 unmodified lines | |||
| 6555 | il4965_prepare_card_hw(il); | 6556 | il4965_prepare_card_hw(il); |
| 6556 | if (!il->hw_ready) { | 6557 | if (!il->hw_ready) { |
| 6557 | IL_WARN("Failed, HW not ready\n"); | 6558 | IL_WARN("Failed, HW not ready\n"); |
| 6559 | err = -EIO; | ||
| 6558 | goto out_iounmap; | 6560 | goto out_iounmap; |
| 6559 | } | 6561 | } |
| 6560 | 6562 | ||
| @@ -3958,17 +3958,21 @@ il_connection_init_rx_config(struct il_priv *il) · 3957 unmodified lines | |||
| 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: · 575 unmodified lines | |||
| 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, · 2 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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, · 102 unmodified lines | |||
| 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: · 4 unmodified lines | |||
| 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. |
| @@ -1723,6 +1723,7 @@ void il_mac_remove_interface(struct ieee80211_hw *hw, · 1722 unmodified lines | |||
| 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 | ||
| @@ -3695,7 +3695,7 @@ struct iwl_bt_uart_msg { · 3694 unmodified lines | |||
| 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 { · 1 unmodified line | |||
| 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 { · 42 unmodified lines | |||
| 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 { · 5 unmodified lines | |||
| 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 |
| @@ -157,7 +157,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, · 156 unmodified lines | |||
| 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, · 12 unmodified lines | |||
| 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 */ |
| @@ -69,7 +69,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = { · 68 unmodified lines | |||
| 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 | /* |
| @@ -206,7 +206,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, · 205 unmodified lines | |||
| 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, · 213 unmodified lines | |||
| 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) · 26 unmodified lines | |||
| 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) · 9 unmodified lines | |||
| 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, · 34 unmodified lines | |||
| 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 | } |
| @@ -354,7 +354,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, · 353 unmodified lines | |||
| 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, · 27 unmodified lines | |||
| 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) · 13 unmodified lines | |||
| 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) · 1212 unmodified lines | |||
| 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, · 83 unmodified lines | |||
| 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, · 32 unmodified lines | |||
| 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, · 72 unmodified lines | |||
| 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 " |
| @@ -186,8 +186,8 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) · 185 unmodified lines | |||
| 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 |
| @@ -231,13 +231,11 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, · 230 unmodified lines | |||
| 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, · 111 unmodified lines | |||
| 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, · 109 unmodified lines | |||
| 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, · 63 unmodified lines | |||
| 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, · 13 unmodified lines | |||
| 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, · 6 unmodified lines | |||
| 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, · 1 unmodified line | |||
| 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, · 355 unmodified lines | |||
| 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, · 113 unmodified lines | |||
| 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), |
| @@ -1151,13 +1145,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, · 66 unmodified lines | |||
| 1151 | next_reclaimed = ssn; | 1145 | next_reclaimed = ssn; |
| 1152 | } | 1146 | } |
| 1153 | 1147 | ||
| 1154 | if (tid != IWL_TID_NON_QOS) { | ||
| 1155 | priv->tid_data[sta_id][tid].next_reclaimed = | ||
| 1156 | next_reclaimed; | ||
| 1157 | IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", | ||
| 1158 | next_reclaimed); | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); | 1148 | iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); |
| 1162 | 1149 | ||
| 1163 | iwlagn_check_ratid_empty(priv, sta_id, tid); | 1150 | iwlagn_check_ratid_empty(priv, sta_id, tid); |
| @@ -1208,21 +1195,49 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, · 44 unmodified lines | |||
| 1208 | if (!is_agg) | 1195 | if (!is_agg) |
| 1209 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); | 1196 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); |
| 1210 | 1197 | ||
| 1198 | /* | ||
| 1199 | * W/A for FW bug - the seq_ctl isn't updated when the | ||
| 1200 | * queues are flushed. Fetch it from the packet itself | ||
| 1201 | */ | ||
| 1202 | if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) { | ||
| 1203 | next_reclaimed = le16_to_cpu(hdr->seq_ctrl); | ||
| 1204 | next_reclaimed = | ||
| 1205 | SEQ_TO_SN(next_reclaimed + 0x10); | ||
| 1206 | } | ||
| 1207 | |||
| 1211 | is_offchannel_skb = | 1208 | is_offchannel_skb = |
| 1212 | (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); | 1209 | (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); |
| 1213 | freed++; | 1210 | freed++; |
| 1214 | } | 1211 | } |
| 1215 | 1212 | ||
| 1216 | WARN_ON(!is_agg && freed != 1); | 1213 | if (tid != IWL_TID_NON_QOS) { |
| 1214 | priv->tid_data[sta_id][tid].next_reclaimed = | ||
| 1215 | next_reclaimed; | ||
| 1216 | IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", | ||
| 1217 | next_reclaimed); | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | if (!is_agg && freed != 1) | ||
| 1221 | IWL_ERR(priv, "Q: %d, freed %d\n", txq_id, freed); | ||
| 1217 | 1222 | ||
| 1218 | /* | 1223 | /* |
| 1219 | * 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 |
| 1220 | * there is no aggregation (and reordering) so it only is single | 1225 | * there is no aggregation (and reordering) so it only is single |
| 1221 | * skb is expected to be processed. | 1226 | * skb is expected to be processed. |
| 1222 | */ | 1227 | */ |
| 1223 | WARN_ON(is_offchannel_skb && freed != 1); | 1228 | if (is_offchannel_skb && freed != 1) |
| 1229 | IWL_ERR(priv, "OFFCHANNEL SKB freed %d\n", freed); | ||
| 1224 | } | 1230 | } |
| 1225 | 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 | |||
| 1226 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | 1241 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
| 1227 | spin_unlock(&priv->sta_lock); | 1242 | spin_unlock(&priv->sta_lock); |
| 1228 | 1243 | ||
| @@ -286,89 +286,6 @@ static int iwl_alive_notify(struct iwl_priv *priv) · 285 unmodified lines | |||
| 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, · 51 unmodified lines | |||
| 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, · 17 unmodified lines | |||
| 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 | } |
| @@ -381,8 +381,8 @@ · 380 unmodified lines | |||
| 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) |
| @@ -225,6 +225,8 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) · 224 unmodified lines | |||
| 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) · 26 unmodified lines | |||
| 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 */ |
| @@ -35,12 +35,12 @@ · 34 unmodified lines | |||
| 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, · 52 unmodified lines | |||
| 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) · 5 unmodified lines | |||
| 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) · 31 unmodified lines | |||
| 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) · 4 unmodified lines | |||
| 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) · 4 unmodified lines | |||
| 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, · 5 unmodified lines | |||
| 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) · 5 unmodified lines | |||
| 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); | ||
| @@ -53,6 +53,8 @@ static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs) · 52 unmodified lines | |||
| 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, · 2 unmodified lines | |||
| 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, · 5 unmodified lines | |||
| 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 |
| @@ -467,18 +467,20 @@ static int iwl_test_indirect_read(struct iwl_test *tst, u32 addr, u32 size) · 466 unmodified lines | |||
| 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, · 16 unmodified lines | |||
| 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 | } |
| @@ -307,6 +307,16 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) · 306 unmodified lines | |||
| 307 | #define IWL_MAX_TID_COUNT 8 | 307 | #define IWL_MAX_TID_COUNT 8 |
| 308 | #define IWL_FRAME_LIMIT 64 | 308 | #define IWL_FRAME_LIMIT 64 |
| 309 | 309 | ||
| 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 | |||
| 310 | /** | 320 | /** |
| 311 | * struct iwl_trans_config - transport configuration | 321 | * struct iwl_trans_config - transport configuration |
| 312 | * | 322 | * |
| @@ -321,6 +331,8 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) · 8 unmodified lines | |||
| 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 { · 8 unmodified lines | |||
| 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; · 19 unmodified lines | |||
| 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; · 18 unmodified lines | |||
| 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 { · 17 unmodified lines | |||
| 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) · 95 unmodified lines | |||
| 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) · 5 unmodified lines | |||
| 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) · 80 unmodified lines | |||
| 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, · 36 unmodified lines | |||
| 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 | ******************************************************/ |
| @@ -222,8 +222,6 @@ struct iwl_txq { · 221 unmodified lines | |||
| 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 { · 4 unmodified lines | |||
| 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 { · 9 unmodified lines | |||
| 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 { · 19 unmodified lines | |||
| 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, · 74 unmodified lines | |||
| 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 | ******************************************************/ |
| @@ -436,7 +436,7 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans) · 435 unmodified lines | |||
| 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) · 12 unmodified lines | |||
| 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) · 30 unmodified lines | |||
| 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) · 20 unmodified lines | |||
| 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) · 21 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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 | ||
| @@ -1166,6 +1172,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) · 599 unmodified lines | |||
| 1166 | else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && | 1172 | else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && |
| 1167 | !trans_pcie->inta) | 1173 | !trans_pcie->inta) |
| 1168 | iwl_enable_interrupts(trans); | 1174 | iwl_enable_interrupts(trans); |
| 1175 | return IRQ_HANDLED; | ||
| 1169 | 1176 | ||
| 1170 | none: | 1177 | none: |
| 1171 | /* re-enable interrupts here since we don't have anything to service. */ | 1178 | /* re-enable interrupts here since we don't have anything to service. */ |
| @@ -75,21 +75,16 @@ · 74 unmodified lines | |||
| 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) · 163 unmodified lines | |||
| 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, · 169 unmodified lines | |||
| 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, · 12 unmodified lines | |||
| 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) · 73 unmodified lines | |||
| 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) · 5 unmodified lines | |||
| 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) · 4 unmodified lines | |||
| 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, · 87 unmodified lines | |||
| 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) · 29 unmodified lines | |||
| 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) · 3 unmodified lines | |||
| 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) · 7 unmodified lines | |||
| 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 = { · 421 unmodified lines | |||
| 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 = { · 16 unmodified lines | |||
| 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, · 75 unmodified lines | |||
| 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, · 19 unmodified lines | |||
| 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: |
| @@ -160,7 +160,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) · 159 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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, · 55 unmodified lines | |||
| 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) · 62 unmodified lines | |||
| 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) · 300 unmodified lines | |||
| 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) · 19 unmodified lines | |||
| 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) · 5 unmodified lines | |||
| 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) · 25 unmodified lines | |||
| 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, · 299 unmodified lines | |||
| 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, · 52 unmodified lines | |||
| 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) · 24 unmodified lines | |||
| 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, · 533 unmodified lines | |||
| 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 | ||
| @@ -363,6 +363,8 @@ struct mac80211_hwsim_data { · 362 unmodified lines | |||
| 363 | /* 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 */ |
| 364 | s64 tsf_offset; | 364 | s64 tsf_offset; |
| 365 | s64 bcn_delta; | 365 | s64 bcn_delta; |
| 366 | /* absolute beacon transmission time. Used to cover up "tx" delay. */ | ||
| 367 | u64 abs_bcn_ts; | ||
| 366 | }; | 368 | }; |
| 367 | 369 | ||
| 368 | 370 | ||
| @@ -410,15 +412,19 @@ static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb, · 41 unmodified lines | |||
| 410 | return NETDEV_TX_OK; | 412 | return NETDEV_TX_OK; |
| 411 | } | 413 | } |
| 412 | 414 | ||
| 415 | static inline u64 mac80211_hwsim_get_tsf_raw(void) | ||
| 416 | { | ||
| 417 | return ktime_to_us(ktime_get_real()); | ||
| 418 | } | ||
| 419 | |||
| 413 | static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) | 420 | static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) |
| 414 | { | 421 | { |
| 415 | struct timeval tv = ktime_to_timeval(ktime_get_real()); | 422 | u64 now = mac80211_hwsim_get_tsf_raw(); |
| 416 | u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec; | ||
| 417 | return cpu_to_le64(now + data->tsf_offset); | 423 | return cpu_to_le64(now + data->tsf_offset); |
| 418 | } | 424 | } |
| 419 | 425 | ||
| 420 | static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw, | 426 | static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw, |
| 421 | struct ieee80211_vif *vif) | 427 | struct ieee80211_vif *vif) |
| 422 | { | 428 | { |
| 423 | struct mac80211_hwsim_data *data = hw->priv; | 429 | struct mac80211_hwsim_data *data = hw->priv; |
| 424 | return le64_to_cpu(__mac80211_hwsim_get_tsf(data)); | 430 | return le64_to_cpu(__mac80211_hwsim_get_tsf(data)); |
| @@ -705,7 +711,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, · 280 unmodified lines | |||
| 705 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 711 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
| 706 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 712 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 707 | struct ieee80211_rx_status rx_status; | 713 | struct ieee80211_rx_status rx_status; |
| 708 | struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); | 714 | u64 now; |
| 709 | 715 | ||
| 710 | memset(&rx_status, 0, sizeof(rx_status)); | 716 | memset(&rx_status, 0, sizeof(rx_status)); |
| 711 | rx_status.flag |= RX_FLAG_MACTIME_START; | 717 | rx_status.flag |= RX_FLAG_MACTIME_START; |
| @@ -731,11 +737,23 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, · 19 unmodified lines | |||
| 731 | secpath_reset(skb); | 737 | secpath_reset(skb); |
| 732 | nf_reset(skb); | 738 | nf_reset(skb); |
| 733 | 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 | |||
| 734 | /* 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 */ |
| 735 | spin_lock(&hwsim_radio_lock); | 754 | spin_lock(&hwsim_radio_lock); |
| 736 | list_for_each_entry(data2, &hwsim_radios, list) { | 755 | list_for_each_entry(data2, &hwsim_radios, list) { |
| 737 | struct sk_buff *nskb; | 756 | struct sk_buff *nskb; |
| 738 | struct ieee80211_mgmt *mgmt; | ||
| 739 | struct tx_iter_data tx_iter_data = { | 757 | struct tx_iter_data tx_iter_data = { |
| 740 | .receive = false, | 758 | .receive = false, |
| 741 | .channel = chan, | 759 | .channel = chan, |
| @@ -787,17 +805,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, · 45 unmodified lines | |||
| 787 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) | 805 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) |
| 788 | ack = true; | 806 | ack = true; |
| 789 | 807 | ||
| 790 | /* set bcn timestamp relative to receiver mactime */ | 808 | rx_status.mactime = now + data2->tsf_offset; |
| 791 | rx_status.mactime = | ||
| 792 | le64_to_cpu(__mac80211_hwsim_get_tsf(data2)); | ||
| 793 | mgmt = (struct ieee80211_mgmt *) nskb->data; | ||
| 794 | if (ieee80211_is_beacon(mgmt->frame_control) || | ||
| 795 | ieee80211_is_probe_resp(mgmt->frame_control)) | ||
| 796 | mgmt->u.beacon.timestamp = cpu_to_le64( | ||
| 797 | rx_status.mactime + | ||
| 798 | (data->tsf_offset - data2->tsf_offset) + | ||
| 799 | 24 * 8 * 10 / txrate->bitrate); | ||
| 800 | |||
| 801 | #if 0 | 809 | #if 0 |
| 802 | /* | 810 | /* |
| 803 | * 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 |
| @@ -987,7 +995,11 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, · 183 unmodified lines | |||
| 987 | static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | 995 | static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, |
| 988 | struct ieee80211_vif *vif) | 996 | struct ieee80211_vif *vif) |
| 989 | { | 997 | { |
| 990 | 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; | ||
| 991 | struct sk_buff *skb; | 1003 | struct sk_buff *skb; |
| 992 | 1004 | ||
| 993 | hwsim_check_magic(vif); | 1005 | hwsim_check_magic(vif); |
| @@ -1000,6 +1012,15 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, · 6 unmodified lines | |||
| 1000 | skb = ieee80211_beacon_get(hw, vif); | 1012 | skb = ieee80211_beacon_get(hw, vif); |
| 1001 | if (skb == NULL) | 1013 | if (skb == NULL) |
| 1002 | 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); | ||
| 1003 | 1024 | ||
| 1004 | mac80211_hwsim_tx_frame(hw, skb, | 1025 | mac80211_hwsim_tx_frame(hw, skb, |
| 1005 | rcu_dereference(vif->chanctx_conf)->def.chan); | 1026 | rcu_dereference(vif->chanctx_conf)->def.chan); |
| @@ -1020,7 +1041,7 @@ mac80211_hwsim_beacon(struct hrtimer *timer) · 14 unmodified lines | |||
| 1020 | 1041 | ||
| 1021 | ieee80211_iterate_active_interfaces_atomic( | 1042 | ieee80211_iterate_active_interfaces_atomic( |
| 1022 | hw, IEEE80211_IFACE_ITER_NORMAL, | 1043 | hw, IEEE80211_IFACE_ITER_NORMAL, |
| 1023 | mac80211_hwsim_beacon_tx, hw); | 1044 | mac80211_hwsim_beacon_tx, data); |
| 1024 | 1045 | ||
| 1025 | /* beacon at new TBTT + beacon interval */ | 1046 | /* beacon at new TBTT + beacon interval */ |
| 1026 | if (data->bcn_delta) { | 1047 | if (data->bcn_delta) { |
| @@ -53,7 +53,9 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, · 52 unmodified lines | |||
| 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 | ||
| @@ -278,14 +278,16 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, · 277 unmodified lines | |||
| 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); |
| @@ -1325,6 +1325,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, · 1324 unmodified lines | |||
| 1325 | } | 1325 | } |
| 1326 | 1326 | ||
| 1327 | 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); | ||
| 1328 | 1329 | ||
| 1329 | if (params->inactivity_timeout > 0) { | 1330 | if (params->inactivity_timeout > 0) { |
| 1330 | /* 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 */ |
| @@ -1457,7 +1458,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, · 126 unmodified lines | |||
| 1457 | struct cfg80211_ssid req_ssid; | 1458 | struct cfg80211_ssid req_ssid; |
| 1458 | int ret, auth_type = 0; | 1459 | int ret, auth_type = 0; |
| 1459 | struct cfg80211_bss *bss = NULL; | 1460 | struct cfg80211_bss *bss = NULL; |
| 1460 | u8 is_scanning_required = 0, config_bands = 0; | 1461 | u8 is_scanning_required = 0; |
| 1461 | 1462 | ||
| 1462 | memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); | 1463 | memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); |
| 1463 | 1464 | ||
| @@ -1476,19 +1477,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, · 12 unmodified lines | |||
| 1476 | /* disconnect before try to associate */ | 1477 | /* disconnect before try to associate */ |
| 1477 | mwifiex_deauthenticate(priv, NULL); | 1478 | mwifiex_deauthenticate(priv, NULL); |
| 1478 | 1479 | ||
| 1479 | if (channel) { | ||
| 1480 | if (mode == NL80211_IFTYPE_STATION) { | ||
| 1481 | if (channel->band == IEEE80211_BAND_2GHZ) | ||
| 1482 | config_bands = BAND_B | BAND_G | BAND_GN; | ||
| 1483 | else | ||
| 1484 | config_bands = BAND_A | BAND_AN; | ||
| 1485 | |||
| 1486 | if (!((config_bands | priv->adapter->fw_bands) & | ||
| 1487 | ~priv->adapter->fw_bands)) | ||
| 1488 | priv->adapter->config_bands = config_bands; | ||
| 1489 | } | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | /* As this is new association, clear locally stored | 1480 | /* As this is new association, clear locally stored |
| 1493 | * keys and security related flags */ | 1481 | * keys and security related flags */ |
| 1494 | priv->sec_info.wpa_enabled = false; | 1482 | priv->sec_info.wpa_enabled = false; |
| @@ -1705,9 +1693,9 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, · 210 unmodified lines | |||
| 1705 | 1693 | ||
| 1706 | if (cfg80211_get_chandef_type(¶ms->chandef) != | 1694 | if (cfg80211_get_chandef_type(¶ms->chandef) != |
| 1707 | NL80211_CHAN_NO_HT) | 1695 | NL80211_CHAN_NO_HT) |
| 1708 | config_bands |= BAND_GN; | 1696 | config_bands |= BAND_G | BAND_GN; |
| 1709 | } else { | 1697 | } else { |
| 1710 | if (cfg80211_get_chandef_type(¶ms->chandef) != | 1698 | if (cfg80211_get_chandef_type(¶ms->chandef) == |
| 1711 | NL80211_CHAN_NO_HT) | 1699 | NL80211_CHAN_NO_HT) |
| 1712 | config_bands = BAND_A; | 1700 | config_bands = BAND_A; |
| 1713 | else | 1701 | else |
| @@ -2259,6 +2247,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) · 545 unmodified lines | |||
| 2259 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 2247 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
| 2260 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | | 2248 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | |
| 2261 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | | 2249 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | |
| 2250 | WIPHY_FLAG_AP_UAPSD | | ||
| 2262 | WIPHY_FLAG_CUSTOM_REGULATORY | | 2251 | WIPHY_FLAG_CUSTOM_REGULATORY | |
| 2263 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 2252 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
| 2264 | 2253 | ||
| @@ -26,6 +26,7 @@ · 25 unmodified lines | |||
| 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 @@ · 26 unmodified lines | |||
| 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 { · 62 unmodified lines | |||
| 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_ */ |
| @@ -330,6 +330,9 @@ enum P2P_MODES { · 329 unmodified lines | |||
| 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 { · 795 unmodified lines | |||
| 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 { · 43 unmodified lines | |||
| 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; |
| @@ -591,6 +591,12 @@ int mwifiex_init_fw(struct mwifiex_adapter *adapter) · 590 unmodified lines | |||
| 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); |
| @@ -20,7 +20,6 @@ · 19 unmodified lines | |||
| 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 { · 80 unmodified lines | |||
| 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 { |
| @@ -615,23 +615,33 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, · 614 unmodified lines | |||
| 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, · 331 unmodified lines | |||
| 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 | ||
| @@ -599,8 +599,10 @@ struct mwifiex_if_ops { · 598 unmodified lines | |||
| 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, · 283 unmodified lines | |||
| 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. |
| @@ -39,17 +39,20 @@ static struct semaphore add_remove_card_sem; · 38 unmodified lines | |||
| 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) · 4 unmodified lines | |||
| 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) · 93 unmodified lines | |||
| 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) · 198 unmodified lines | |||
| 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) · 9 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 3 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 6 unmodified lines | |||
| 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) · 7 unmodified lines | |||
| 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) · 15 unmodified lines | |||
| 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) · 7 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 6 unmodified lines | |||
| 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) · 7 unmodified lines | |||
| 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) · 15 unmodified lines | |||
| 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) · 7 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 13 unmodified lines | |||
| 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) · 4 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 10 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 8 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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) · 4 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 1 unmodified line | |||
| 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) · 21 unmodified lines | |||
| 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: · 3 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 8 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 1 unmodified line | |||
| 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) · 32 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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, · 27 unmodified lines | |||
| 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) · 7 unmodified lines | |||
| 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) · 25 unmodified lines | |||
| 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, · 38 unmodified lines | |||
| 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, · 13 unmodified lines | |||
| 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, · 42 unmodified lines | |||
| 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, · 15 unmodified lines | |||
| 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, · 68 unmodified lines | |||
| 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, · 1 unmodified line | |||
| 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: · 176 unmodified lines | |||
| 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) · 21 unmodified lines | |||
| 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, · 25 unmodified lines | |||
| 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) · 120 unmodified lines | |||
| 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) · 50 unmodified lines | |||
| 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 = { · 15 unmodified lines | |||
| 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 | /* |
| @@ -114,11 +114,12 @@ struct pcie_service_card { · 113 unmodified lines | |||
| 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 { · 1 unmodified line | |||
| 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 { · 1 unmodified line | |||
| 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 */ |
| @@ -931,7 +931,6 @@ mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv, · 930 unmodified lines | |||
| 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, · 15 unmodified lines | |||
| 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 | } |
| @@ -56,7 +56,6 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, · 55 unmodified lines | |||
| 56 | */ | 56 | */ |
| 57 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) | 57 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) |
| 58 | { | 58 | { |
| 59 | bool cancel_flag = false; | ||
| 60 | int status; | 59 | int status; |
| 61 | struct cmd_ctrl_node *cmd_queued; | 60 | struct cmd_ctrl_node *cmd_queued; |
| 62 | 61 | ||
| @@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) · 7 unmodified lines | |||
| 70 | atomic_inc(&adapter->cmd_pending); | 69 | atomic_inc(&adapter->cmd_pending); |
| 71 | 70 | ||
| 72 | /* Wait for completion */ | 71 | /* Wait for completion */ |
| 73 | wait_event_interruptible(adapter->cmd_wait_q.wait, | 72 | status = wait_event_interruptible(adapter->cmd_wait_q.wait, |
| 74 | *(cmd_queued->condition)); | 73 | *(cmd_queued->condition)); |
| 75 | if (!*(cmd_queued->condition)) | 74 | if (status) { |
| 76 | cancel_flag = true; | 75 | dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); |
| 77 | 76 | return status; | |
| 78 | if (cancel_flag) { | ||
| 79 | mwifiex_cancel_pending_ioctl(adapter); | ||
| 80 | dev_dbg(adapter->dev, "cmd cancel\n"); | ||
| 81 | } | 77 | } |
| 82 | 78 | ||
| 83 | status = adapter->cmd_wait_q.status; | 79 | status = adapter->cmd_wait_q.status; |
| @@ -287,6 +283,20 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, · 203 unmodified lines | |||
| 287 | if (ret) | 283 | if (ret) |
| 288 | goto done; | 284 | goto done; |
| 289 | 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 | |||
| 290 | ret = mwifiex_check_network_compatibility(priv, bss_desc); | 300 | ret = mwifiex_check_network_compatibility(priv, bss_desc); |
| 291 | if (ret) | 301 | if (ret) |
| 292 | goto done; | 302 | goto done; |
| @@ -496,8 +506,11 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) · 203 unmodified lines | |||
| 496 | return false; | 506 | return false; |
| 497 | } | 507 | } |
| 498 | 508 | ||
| 499 | wait_event_interruptible(adapter->hs_activate_wait_q, | 509 | if (wait_event_interruptible(adapter->hs_activate_wait_q, |
| 500 | adapter->hs_activate_wait_q_woken); | 510 | adapter->hs_activate_wait_q_woken)) { |
| 511 | dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); | ||
| 512 | return false; | ||
| 513 | } | ||
| 501 | 514 | ||
| 502 | return true; | 515 | return true; |
| 503 | } | 516 | } |
| @@ -117,14 +117,16 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, · 116 unmodified lines | |||
| 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); |
| @@ -219,6 +219,7 @@ void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config) · 218 unmodified lines | |||
| 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) · 72 unmodified lines | |||
| 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) · 51 unmodified lines | |||
| 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) · 147 unmodified lines | |||
| 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); |
| @@ -786,21 +786,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) · 785 unmodified lines | |||
| 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, · 29 unmodified lines | |||
| 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; |
| @@ -22,16 +22,16 @@ · 21 unmodified lines | |||
| 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_ */ |
| @@ -568,6 +568,8 @@ mwifiex_clean_txrx(struct mwifiex_private *priv) · 567 unmodified lines | |||
| 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, · 632 unmodified lines | |||
| 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 | } |
| @@ -101,6 +101,18 @@ MODULE_PARM_DESC(ap_mode_default, · 100 unmodified lines | |||
| 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 { · 53 unmodified lines | |||
| 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 { · 35 unmodified lines | |||
| 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) · 1308 unmodified lines | |||
| 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) · 15 unmodified lines | |||
| 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) · 21 unmodified lines | |||
| 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) · 164 unmodified lines | |||
| 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) · 34 unmodified lines | |||
| 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) · 40 unmodified lines | |||
| 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, · 93 unmodified lines | |||
| 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, · 35 unmodified lines | |||
| 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) · 1601 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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, · 153 unmodified lines | |||
| 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, · 5 unmodified lines | |||
| 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, · 90 unmodified lines | |||
| 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) |
| @@ -4250,9 +4333,11 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, · 368 unmodified lines | |||
| 4250 | p->amsdu_enabled = 0; | 4333 | p->amsdu_enabled = 0; |
| 4251 | 4334 | ||
| 4252 | rc = mwl8k_post_cmd(hw, &cmd->header); | 4335 | rc = mwl8k_post_cmd(hw, &cmd->header); |
| 4336 | if (!rc) | ||
| 4337 | rc = p->station_id; | ||
| 4253 | kfree(cmd); | 4338 | kfree(cmd); |
| 4254 | 4339 | ||
| 4255 | return rc ? rc : p->station_id; | 4340 | return rc; |
| 4256 | } | 4341 | } |
| 4257 | 4342 | ||
| 4258 | static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, | 4343 | static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, |
| @@ -4301,6 +4386,10 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) · 42 unmodified lines | |||
| 4301 | } | 4386 | } |
| 4302 | 4387 | ||
| 4303 | 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); | ||
| 4304 | status &= ~MWL8K_A2H_INT_BA_WATCHDOG; | 4393 | status &= ~MWL8K_A2H_INT_BA_WATCHDOG; |
| 4305 | ieee80211_queue_work(hw, &priv->watchdog_ba_handle); | 4394 | ieee80211_queue_work(hw, &priv->watchdog_ba_handle); |
| 4306 | } | 4395 | } |
| @@ -4444,6 +4533,8 @@ static int mwl8k_start(struct ieee80211_hw *hw) · 137 unmodified lines | |||
| 4444 | priv->irq = -1; | 4533 | priv->irq = -1; |
| 4445 | tasklet_disable(&priv->poll_tx_task); | 4534 | tasklet_disable(&priv->poll_tx_task); |
| 4446 | tasklet_disable(&priv->poll_rx_task); | 4535 | tasklet_disable(&priv->poll_rx_task); |
| 4536 | } else { | ||
| 4537 | ieee80211_wake_queues(hw); | ||
| 4447 | } | 4538 | } |
| 4448 | 4539 | ||
| 4449 | return rc; | 4540 | return rc; |
| @@ -5092,7 +5183,7 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 642 unmodified lines | |||
| 5092 | int i, rc = 0; | 5183 | int i, rc = 0; |
| 5093 | struct mwl8k_priv *priv = hw->priv; | 5184 | struct mwl8k_priv *priv = hw->priv; |
| 5094 | struct mwl8k_ampdu_stream *stream; | 5185 | struct mwl8k_ampdu_stream *stream; |
| 5095 | u8 *addr = sta->addr; | 5186 | u8 *addr = sta->addr, idx; |
| 5096 | struct mwl8k_sta *sta_info = MWL8K_STA(sta); | 5187 | struct mwl8k_sta *sta_info = MWL8K_STA(sta); |
| 5097 | 5188 | ||
| 5098 | if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) | 5189 | if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) |
| @@ -5175,8 +5266,9 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, · 76 unmodified lines | |||
| 5175 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | 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, · 9 unmodified lines | |||
| 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 { · 56 unmodified lines | |||
| 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) · 201 unmodified lines | |||
| 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) · 3 unmodified lines | |||
| 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, · 330 unmodified lines | |||
| 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, · 6 unmodified lines | |||
| 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 | } |
| @@ -559,6 +559,7 @@ static int p54p_probe(struct pci_dev *pdev, · 558 unmodified lines | |||
| 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, · 3 unmodified lines | |||
| 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 | } |
| @@ -47,6 +47,7 @@ static struct usb_device_id p54u_table[] = { · 46 unmodified lines | |||
| 47 | {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ | 47 | {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ |
| 48 | {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ | 48 | {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ |
| 49 | {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ | 49 | {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ |
| 50 | {USB_DEVICE(0x0675, 0x0530)}, /* DrayTek Vigor 530 */ | ||
| 50 | {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */ | 51 | {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */ |
| 51 | {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ | 52 | {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ |
| 52 | {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */ | 53 | {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */ |
| @@ -82,6 +83,8 @@ static struct usb_device_id p54u_table[] = { · 29 unmodified lines | |||
| 82 | {USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */ | 83 | {USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */ |
| 83 | {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ | 84 | {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ |
| 84 | {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ | 85 | {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ |
| 86 | {USB_DEVICE(0x0803, 0x4310)}, /* Zoom 4410a */ | ||
| 87 | {USB_DEVICE(0x083a, 0x4503)}, /* T-Com Sinus 154 data II */ | ||
| 85 | {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ | 88 | {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ |
| 86 | {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */ | 89 | {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */ |
| 87 | {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ | 90 | {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ |
| @@ -101,6 +104,7 @@ static struct usb_device_id p54u_table[] = { · 13 unmodified lines | |||
| 101 | {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ | 104 | {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ |
| 102 | {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ | 105 | {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ |
| 103 | {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ | 106 | {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ |
| 107 | /* {USB_DEVICE(0x15a9, 0x0002)}, * Also SparkLAN WL-682 with 3887 */ | ||
| 104 | {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ | 108 | {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ |
| 105 | {USB_DEVICE(0x1740, 0x1000)}, /* Senao NUB-350 */ | 109 | {USB_DEVICE(0x1740, 0x1000)}, /* Senao NUB-350 */ |
| 106 | {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ | 110 | {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ |
| @@ -1503,6 +1503,7 @@ static int prism54_get_auth(struct net_device *ndev, · 1502 unmodified lines | |||
| 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; |
| @@ -1107,12 +1107,15 @@ static int ray_get_essid(struct net_device *dev, struct iw_request_info *info, · 1106 unmodified lines | |||
| 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) · 723 unmodified lines | |||
| 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) · 53 unmodified lines | |||
| 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) · 21 unmodified lines | |||
| 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); |
| @@ -1296,8 +1296,7 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, · 1295 unmodified lines | |||
| 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, · 2562 unmodified lines | |||
| 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) · 17 unmodified lines | |||
| 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) · 12 unmodified lines | |||
| 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) · 334 unmodified lines | |||
| 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) · 3 unmodified lines | |||
| 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) · 444 unmodified lines | |||
| 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 |
| @@ -43,7 +43,7 @@ struct rt2800_ops { · 42 unmodified lines | |||
| 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, · 67 unmodified lines | |||
| 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); · 79 unmodified lines | |||
| 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 | ||
| @@ -90,17 +90,22 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) · 89 unmodified lines | |||
| 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) · 28 unmodified lines | |||
| 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) · 22 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 1 unmodified line | |||
| 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) · 777 unmodified lines | |||
| 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 = { |
| @@ -735,13 +735,17 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, · 734 unmodified lines | |||
| 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) |
| @@ -1016,6 +1016,26 @@ struct rt2x00_dev { · 1015 unmodified lines | |||
| 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 | /* |
| @@ -271,6 +271,50 @@ void rt2x00lib_dmadone(struct queue_entry *entry) · 270 unmodified lines | |||
| 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, · 47 unmodified lines | |||
| 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) · 158 unmodified lines | |||
| 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) |
| @@ -673,6 +764,12 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp) · 176 unmodified lines | |||
| 673 | */ | 764 | */ |
| 674 | rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc); | 765 | rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc); |
| 675 | 766 | ||
| 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 | |||
| 676 | /* | 773 | /* |
| 677 | * Update extra components | 774 | * Update extra components |
| 678 | */ | 775 | */ |
| @@ -1183,6 +1280,8 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) · 504 unmodified lines | |||
| 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 | ||
| @@ -582,6 +582,48 @@ static void rt2x00queue_kick_tx_queue(struct data_queue *queue, · 581 unmodified lines | |||
| 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, · 92 unmodified lines | |||
| 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); |
| @@ -57,12 +57,12 @@ config RTL8192CU · 56 unmodified lines | |||
| 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 |
| @@ -743,6 +743,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) · 742 unmodified lines | |||
| 743 | 743 | ||
| 744 | done: | 744 | done: |
| 745 | bufferaddress = (*((dma_addr_t *)skb->cb)); | 745 | bufferaddress = (*((dma_addr_t *)skb->cb)); |
| 746 | if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress)) | ||
| 747 | return; | ||
| 746 | tmp_one = 1; | 748 | tmp_one = 1; |
| 747 | rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, | 749 | rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, |
| 748 | HW_DESC_RXBUFF_ADDR, | 750 | HW_DESC_RXBUFF_ADDR, |
| @@ -1115,6 +1117,10 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) · 366 unmodified lines | |||
| 1115 | PCI_DMA_FROMDEVICE); | 1117 | PCI_DMA_FROMDEVICE); |
| 1116 | 1118 | ||
| 1117 | bufferaddress = (*((dma_addr_t *)skb->cb)); | 1119 | bufferaddress = (*((dma_addr_t *)skb->cb)); |
| 1120 | if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress)) { | ||
| 1121 | dev_kfree_skb_any(skb); | ||
| 1122 | return 1; | ||
| 1123 | } | ||
| 1118 | rtlpriv->cfg->ops->set_desc((u8 *)entry, false, | 1124 | rtlpriv->cfg->ops->set_desc((u8 *)entry, false, |
| 1119 | HW_DESC_RXBUFF_ADDR, | 1125 | HW_DESC_RXBUFF_ADDR, |
| 1120 | (u8 *)&bufferaddress); | 1126 | (u8 *)&bufferaddress); |
| @@ -692,7 +692,7 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) · 691 unmodified lines | |||
| 692 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | 692 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { |
| 693 | rtl92c_phy_sw_chnl_callback(hw); | 693 | rtl92c_phy_sw_chnl_callback(hw); |
| 694 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 694 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
| 695 | "sw_chnl_inprogress false schdule workitem\n"); | 695 | "sw_chnl_inprogress false schedule workitem\n"); |
| 696 | rtlphy->sw_chnl_inprogress = false; | 696 | rtlphy->sw_chnl_inprogress = false; |
| 697 | } else { | 697 | } else { |
| 698 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 698 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
| @@ -611,8 +611,14 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, · 610 unmodified lines | |||
| 611 | dma_addr_t mapping = pci_map_single(rtlpci->pdev, | 611 | dma_addr_t mapping = pci_map_single(rtlpci->pdev, |
| 612 | skb->data, skb->len, | 612 | skb->data, skb->len, |
| 613 | PCI_DMA_TODEVICE); | 613 | PCI_DMA_TODEVICE); |
| 614 | |||
| 614 | u8 bw_40 = 0; | 615 | u8 bw_40 = 0; |
| 615 | 616 | ||
| 617 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { | ||
| 618 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
| 619 | "DMA mapping error"); | ||
| 620 | return; | ||
| 621 | } | ||
| 616 | rcu_read_lock(); | 622 | rcu_read_lock(); |
| 617 | sta = get_sta(hw, mac->vif, mac->bssid); | 623 | sta = get_sta(hw, mac->vif, mac->bssid); |
| 618 | if (mac->opmode == NL80211_IFTYPE_STATION) { | 624 | if (mac->opmode == NL80211_IFTYPE_STATION) { |
| @@ -774,6 +780,11 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, · 155 unmodified lines | |||
| 774 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); | 780 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); |
| 775 | __le16 fc = hdr->frame_control; | 781 | __le16 fc = hdr->frame_control; |
| 776 | 782 | ||
| 783 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { | ||
| 784 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
| 785 | "DMA mapping error"); | ||
| 786 | return; | ||
| 787 | } | ||
| 777 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); | 788 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); |
| 778 | 789 | ||
| 779 | if (firstseg) | 790 | if (firstseg) |
| @@ -452,7 +452,7 @@ static void _rtl92de_translate_rx_signal_stuff(struct ieee80211_hw *hw, · 451 unmodified lines | |||
| 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; |
| @@ -587,6 +587,11 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, · 128 unmodified lines | |||
| 587 | buf_len = skb->len; | 587 | buf_len = skb->len; |
| 588 | mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, | 588 | mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, |
| 589 | PCI_DMA_TODEVICE); | 589 | PCI_DMA_TODEVICE); |
| 590 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { | ||
| 591 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
| 592 | "DMA mapping error"); | ||
| 593 | return; | ||
| 594 | } | ||
| 590 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d)); | 595 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d)); |
| 591 | if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { | 596 | if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { |
| 592 | firstseg = true; | 597 | firstseg = true; |
| @@ -740,6 +745,11 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, · 147 unmodified lines | |||
| 740 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); | 745 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); |
| 741 | __le16 fc = hdr->frame_control; | 746 | __le16 fc = hdr->frame_control; |
| 742 | 747 | ||
| 748 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { | ||
| 749 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
| 750 | "DMA mapping error"); | ||
| 751 | return; | ||
| 752 | } | ||
| 743 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); | 753 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); |
| 744 | if (firstseg) | 754 | if (firstseg) |
| 745 | SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); | 755 | SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); |
| @@ -480,7 +480,7 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, · 479 unmodified lines | |||
| 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 | ||
| @@ -611,6 +611,11 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, · 124 unmodified lines | |||
| 611 | PCI_DMA_TODEVICE); | 611 | PCI_DMA_TODEVICE); |
| 612 | u8 bw_40 = 0; | 612 | u8 bw_40 = 0; |
| 613 | 613 | ||
| 614 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { | ||
| 615 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
| 616 | "DMA mapping error"); | ||
| 617 | return; | ||
| 618 | } | ||
| 614 | if (mac->opmode == NL80211_IFTYPE_STATION) { | 619 | if (mac->opmode == NL80211_IFTYPE_STATION) { |
| 615 | bw_40 = mac->bw_40; | 620 | bw_40 = mac->bw_40; |
| 616 | } else if (mac->opmode == NL80211_IFTYPE_AP || | 621 | } else if (mac->opmode == NL80211_IFTYPE_AP || |
| @@ -763,6 +768,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, · 146 unmodified lines | |||
| 763 | void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, | 768 | void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, |
| 764 | bool firstseg, bool lastseg, struct sk_buff *skb) | 769 | bool firstseg, bool lastseg, struct sk_buff *skb) |
| 765 | { | 770 | { |
| 771 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 766 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 772 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
| 767 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 773 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 768 | struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb); | 774 | struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb); |
| @@ -770,7 +776,12 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, · 1 unmodified line | |||
| 770 | dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, | 776 | dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, |
| 771 | PCI_DMA_TODEVICE); | 777 | PCI_DMA_TODEVICE); |
| 772 | 778 | ||
| 773 | /* Clear all status */ | 779 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { |
| 780 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
| 781 | "DMA mapping error"); | ||
| 782 | return; | ||
| 783 | } | ||
| 784 | /* Clear all status */ | ||
| 774 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S); | 785 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S); |
| 775 | 786 | ||
| 776 | /* This bit indicate this packet is used for FW download. */ | 787 | /* This bit indicate this packet is used for FW download. */ |
| @@ -1106,7 +1106,7 @@ u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw) · 1105 unmodified lines | |||
| 1106 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | 1106 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { |
| 1107 | rtl8723ae_phy_sw_chnl_callback(hw); | 1107 | rtl8723ae_phy_sw_chnl_callback(hw); |
| 1108 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 1108 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
| 1109 | "sw_chnl_inprogress false schdule workitem\n"); | 1109 | "sw_chnl_inprogress false schedule workitem\n"); |
| 1110 | rtlphy->sw_chnl_inprogress = false; | 1110 | rtlphy->sw_chnl_inprogress = false; |
| 1111 | } else { | 1111 | } else { |
| 1112 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 1112 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
| @@ -247,7 +247,7 @@ static void _rtl8723ae_translate_rx_signal_stuff(struct ieee80211_hw *hw, · 246 unmodified lines | |||
| 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 | ||
| @@ -387,6 +387,11 @@ void rtl8723ae_tx_fill_desc(struct ieee80211_hw *hw, · 133 unmodified lines | |||
| 387 | PCI_DMA_TODEVICE); | 387 | PCI_DMA_TODEVICE); |
| 388 | u8 bw_40 = 0; | 388 | u8 bw_40 = 0; |
| 389 | 389 | ||
| 390 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { | ||
| 391 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
| 392 | "DMA mapping error"); | ||
| 393 | return; | ||
| 394 | } | ||
| 390 | if (mac->opmode == NL80211_IFTYPE_STATION) { | 395 | if (mac->opmode == NL80211_IFTYPE_STATION) { |
| 391 | bw_40 = mac->bw_40; | 396 | bw_40 = mac->bw_40; |
| 392 | } else if (mac->opmode == NL80211_IFTYPE_AP || | 397 | } else if (mac->opmode == NL80211_IFTYPE_AP || |
| @@ -542,6 +547,11 @@ void rtl8723ae_tx_fill_cmddesc(struct ieee80211_hw *hw, · 149 unmodified lines | |||
| 542 | PCI_DMA_TODEVICE); | 547 | PCI_DMA_TODEVICE); |
| 543 | __le16 fc = hdr->frame_control; | 548 | __le16 fc = hdr->frame_control; |
| 544 | 549 | ||
| 550 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { | ||
| 551 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
| 552 | "DMA mapping error"); | ||
| 553 | return; | ||
| 554 | } | ||
| 545 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); | 555 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); |
| 546 | 556 | ||
| 547 | if (firstseg) | 557 | if (firstseg) |
| @@ -210,17 +210,16 @@ static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, · 209 unmodified lines | |||
| 210 | u16 index = REALTEK_USB_VENQT_CMD_IDX; | 210 | u16 index = REALTEK_USB_VENQT_CMD_IDX; |
| 211 | int pipe = usb_sndctrlpipe(udev, 0); /* write_out */ | 211 | int pipe = usb_sndctrlpipe(udev, 0); /* write_out */ |
| 212 | u8 *buffer; | 212 | u8 *buffer; |
| 213 | dma_addr_t dma_addr; | ||
| 214 | 213 | ||
| 215 | wvalue = (u16)(addr&0x0000ffff); | 214 | wvalue = (u16)(addr & 0x0000ffff); |
| 216 | buffer = usb_alloc_coherent(udev, (size_t)len, GFP_ATOMIC, &dma_addr); | 215 | buffer = kmalloc(len, GFP_ATOMIC); |
| 217 | if (!buffer) | 216 | if (!buffer) |
| 218 | return; | 217 | return; |
| 219 | memcpy(buffer, data, len); | 218 | memcpy(buffer, data, len); |
| 220 | usb_control_msg(udev, pipe, request, reqtype, wvalue, | 219 | usb_control_msg(udev, pipe, request, reqtype, wvalue, |
| 221 | index, buffer, len, 50); | 220 | index, buffer, len, 50); |
| 222 | 221 | ||
| 223 | usb_free_coherent(udev, (size_t)len, buffer, dma_addr); | 222 | kfree(buffer); |
| 224 | } | 223 | } |
| 225 | 224 | ||
| 226 | static void _rtl_usb_io_handler_init(struct device *dev, | 225 | static void _rtl_usb_io_handler_init(struct device *dev, |
| @@ -640,6 +639,7 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw) · 413 unmodified lines | |||
| 640 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, | 639 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, |
| 641 | "Failed to prep_rx_urb!!\n"); | 640 | "Failed to prep_rx_urb!!\n"); |
| 642 | err = PTR_ERR(skb); | 641 | err = PTR_ERR(skb); |
| 642 | usb_free_urb(urb); | ||
| 643 | goto err_out; | 643 | goto err_out; |
| 644 | } | 644 | } |
| 645 | 645 | ||
| @@ -5,19 +5,6 @@ · 4 unmodified lines | |||
| 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 · 15 unmodified lines | |||
| 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 |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 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 | ||
| @@ -526,7 +526,7 @@ static int nfcwilink_probe(struct platform_device *pdev) · 525 unmodified lines | |||
| 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) · 9 unmodified lines | |||
| 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) · 12 unmodified lines | |||
| 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) · 13 unmodified lines | |||
| 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; |
| @@ -41,11 +41,6 @@ · 40 unmodified lines | |||
| 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); · 32 unmodified lines | |||
| 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); · 7 unmodified lines | |||
| 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); · 7 unmodified lines | |||
| 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); · 2 unmodified lines | |||
| 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[] = { · 141 unmodified lines | |||
| 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 { · 6 unmodified lines | |||
| 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 { · 16 unmodified lines | |||
| 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 { · 4 unmodified lines | |||
| 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 { · 14 unmodified lines | |||
| 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 { · 4 unmodified lines | |||
| 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) · 12 unmodified lines | |||
| 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) · 2 unmodified lines | |||
| 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) · 20 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 14 unmodified lines | |||
| 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) · 6 unmodified lines | |||
| 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) · 1 unmodified line | |||
| 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) · 6 unmodified lines | |||
| 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: · 4 unmodified lines | |||
| 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, · 34 unmodified lines | |||
| 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, · 8 unmodified lines | |||
| 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, · 51 unmodified lines | |||
| 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, · 23 unmodified lines | |||
| 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, · 4 unmodified lines | |||
| 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, · 52 unmodified lines | |||
| 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, · 3 unmodified lines | |||
| 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, · 1 unmodified line | |||
| 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) · 15 unmodified lines | |||
| 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, · 2 unmodified lines | |||
| 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, · 8 unmodified lines | |||
| 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 · 5 unmodified lines | |||
| 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 | ||
1210 more lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 141 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 141 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 110 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 127 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.