diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-03-06 16:30:58 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-03-07 13:56:32 -0500 |
commit | 4bd14dd5f77bbe3c51f50f4e86d3b8960e6a518c (patch) | |
tree | 0dbf32e6fbf047035389a09b7b1124ca769a5551 /drivers/net/wireless/iwlwifi | |
parent | f47208934b2aba432722baeb86a72fcbfd26b593 (diff) |
iwlwifi: abstract out notification wait support
This will be sharable, but needs to live in the
op_mode as it is dependent on command processing.
Make a library out of the notification wait code.
Since I wrote all of the code originally and only
Intel employees changed it, we can also relicense
it to dual BSD/GPL.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-notif-wait.c | 157 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-notif-wait.h | 130 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-shared.h | 55 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-testmode.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-ucode.c | 81 |
10 files changed, 314 insertions, 160 deletions
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index f2a903d01aa..85d163ed3db 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -14,6 +14,7 @@ iwlwifi-objs += iwl-1000.o | |||
14 | iwlwifi-objs += iwl-2000.o | 14 | iwlwifi-objs += iwl-2000.o |
15 | iwlwifi-objs += iwl-pci.o | 15 | iwlwifi-objs += iwl-pci.o |
16 | iwlwifi-objs += iwl-drv.o | 16 | iwlwifi-objs += iwl-drv.o |
17 | iwlwifi-objs += iwl-notif-wait.o | ||
17 | iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o | 18 | iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o |
18 | 19 | ||
19 | iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 20 | iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 5c9c88b8609..f17142bb5df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c | |||
@@ -1142,9 +1142,7 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
1142 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; | 1142 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; |
1143 | 1143 | ||
1144 | /* set up notification wait support */ | 1144 | /* set up notification wait support */ |
1145 | spin_lock_init(&priv->shrd->notif_wait_lock); | 1145 | iwl_notification_wait_init(&priv->notif_wait); |
1146 | INIT_LIST_HEAD(&priv->shrd->notif_waits); | ||
1147 | init_waitqueue_head(&priv->shrd->notif_waitq); | ||
1148 | 1146 | ||
1149 | /* Set up BT Rx handlers */ | 1147 | /* Set up BT Rx handlers */ |
1150 | if (cfg(priv)->lib->bt_rx_handler_setup) | 1148 | if (cfg(priv)->lib->bt_rx_handler_setup) |
@@ -1164,25 +1162,7 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, | |||
1164 | * even if the RX handler consumes the RXB we have | 1162 | * even if the RX handler consumes the RXB we have |
1165 | * access to it in the notification wait entry. | 1163 | * access to it in the notification wait entry. |
1166 | */ | 1164 | */ |
1167 | if (!list_empty(&priv->shrd->notif_waits)) { | 1165 | iwl_notification_wait_notify(&priv->notif_wait, pkt); |
1168 | struct iwl_notification_wait *w; | ||
1169 | |||
1170 | spin_lock(&priv->shrd->notif_wait_lock); | ||
1171 | list_for_each_entry(w, &priv->shrd->notif_waits, list) { | ||
1172 | if (w->cmd != pkt->hdr.cmd) | ||
1173 | continue; | ||
1174 | IWL_DEBUG_RX(priv, | ||
1175 | "Notif: %s, 0x%02x - wake the callers up\n", | ||
1176 | get_cmd_string(pkt->hdr.cmd), | ||
1177 | pkt->hdr.cmd); | ||
1178 | w->triggered = true; | ||
1179 | if (w->fn) | ||
1180 | w->fn(priv, pkt, w->fn_data); | ||
1181 | } | ||
1182 | spin_unlock(&priv->shrd->notif_wait_lock); | ||
1183 | |||
1184 | wake_up_all(&priv->shrd->notif_waitq); | ||
1185 | } | ||
1186 | 1166 | ||
1187 | if (priv->pre_rx_handler && | 1167 | if (priv->pre_rx_handler && |
1188 | priv->shrd->ucode_owner == IWL_OWNERSHIP_TM) | 1168 | priv->shrd->ucode_owner == IWL_OWNERSHIP_TM) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index e191d394cfa..9d955fa387e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -60,9 +60,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, | |||
60 | u8 old_dev_type = send->dev_type; | 60 | u8 old_dev_type = send->dev_type; |
61 | int ret; | 61 | int ret; |
62 | 62 | ||
63 | iwl_init_notification_wait(priv->shrd, &disable_wait, | 63 | iwl_init_notification_wait(&priv->notif_wait, &disable_wait, |
64 | REPLY_WIPAN_DEACTIVATION_COMPLETE, | 64 | REPLY_WIPAN_DEACTIVATION_COMPLETE, |
65 | NULL, NULL); | 65 | NULL, NULL); |
66 | 66 | ||
67 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 67 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
68 | send->dev_type = RXON_DEV_TYPE_P2P; | 68 | send->dev_type = RXON_DEV_TYPE_P2P; |
@@ -74,9 +74,10 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, | |||
74 | 74 | ||
75 | if (ret) { | 75 | if (ret) { |
76 | IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); | 76 | IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); |
77 | iwl_remove_notification(priv->shrd, &disable_wait); | 77 | iwl_remove_notification(&priv->notif_wait, &disable_wait); |
78 | } else { | 78 | } else { |
79 | ret = iwl_wait_notification(priv->shrd, &disable_wait, HZ); | 79 | ret = iwl_wait_notification(&priv->notif_wait, |
80 | &disable_wait, HZ); | ||
80 | if (ret) | 81 | if (ret) |
81 | IWL_ERR(priv, "Timed out waiting for PAN disable\n"); | 82 | IWL_ERR(priv, "Timed out waiting for PAN disable\n"); |
82 | } | 83 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2422eef6d15..5f0e07c0b50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -845,7 +845,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
845 | /* Cancel currently queued command. */ | 845 | /* Cancel currently queued command. */ |
846 | clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); | 846 | clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); |
847 | 847 | ||
848 | iwl_abort_notification_waits(priv->shrd); | 848 | iwl_abort_notification_waits(&priv->notif_wait); |
849 | 849 | ||
850 | /* Keep the restart process from trying to send host | 850 | /* Keep the restart process from trying to send host |
851 | * commands by clearing the ready bit */ | 851 | * commands by clearing the ready bit */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 0c397fd635a..c57e605b26b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -51,6 +51,7 @@ | |||
51 | #include "iwl-trans.h" | 51 | #include "iwl-trans.h" |
52 | #include "iwl-shared.h" | 52 | #include "iwl-shared.h" |
53 | #include "iwl-op-mode.h" | 53 | #include "iwl-op-mode.h" |
54 | #include "iwl-notif-wait.h" | ||
54 | 55 | ||
55 | struct iwl_tx_queue; | 56 | struct iwl_tx_queue; |
56 | 57 | ||
@@ -739,6 +740,8 @@ struct iwl_priv { | |||
739 | struct iwl_rx_cmd_buffer *rxb, | 740 | struct iwl_rx_cmd_buffer *rxb, |
740 | struct iwl_device_cmd *cmd); | 741 | struct iwl_device_cmd *cmd); |
741 | 742 | ||
743 | struct iwl_notif_wait_data notif_wait; | ||
744 | |||
742 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | 745 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |
743 | 746 | ||
744 | /* spectrum measurement report caching */ | 747 | /* spectrum measurement report caching */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c new file mode 100644 index 00000000000..88dc4a0f96b --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | #include <linux/sched.h> | ||
64 | |||
65 | #include "iwl-notif-wait.h" | ||
66 | |||
67 | |||
68 | void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait) | ||
69 | { | ||
70 | spin_lock_init(¬if_wait->notif_wait_lock); | ||
71 | INIT_LIST_HEAD(¬if_wait->notif_waits); | ||
72 | init_waitqueue_head(¬if_wait->notif_waitq); | ||
73 | } | ||
74 | |||
75 | void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, | ||
76 | struct iwl_rx_packet *pkt) | ||
77 | { | ||
78 | if (!list_empty(¬if_wait->notif_waits)) { | ||
79 | struct iwl_notification_wait *w; | ||
80 | |||
81 | spin_lock(¬if_wait->notif_wait_lock); | ||
82 | list_for_each_entry(w, ¬if_wait->notif_waits, list) { | ||
83 | if (w->cmd != pkt->hdr.cmd) | ||
84 | continue; | ||
85 | w->triggered = true; | ||
86 | if (w->fn) | ||
87 | w->fn(notif_wait, pkt, w->fn_data); | ||
88 | } | ||
89 | spin_unlock(¬if_wait->notif_wait_lock); | ||
90 | |||
91 | wake_up_all(¬if_wait->notif_waitq); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) | ||
96 | { | ||
97 | unsigned long flags; | ||
98 | struct iwl_notification_wait *wait_entry; | ||
99 | |||
100 | spin_lock_irqsave(¬if_wait->notif_wait_lock, flags); | ||
101 | list_for_each_entry(wait_entry, ¬if_wait->notif_waits, list) | ||
102 | wait_entry->aborted = true; | ||
103 | spin_unlock_irqrestore(¬if_wait->notif_wait_lock, flags); | ||
104 | |||
105 | wake_up_all(¬if_wait->notif_waitq); | ||
106 | } | ||
107 | |||
108 | |||
109 | void | ||
110 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, | ||
111 | struct iwl_notification_wait *wait_entry, | ||
112 | u8 cmd, | ||
113 | void (*fn)(struct iwl_notif_wait_data *notif_wait, | ||
114 | struct iwl_rx_packet *pkt, void *data), | ||
115 | void *fn_data) | ||
116 | { | ||
117 | wait_entry->fn = fn; | ||
118 | wait_entry->fn_data = fn_data; | ||
119 | wait_entry->cmd = cmd; | ||
120 | wait_entry->triggered = false; | ||
121 | wait_entry->aborted = false; | ||
122 | |||
123 | spin_lock_bh(¬if_wait->notif_wait_lock); | ||
124 | list_add(&wait_entry->list, ¬if_wait->notif_waits); | ||
125 | spin_unlock_bh(¬if_wait->notif_wait_lock); | ||
126 | } | ||
127 | |||
128 | int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait, | ||
129 | struct iwl_notification_wait *wait_entry, | ||
130 | unsigned long timeout) | ||
131 | { | ||
132 | int ret; | ||
133 | |||
134 | ret = wait_event_timeout(notif_wait->notif_waitq, | ||
135 | wait_entry->triggered || wait_entry->aborted, | ||
136 | timeout); | ||
137 | |||
138 | spin_lock_bh(¬if_wait->notif_wait_lock); | ||
139 | list_del(&wait_entry->list); | ||
140 | spin_unlock_bh(¬if_wait->notif_wait_lock); | ||
141 | |||
142 | if (wait_entry->aborted) | ||
143 | return -EIO; | ||
144 | |||
145 | /* return value is always >= 0 */ | ||
146 | if (ret <= 0) | ||
147 | return -ETIMEDOUT; | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait, | ||
152 | struct iwl_notification_wait *wait_entry) | ||
153 | { | ||
154 | spin_lock_bh(¬if_wait->notif_wait_lock); | ||
155 | list_del(&wait_entry->list); | ||
156 | spin_unlock_bh(¬if_wait->notif_wait_lock); | ||
157 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h new file mode 100644 index 00000000000..419f1ad6544 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h | |||
@@ -0,0 +1,130 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * distribution. | ||
45 | * * Neither the name Intel Corporation nor the names of its | ||
46 | * contributors may be used to endorse or promote products derived | ||
47 | * from this software without specific prior written permission. | ||
48 | * | ||
49 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
50 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
51 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
52 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
53 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
54 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
55 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
56 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
57 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
58 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
59 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
60 | * | ||
61 | *****************************************************************************/ | ||
62 | #ifndef __iwl_notif_wait_h__ | ||
63 | #define __iwl_notif_wait_h__ | ||
64 | |||
65 | #include <linux/wait.h> | ||
66 | |||
67 | /* TODO: remove later */ | ||
68 | #include "iwl-commands.h" | ||
69 | |||
70 | struct iwl_notif_wait_data { | ||
71 | struct list_head notif_waits; | ||
72 | spinlock_t notif_wait_lock; | ||
73 | wait_queue_head_t notif_waitq; | ||
74 | }; | ||
75 | |||
76 | /** | ||
77 | * struct iwl_notification_wait - notification wait entry | ||
78 | * @list: list head for global list | ||
79 | * @fn: function called with the notification | ||
80 | * @cmd: command ID | ||
81 | * | ||
82 | * This structure is not used directly, to wait for a | ||
83 | * notification declare it on the stack, and call | ||
84 | * iwlagn_init_notification_wait() with appropriate | ||
85 | * parameters. Then do whatever will cause the ucode | ||
86 | * to notify the driver, and to wait for that then | ||
87 | * call iwlagn_wait_notification(). | ||
88 | * | ||
89 | * Each notification is one-shot. If at some point we | ||
90 | * need to support multi-shot notifications (which | ||
91 | * can't be allocated on the stack) we need to modify | ||
92 | * the code for them. | ||
93 | */ | ||
94 | struct iwl_notification_wait { | ||
95 | struct list_head list; | ||
96 | |||
97 | void (*fn)(struct iwl_notif_wait_data *notif_data, | ||
98 | struct iwl_rx_packet *pkt, void *data); | ||
99 | void *fn_data; | ||
100 | |||
101 | u8 cmd; | ||
102 | bool triggered, aborted; | ||
103 | }; | ||
104 | |||
105 | |||
106 | /* caller functions */ | ||
107 | void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_data); | ||
108 | void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_data, | ||
109 | struct iwl_rx_packet *pkt); | ||
110 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_data); | ||
111 | |||
112 | /* user functions */ | ||
113 | void __acquires(wait_entry) | ||
114 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_data, | ||
115 | struct iwl_notification_wait *wait_entry, | ||
116 | u8 cmd, | ||
117 | void (*fn)(struct iwl_notif_wait_data *notif_data, | ||
118 | struct iwl_rx_packet *pkt, void *data), | ||
119 | void *fn_data); | ||
120 | |||
121 | int __must_check __releases(wait_entry) | ||
122 | iwl_wait_notification(struct iwl_notif_wait_data *notif_data, | ||
123 | struct iwl_notification_wait *wait_entry, | ||
124 | unsigned long timeout); | ||
125 | |||
126 | void __releases(wait_entry) | ||
127 | iwl_remove_notification(struct iwl_notif_wait_data *notif_data, | ||
128 | struct iwl_notification_wait *wait_entry); | ||
129 | |||
130 | #endif /* __iwl_notif_wait_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 5a67fa14174..8ffc7607912 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h | |||
@@ -212,35 +212,6 @@ enum iwl_ucode_type { | |||
212 | }; | 212 | }; |
213 | 213 | ||
214 | /** | 214 | /** |
215 | * struct iwl_notification_wait - notification wait entry | ||
216 | * @list: list head for global list | ||
217 | * @fn: function called with the notification | ||
218 | * @cmd: command ID | ||
219 | * | ||
220 | * This structure is not used directly, to wait for a | ||
221 | * notification declare it on the stack, and call | ||
222 | * iwlagn_init_notification_wait() with appropriate | ||
223 | * parameters. Then do whatever will cause the ucode | ||
224 | * to notify the driver, and to wait for that then | ||
225 | * call iwlagn_wait_notification(). | ||
226 | * | ||
227 | * Each notification is one-shot. If at some point we | ||
228 | * need to support multi-shot notifications (which | ||
229 | * can't be allocated on the stack) we need to modify | ||
230 | * the code for them. | ||
231 | */ | ||
232 | struct iwl_notification_wait { | ||
233 | struct list_head list; | ||
234 | |||
235 | void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, | ||
236 | void *data); | ||
237 | void *fn_data; | ||
238 | |||
239 | u8 cmd; | ||
240 | bool triggered, aborted; | ||
241 | }; | ||
242 | |||
243 | /** | ||
244 | * enum iwl_pa_type - Power Amplifier type | 215 | * enum iwl_pa_type - Power Amplifier type |
245 | * @IWL_PA_SYSTEM: based on uCode configuration | 216 | * @IWL_PA_SYSTEM: based on uCode configuration |
246 | * @IWL_PA_INTERNAL: use Internal only | 217 | * @IWL_PA_INTERNAL: use Internal only |
@@ -400,9 +371,6 @@ struct iwl_cfg { | |||
400 | * @wait_command_queue: the wait_queue for SYNC host command nad uCode load | 371 | * @wait_command_queue: the wait_queue for SYNC host command nad uCode load |
401 | * @eeprom: pointer to the eeprom/OTP image | 372 | * @eeprom: pointer to the eeprom/OTP image |
402 | * @ucode_type: indicator of loaded ucode image | 373 | * @ucode_type: indicator of loaded ucode image |
403 | * @notif_waits: things waiting for notification | ||
404 | * @notif_wait_lock: lock protecting notification | ||
405 | * @notif_waitq: head of notification wait queue | ||
406 | * @device_pointers: pointers to ucode event tables | 374 | * @device_pointers: pointers to ucode event tables |
407 | */ | 375 | */ |
408 | struct iwl_shared { | 376 | struct iwl_shared { |
@@ -428,11 +396,6 @@ struct iwl_shared { | |||
428 | /* ucode related variables */ | 396 | /* ucode related variables */ |
429 | enum iwl_ucode_type ucode_type; | 397 | enum iwl_ucode_type ucode_type; |
430 | 398 | ||
431 | /* notification wait support */ | ||
432 | struct list_head notif_waits; | ||
433 | spinlock_t notif_wait_lock; | ||
434 | wait_queue_head_t notif_waitq; | ||
435 | |||
436 | struct { | 399 | struct { |
437 | u32 error_event_table; | 400 | u32 error_event_table; |
438 | u32 log_event_table; | 401 | u32 log_event_table; |
@@ -462,24 +425,6 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr); | |||
462 | void iwl_nic_config(struct iwl_priv *priv); | 425 | void iwl_nic_config(struct iwl_priv *priv); |
463 | const char *get_cmd_string(u8 cmd); | 426 | const char *get_cmd_string(u8 cmd); |
464 | 427 | ||
465 | /* notification wait support */ | ||
466 | void iwl_abort_notification_waits(struct iwl_shared *shrd); | ||
467 | void __acquires(wait_entry) | ||
468 | iwl_init_notification_wait(struct iwl_shared *shrd, | ||
469 | struct iwl_notification_wait *wait_entry, | ||
470 | u8 cmd, | ||
471 | void (*fn)(struct iwl_priv *priv, | ||
472 | struct iwl_rx_packet *pkt, | ||
473 | void *data), | ||
474 | void *fn_data); | ||
475 | int __must_check __releases(wait_entry) | ||
476 | iwl_wait_notification(struct iwl_shared *shrd, | ||
477 | struct iwl_notification_wait *wait_entry, | ||
478 | unsigned long timeout); | ||
479 | void __releases(wait_entry) | ||
480 | iwl_remove_notification(struct iwl_shared *shrd, | ||
481 | struct iwl_notification_wait *wait_entry); | ||
482 | |||
483 | #define IWL_CMD(x) case x: return #x | 428 | #define IWL_CMD(x) case x: return #x |
484 | 429 | ||
485 | /***************************************************** | 430 | /***************************************************** |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 095d71dc99c..cc049d22151 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c | |||
@@ -418,23 +418,23 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) | |||
418 | struct iwl_notification_wait calib_wait; | 418 | struct iwl_notification_wait calib_wait; |
419 | int ret; | 419 | int ret; |
420 | 420 | ||
421 | iwl_init_notification_wait(priv->shrd, &calib_wait, | 421 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, |
422 | CALIBRATION_COMPLETE_NOTIFICATION, | 422 | CALIBRATION_COMPLETE_NOTIFICATION, |
423 | NULL, NULL); | 423 | NULL, NULL); |
424 | ret = iwl_init_alive_start(priv); | 424 | ret = iwl_init_alive_start(priv); |
425 | if (ret) { | 425 | if (ret) { |
426 | IWL_ERR(priv, "Fail init calibration: %d\n", ret); | 426 | IWL_ERR(priv, "Fail init calibration: %d\n", ret); |
427 | goto cfg_init_calib_error; | 427 | goto cfg_init_calib_error; |
428 | } | 428 | } |
429 | 429 | ||
430 | ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ); | 430 | ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ); |
431 | if (ret) | 431 | if (ret) |
432 | IWL_ERR(priv, "Error detecting" | 432 | IWL_ERR(priv, "Error detecting" |
433 | " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); | 433 | " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); |
434 | return ret; | 434 | return ret; |
435 | 435 | ||
436 | cfg_init_calib_error: | 436 | cfg_init_calib_error: |
437 | iwl_remove_notification(priv->shrd, &calib_wait); | 437 | iwl_remove_notification(&priv->notif_wait, &calib_wait); |
438 | return ret; | 438 | return ret; |
439 | } | 439 | } |
440 | 440 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 686d456d226..4d34327f942 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c | |||
@@ -29,7 +29,6 @@ | |||
29 | 29 | ||
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/sched.h> | ||
33 | 32 | ||
34 | #include "iwl-dev.h" | 33 | #include "iwl-dev.h" |
35 | #include "iwl-core.h" | 34 | #include "iwl-core.h" |
@@ -434,10 +433,12 @@ struct iwl_alive_data { | |||
434 | u8 subtype; | 433 | u8 subtype; |
435 | }; | 434 | }; |
436 | 435 | ||
437 | static void iwl_alive_fn(struct iwl_priv *priv, | 436 | static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, |
438 | struct iwl_rx_packet *pkt, | 437 | struct iwl_rx_packet *pkt, |
439 | void *data) | 438 | void *data) |
440 | { | 439 | { |
440 | struct iwl_priv *priv = | ||
441 | container_of(notif_wait, struct iwl_priv, notif_wait); | ||
441 | struct iwl_alive_data *alive_data = data; | 442 | struct iwl_alive_data *alive_data = data; |
442 | struct iwl_alive_resp *palive; | 443 | struct iwl_alive_resp *palive; |
443 | 444 | ||
@@ -457,70 +458,6 @@ static void iwl_alive_fn(struct iwl_priv *priv, | |||
457 | alive_data->valid = palive->is_valid == UCODE_VALID_OK; | 458 | alive_data->valid = palive->is_valid == UCODE_VALID_OK; |
458 | } | 459 | } |
459 | 460 | ||
460 | /* notification wait support */ | ||
461 | void iwl_init_notification_wait(struct iwl_shared *shrd, | ||
462 | struct iwl_notification_wait *wait_entry, | ||
463 | u8 cmd, | ||
464 | void (*fn)(struct iwl_priv *priv, | ||
465 | struct iwl_rx_packet *pkt, | ||
466 | void *data), | ||
467 | void *fn_data) | ||
468 | { | ||
469 | wait_entry->fn = fn; | ||
470 | wait_entry->fn_data = fn_data; | ||
471 | wait_entry->cmd = cmd; | ||
472 | wait_entry->triggered = false; | ||
473 | wait_entry->aborted = false; | ||
474 | |||
475 | spin_lock_bh(&shrd->notif_wait_lock); | ||
476 | list_add(&wait_entry->list, &shrd->notif_waits); | ||
477 | spin_unlock_bh(&shrd->notif_wait_lock); | ||
478 | } | ||
479 | |||
480 | int iwl_wait_notification(struct iwl_shared *shrd, | ||
481 | struct iwl_notification_wait *wait_entry, | ||
482 | unsigned long timeout) | ||
483 | { | ||
484 | int ret; | ||
485 | |||
486 | ret = wait_event_timeout(shrd->notif_waitq, | ||
487 | wait_entry->triggered || wait_entry->aborted, | ||
488 | timeout); | ||
489 | |||
490 | spin_lock_bh(&shrd->notif_wait_lock); | ||
491 | list_del(&wait_entry->list); | ||
492 | spin_unlock_bh(&shrd->notif_wait_lock); | ||
493 | |||
494 | if (wait_entry->aborted) | ||
495 | return -EIO; | ||
496 | |||
497 | /* return value is always >= 0 */ | ||
498 | if (ret <= 0) | ||
499 | return -ETIMEDOUT; | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | void iwl_remove_notification(struct iwl_shared *shrd, | ||
504 | struct iwl_notification_wait *wait_entry) | ||
505 | { | ||
506 | spin_lock_bh(&shrd->notif_wait_lock); | ||
507 | list_del(&wait_entry->list); | ||
508 | spin_unlock_bh(&shrd->notif_wait_lock); | ||
509 | } | ||
510 | |||
511 | void iwl_abort_notification_waits(struct iwl_shared *shrd) | ||
512 | { | ||
513 | unsigned long flags; | ||
514 | struct iwl_notification_wait *wait_entry; | ||
515 | |||
516 | spin_lock_irqsave(&shrd->notif_wait_lock, flags); | ||
517 | list_for_each_entry(wait_entry, &shrd->notif_waits, list) | ||
518 | wait_entry->aborted = true; | ||
519 | spin_unlock_irqrestore(&shrd->notif_wait_lock, flags); | ||
520 | |||
521 | wake_up_all(&shrd->notif_waitq); | ||
522 | } | ||
523 | |||
524 | #define UCODE_ALIVE_TIMEOUT HZ | 461 | #define UCODE_ALIVE_TIMEOUT HZ |
525 | #define UCODE_CALIB_TIMEOUT (2*HZ) | 462 | #define UCODE_CALIB_TIMEOUT (2*HZ) |
526 | 463 | ||
@@ -540,13 +477,13 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
540 | if (!fw) | 477 | if (!fw) |
541 | return -EINVAL; | 478 | return -EINVAL; |
542 | 479 | ||
543 | iwl_init_notification_wait(priv->shrd, &alive_wait, REPLY_ALIVE, | 480 | iwl_init_notification_wait(&priv->notif_wait, &alive_wait, REPLY_ALIVE, |
544 | iwl_alive_fn, &alive_data); | 481 | iwl_alive_fn, &alive_data); |
545 | 482 | ||
546 | ret = iwl_trans_start_fw(trans(priv), fw); | 483 | ret = iwl_trans_start_fw(trans(priv), fw); |
547 | if (ret) { | 484 | if (ret) { |
548 | priv->shrd->ucode_type = old_type; | 485 | priv->shrd->ucode_type = old_type; |
549 | iwl_remove_notification(priv->shrd, &alive_wait); | 486 | iwl_remove_notification(&priv->notif_wait, &alive_wait); |
550 | return ret; | 487 | return ret; |
551 | } | 488 | } |
552 | 489 | ||
@@ -554,7 +491,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
554 | * Some things may run in the background now, but we | 491 | * Some things may run in the background now, but we |
555 | * just wait for the ALIVE notification here. | 492 | * just wait for the ALIVE notification here. |
556 | */ | 493 | */ |
557 | ret = iwl_wait_notification(priv->shrd, &alive_wait, | 494 | ret = iwl_wait_notification(&priv->notif_wait, &alive_wait, |
558 | UCODE_ALIVE_TIMEOUT); | 495 | UCODE_ALIVE_TIMEOUT); |
559 | if (ret) { | 496 | if (ret) { |
560 | priv->shrd->ucode_type = old_type; | 497 | priv->shrd->ucode_type = old_type; |
@@ -608,7 +545,7 @@ int iwl_run_init_ucode(struct iwl_priv *priv) | |||
608 | if (priv->shrd->ucode_type != IWL_UCODE_NONE) | 545 | if (priv->shrd->ucode_type != IWL_UCODE_NONE) |
609 | return 0; | 546 | return 0; |
610 | 547 | ||
611 | iwl_init_notification_wait(priv->shrd, &calib_wait, | 548 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, |
612 | CALIBRATION_COMPLETE_NOTIFICATION, | 549 | CALIBRATION_COMPLETE_NOTIFICATION, |
613 | NULL, NULL); | 550 | NULL, NULL); |
614 | 551 | ||
@@ -625,13 +562,13 @@ int iwl_run_init_ucode(struct iwl_priv *priv) | |||
625 | * Some things may run in the background now, but we | 562 | * Some things may run in the background now, but we |
626 | * just wait for the calibration complete notification. | 563 | * just wait for the calibration complete notification. |
627 | */ | 564 | */ |
628 | ret = iwl_wait_notification(priv->shrd, &calib_wait, | 565 | ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, |
629 | UCODE_CALIB_TIMEOUT); | 566 | UCODE_CALIB_TIMEOUT); |
630 | 567 | ||
631 | goto out; | 568 | goto out; |
632 | 569 | ||
633 | error: | 570 | error: |
634 | iwl_remove_notification(priv->shrd, &calib_wait); | 571 | iwl_remove_notification(&priv->notif_wait, &calib_wait); |
635 | out: | 572 | out: |
636 | /* Whatever happened, stop the device */ | 573 | /* Whatever happened, stop the device */ |
637 | iwl_trans_stop_device(trans(priv)); | 574 | iwl_trans_stop_device(trans(priv)); |