Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
00b3ed16 GKH |
2 | #include "hfa384x_usb.c" |
3 | #include "prism2mgmt.c" | |
4 | #include "prism2mib.c" | |
5 | #include "prism2sta.c" | |
76e3e7c4 | 6 | #include "prism2fw.c" |
00b3ed16 | 7 | |
bbb591a7 DP |
8 | #define PRISM_DEV(vid, pid, name) \ |
9 | { USB_DEVICE(vid, pid), \ | |
e2911905 | 10 | .driver_info = (unsigned long)name } |
00b3ed16 | 11 | |
71fa2cf9 | 12 | static const struct usb_device_id usb_prism_tbl[] = { |
bbb591a7 | 13 | PRISM_DEV(0x04bb, 0x0922, "IOData AirPort WN-B11/USBS"), |
5d7cf67f AS |
14 | PRISM_DEV(0x07aa, 0x0012, "Corega USB Wireless LAN Stick-11"), |
15 | PRISM_DEV(0x09aa, 0x3642, "Prism2.x 11Mbps USB WLAN Adapter"), | |
16 | PRISM_DEV(0x1668, 0x0408, "Actiontec Prism2.5 11Mbps USB WLAN Adapter"), | |
17 | PRISM_DEV(0x1668, 0x0421, "Actiontec Prism2.5 11Mbps USB WLAN Adapter"), | |
18 | PRISM_DEV(0x1915, 0x2236, "Linksys WUSB11v3.0 11Mbps USB WLAN Adapter"), | |
19 | PRISM_DEV(0x066b, 0x2212, "Linksys WUSB11v2.5 11Mbps USB WLAN Adapter"), | |
20 | PRISM_DEV(0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps USB WLAN Adapter"), | |
bbb591a7 | 21 | PRISM_DEV(0x0411, 0x0016, "Melco WLI-USB-S11 11Mbps WLAN Adapter"), |
5d7cf67f AS |
22 | PRISM_DEV(0x08de, 0x7a01, "PRISM25 USB IEEE 802.11 Mini Adapter"), |
23 | PRISM_DEV(0x8086, 0x1111, "Intel PRO/Wireless 2011B USB LAN Adapter"), | |
bbb591a7 | 24 | PRISM_DEV(0x0d8e, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter"), |
5d7cf67f | 25 | PRISM_DEV(0x045e, 0x006e, "Microsoft MN510 USB Wireless Adapter"), |
bbb591a7 DP |
26 | PRISM_DEV(0x0967, 0x0204, "Acer Warplink USB Adapter"), |
27 | PRISM_DEV(0x0cde, 0x0002, "Z-Com 725/726 Prism2.5 USB/USB Integrated"), | |
5d7cf67f AS |
28 | PRISM_DEV(0x0cde, 0x0005, "Z-Com Xl735 USB Wireless 802.11b Adapter"), |
29 | PRISM_DEV(0x413c, 0x8100, "Dell TrueMobile 1180 USB Wireless Adapter"), | |
30 | PRISM_DEV(0x0b3b, 0x1601, "ALLNET 0193 11Mbps USB WLAN Adapter"), | |
31 | PRISM_DEV(0x0b3b, 0x1602, "ZyXEL ZyAIR B200 USB Wireless Adapter"), | |
32 | PRISM_DEV(0x0baf, 0x00eb, "USRobotics USR1120 USB Wireless Adapter"), | |
bbb591a7 DP |
33 | PRISM_DEV(0x0411, 0x0027, "Melco WLI-USB-KS11G 11Mbps WLAN Adapter"), |
34 | PRISM_DEV(0x04f1, 0x3009, "JVC MP-XP7250 Builtin USB WLAN Adapter"), | |
35 | PRISM_DEV(0x0846, 0x4110, "NetGear MA111"), | |
36 | PRISM_DEV(0x03f3, 0x0020, "Adaptec AWN-8020 USB WLAN Adapter"), | |
5d7cf67f AS |
37 | PRISM_DEV(0x2821, 0x3300, "ASUS-WL140 / Hawking HighDB USB Wireless Adapter"), |
38 | PRISM_DEV(0x2001, 0x3700, "DWL-122 USB Wireless Adapter"), | |
39 | PRISM_DEV(0x2001, 0x3702, "DWL-120 Rev F USB Wireless Adapter"), | |
bbb591a7 | 40 | PRISM_DEV(0x50c2, 0x4013, "Averatec USB WLAN Adapter"), |
5d7cf67f AS |
41 | PRISM_DEV(0x2c02, 0x14ea, "Planex GW-US11H USB WLAN Adapter"), |
42 | PRISM_DEV(0x124a, 0x168b, "Airvast PRISM3 USB WLAN Adapter"), | |
bbb591a7 | 43 | PRISM_DEV(0x083a, 0x3503, "T-Sinus 111 USB WLAN Adapter"), |
bbb591a7 | 44 | PRISM_DEV(0x0411, 0x0044, "Melco WLI-USB-KB11 11Mbps WLAN Adapter"), |
5d7cf67f AS |
45 | PRISM_DEV(0x1668, 0x6106, "ROPEX FreeLan USB 802.11b Adapter"), |
46 | PRISM_DEV(0x124a, 0x4017, "Pheenet WL-503IA USB 802.11b Adapter"), | |
bbb591a7 | 47 | PRISM_DEV(0x0bb2, 0x0302, "Ambit Microsystems Corp."), |
5d7cf67f | 48 | PRISM_DEV(0x9016, 0x182d, "Sitecom WL-022 USB 802.11b Adapter"), |
bbb591a7 | 49 | PRISM_DEV(0x0543, 0x0f01, |
8d215ead | 50 | "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)"), |
bbb591a7 | 51 | PRISM_DEV(0x067c, 0x1022, |
5d7cf67f | 52 | "Siemens SpeedStream 1022 11Mbps USB WLAN Adapter"), |
bbb591a7 | 53 | PRISM_DEV(0x049f, 0x0033, |
8d215ead | 54 | "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter"), |
bbb591a7 | 55 | { } /* terminator */ |
00b3ed16 | 56 | }; |
00b3ed16 GKH |
57 | MODULE_DEVICE_TABLE(usb, usb_prism_tbl); |
58 | ||
f4ee0f42 MM |
59 | static int prism2sta_probe_usb(struct usb_interface *interface, |
60 | const struct usb_device_id *id) | |
00b3ed16 | 61 | { |
00b3ed16 | 62 | struct usb_device *dev; |
fea22e15 RK |
63 | struct usb_endpoint_descriptor *bulk_in, *bulk_out; |
64 | struct usb_host_interface *iface_desc = interface->cur_altsetting; | |
c9573a8d | 65 | struct wlandevice *wlandev = NULL; |
5a2214e2 | 66 | struct hfa384x *hw = NULL; |
f4ee0f42 | 67 | int result = 0; |
00b3ed16 | 68 | |
fea22e15 RK |
69 | result = usb_find_common_endpoints(iface_desc, &bulk_in, &bulk_out, NULL, NULL); |
70 | if (result) | |
faaff976 RK |
71 | goto failed; |
72 | ||
00b3ed16 | 73 | dev = interface_to_usbdev(interface); |
297f06ce | 74 | wlandev = create_wlan(); |
e2e77528 | 75 | if (!wlandev) { |
318e16b9 | 76 | dev_err(&interface->dev, "Memory allocation failure.\n"); |
00b3ed16 GKH |
77 | result = -EIO; |
78 | goto failed; | |
79 | } | |
80 | hw = wlandev->priv; | |
81 | ||
d03c075d | 82 | if (wlan_setup(wlandev, &interface->dev) != 0) { |
318e16b9 | 83 | dev_err(&interface->dev, "wlan_setup() failed.\n"); |
00b3ed16 GKH |
84 | result = -EIO; |
85 | goto failed; | |
86 | } | |
87 | ||
88 | /* Initialize the hw data */ | |
fea22e15 RK |
89 | hw->endp_in = usb_rcvbulkpipe(dev, bulk_in->bEndpointAddress); |
90 | hw->endp_out = usb_sndbulkpipe(dev, bulk_out->bEndpointAddress); | |
00b3ed16 GKH |
91 | hfa384x_create(hw, dev); |
92 | hw->wlandev = wlandev; | |
93 | ||
94 | /* Register the wlandev, this gets us a name and registers the | |
95 | * linux netdevice. | |
96 | */ | |
d03c075d | 97 | SET_NETDEV_DEV(wlandev->netdev, &interface->dev); |
00b3ed16 GKH |
98 | |
99 | /* Do a chip-level reset on the MAC */ | |
100 | if (prism2_doreset) { | |
101 | result = hfa384x_corereset(hw, | |
f4ee0f42 MM |
102 | prism2_reset_holdtime, |
103 | prism2_reset_settletime, 0); | |
00b3ed16 | 104 | if (result != 0) { |
00b3ed16 | 105 | result = -EIO; |
58612c60 DP |
106 | dev_err(&interface->dev, |
107 | "hfa384x_corereset() failed.\n"); | |
b76ed59f | 108 | goto failed_reset; |
00b3ed16 GKH |
109 | } |
110 | } | |
111 | ||
00b3ed16 | 112 | usb_get_dev(dev); |
00b3ed16 GKH |
113 | |
114 | wlandev->msdstate = WLAN_MSD_HWPRESENT; | |
115 | ||
76e3e7c4 KR |
116 | /* Try and load firmware, then enable card before we register */ |
117 | prism2_fwtry(dev, wlandev); | |
118 | prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable); | |
119 | ||
f4ee0f42 | 120 | if (register_wlandev(wlandev) != 0) { |
318e16b9 | 121 | dev_err(&interface->dev, "register_wlandev() failed.\n"); |
1d1b6985 | 122 | result = -EIO; |
b76ed59f | 123 | goto failed_register; |
f4ee0f42 | 124 | } |
1d1b6985 | 125 | |
00b3ed16 GKH |
126 | goto done; |
127 | ||
b76ed59f AK |
128 | failed_register: |
129 | usb_put_dev(dev); | |
130 | failed_reset: | |
131 | wlan_unsetup(wlandev); | |
f4ee0f42 | 132 | failed: |
7c98f718 MM |
133 | kfree(wlandev); |
134 | kfree(hw); | |
00b3ed16 GKH |
135 | wlandev = NULL; |
136 | ||
f4ee0f42 | 137 | done: |
00b3ed16 GKH |
138 | usb_set_intfdata(interface, wlandev); |
139 | return result; | |
00b3ed16 GKH |
140 | } |
141 | ||
f4ee0f42 | 142 | static void prism2sta_disconnect_usb(struct usb_interface *interface) |
00b3ed16 | 143 | { |
c9573a8d | 144 | struct wlandevice *wlandev; |
00b3ed16 | 145 | |
eaa4e501 | 146 | wlandev = usb_get_intfdata(interface); |
1f0c9efe | 147 | if (wlandev) { |
00b3ed16 | 148 | LIST_HEAD(cleanlist); |
a10d36b0 | 149 | struct hfa384x_usbctlx *ctlx, *temp; |
f4ee0f42 | 150 | unsigned long flags; |
00b3ed16 | 151 | |
5a2214e2 | 152 | struct hfa384x *hw = wlandev->priv; |
00b3ed16 GKH |
153 | |
154 | if (!hw) | |
155 | goto exit; | |
156 | ||
157 | spin_lock_irqsave(&hw->ctlxq.lock, flags); | |
158 | ||
159 | p80211netdev_hwremoved(wlandev); | |
160 | list_splice_init(&hw->ctlxq.reapable, &cleanlist); | |
161 | list_splice_init(&hw->ctlxq.completing, &cleanlist); | |
162 | list_splice_init(&hw->ctlxq.pending, &cleanlist); | |
163 | list_splice_init(&hw->ctlxq.active, &cleanlist); | |
164 | ||
165 | spin_unlock_irqrestore(&hw->ctlxq.lock, flags); | |
166 | ||
167 | /* There's no hardware to shutdown, but the driver | |
9442e81d DB |
168 | * might have some tasks that must be stopped before |
169 | * we can tear everything down. | |
00b3ed16 GKH |
170 | */ |
171 | prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); | |
172 | ||
292a089d SRG |
173 | timer_shutdown_sync(&hw->throttle); |
174 | timer_shutdown_sync(&hw->reqtimer); | |
175 | timer_shutdown_sync(&hw->resptimer); | |
00b3ed16 GKH |
176 | |
177 | /* Unlink all the URBs. This "removes the wheels" | |
178 | * from the entire CTLX handling mechanism. | |
179 | */ | |
180 | usb_kill_urb(&hw->rx_urb); | |
181 | usb_kill_urb(&hw->tx_urb); | |
182 | usb_kill_urb(&hw->ctlx_urb); | |
183 | ||
9442e81d | 184 | cancel_work_sync(&hw->completion_bh); |
cbe0f674 | 185 | cancel_work_sync(&hw->reaper_bh); |
00b3ed16 | 186 | |
5be2f42b AKC |
187 | cancel_work_sync(&hw->link_bh); |
188 | cancel_work_sync(&hw->commsqual_bh); | |
a1f165a6 | 189 | cancel_work_sync(&hw->usb_work); |
00b3ed16 GKH |
190 | |
191 | /* Now we complete any outstanding commands | |
192 | * and tell everyone who is waiting for their | |
193 | * responses that we have shut down. | |
194 | */ | |
57477bf0 | 195 | list_for_each_entry(ctlx, &cleanlist, list) |
00b3ed16 | 196 | complete(&ctlx->done); |
00b3ed16 GKH |
197 | |
198 | /* Give any outstanding synchronous commands | |
199 | * a chance to complete. All they need to do | |
200 | * is "wake up", so that's easy. | |
201 | * (I'd like a better way to do this, really.) | |
202 | */ | |
203 | msleep(100); | |
204 | ||
205 | /* Now delete the CTLXs, because no-one else can now. */ | |
57477bf0 | 206 | list_for_each_entry_safe(ctlx, temp, &cleanlist, list) |
00b3ed16 | 207 | kfree(ctlx); |
00b3ed16 GKH |
208 | |
209 | /* Unhook the wlandev */ | |
210 | unregister_wlandev(wlandev); | |
211 | wlan_unsetup(wlandev); | |
212 | ||
00b3ed16 | 213 | usb_put_dev(hw->usb); |
00b3ed16 GKH |
214 | |
215 | hfa384x_destroy(hw); | |
216 | kfree(hw); | |
217 | ||
218 | kfree(wlandev); | |
219 | } | |
220 | ||
f4ee0f42 | 221 | exit: |
00b3ed16 | 222 | usb_set_intfdata(interface, NULL); |
00b3ed16 GKH |
223 | } |
224 | ||
59497bba CF |
225 | #ifdef CONFIG_PM |
226 | static int prism2sta_suspend(struct usb_interface *interface, | |
8d215ead | 227 | pm_message_t message) |
59497bba | 228 | { |
5a2214e2 | 229 | struct hfa384x *hw = NULL; |
c9573a8d | 230 | struct wlandevice *wlandev; |
58612c60 | 231 | |
eaa4e501 | 232 | wlandev = usb_get_intfdata(interface); |
59497bba CF |
233 | if (!wlandev) |
234 | return -ENODEV; | |
235 | ||
236 | hw = wlandev->priv; | |
237 | if (!hw) | |
238 | return -ENODEV; | |
239 | ||
240 | prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable); | |
241 | ||
242 | usb_kill_urb(&hw->rx_urb); | |
243 | usb_kill_urb(&hw->tx_urb); | |
244 | usb_kill_urb(&hw->ctlx_urb); | |
245 | ||
246 | return 0; | |
247 | } | |
248 | ||
249 | static int prism2sta_resume(struct usb_interface *interface) | |
250 | { | |
251 | int result = 0; | |
5a2214e2 | 252 | struct hfa384x *hw = NULL; |
c9573a8d | 253 | struct wlandevice *wlandev; |
58612c60 | 254 | |
eaa4e501 | 255 | wlandev = usb_get_intfdata(interface); |
59497bba CF |
256 | if (!wlandev) |
257 | return -ENODEV; | |
258 | ||
259 | hw = wlandev->priv; | |
260 | if (!hw) | |
261 | return -ENODEV; | |
262 | ||
263 | /* Do a chip-level reset on the MAC */ | |
264 | if (prism2_doreset) { | |
265 | result = hfa384x_corereset(hw, | |
266 | prism2_reset_holdtime, | |
267 | prism2_reset_settletime, 0); | |
268 | if (result != 0) { | |
269 | unregister_wlandev(wlandev); | |
270 | hfa384x_destroy(hw); | |
318e16b9 | 271 | dev_err(&interface->dev, "hfa384x_corereset() failed.\n"); |
59497bba CF |
272 | kfree(wlandev); |
273 | kfree(hw); | |
274 | wlandev = NULL; | |
275 | return -ENODEV; | |
276 | } | |
277 | } | |
278 | ||
279 | prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable); | |
280 | ||
281 | return 0; | |
282 | } | |
283 | #else | |
284 | #define prism2sta_suspend NULL | |
285 | #define prism2sta_resume NULL | |
286 | #endif /* CONFIG_PM */ | |
287 | ||
00b3ed16 | 288 | static struct usb_driver prism2_usb_driver = { |
00b3ed16 GKH |
289 | .name = "prism2_usb", |
290 | .probe = prism2sta_probe_usb, | |
291 | .disconnect = prism2sta_disconnect_usb, | |
292 | .id_table = usb_prism_tbl, | |
59497bba CF |
293 | .suspend = prism2sta_suspend, |
294 | .resume = prism2sta_resume, | |
295 | .reset_resume = prism2sta_resume, | |
00b3ed16 GKH |
296 | /* fops, minor? */ |
297 | }; | |
298 | ||
bac2c126 | 299 | module_usb_driver(prism2_usb_driver); |