diff options
Diffstat (limited to 'drivers/uwb/i1480/i1480u-wlp/netdev.c')
-rw-r--r-- | drivers/uwb/i1480/i1480u-wlp/netdev.c | 331 |
1 files changed, 0 insertions, 331 deletions
diff --git a/drivers/uwb/i1480/i1480u-wlp/netdev.c b/drivers/uwb/i1480/i1480u-wlp/netdev.c deleted file mode 100644 index f98f6ce8b9e7..000000000000 --- a/drivers/uwb/i1480/i1480u-wlp/netdev.c +++ /dev/null | |||
@@ -1,331 +0,0 @@ | |||
1 | /* | ||
2 | * WUSB Wire Adapter: WLP interface | ||
3 | * Driver for the Linux Network stack. | ||
4 | * | ||
5 | * Copyright (C) 2005-2006 Intel Corporation | ||
6 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License version | ||
10 | * 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
20 | * 02110-1301, USA. | ||
21 | * | ||
22 | * | ||
23 | * FIXME: docs | ||
24 | * | ||
25 | * Implementation of the netdevice linkage (except tx and rx related stuff). | ||
26 | * | ||
27 | * ROADMAP: | ||
28 | * | ||
29 | * ENTRY POINTS (Net device): | ||
30 | * | ||
31 | * i1480u_open(): Called when we ifconfig up the interface; | ||
32 | * associates to a UWB host controller, reserves | ||
33 | * bandwidth (MAS), sets up RX USB URB and starts | ||
34 | * the queue. | ||
35 | * | ||
36 | * i1480u_stop(): Called when we ifconfig down a interface; | ||
37 | * reverses _open(). | ||
38 | * | ||
39 | * i1480u_set_config(): | ||
40 | */ | ||
41 | |||
42 | #include <linux/slab.h> | ||
43 | #include <linux/if_arp.h> | ||
44 | #include <linux/etherdevice.h> | ||
45 | |||
46 | #include "i1480u-wlp.h" | ||
47 | |||
48 | struct i1480u_cmd_set_ip_mas { | ||
49 | struct uwb_rccb rccb; | ||
50 | struct uwb_dev_addr addr; | ||
51 | u8 stream; | ||
52 | u8 owner; | ||
53 | u8 type; /* enum uwb_drp_type */ | ||
54 | u8 baMAS[32]; | ||
55 | } __attribute__((packed)); | ||
56 | |||
57 | |||
58 | static | ||
59 | int i1480u_set_ip_mas( | ||
60 | struct uwb_rc *rc, | ||
61 | const struct uwb_dev_addr *dstaddr, | ||
62 | u8 stream, u8 owner, u8 type, unsigned long *mas) | ||
63 | { | ||
64 | |||
65 | int result; | ||
66 | struct i1480u_cmd_set_ip_mas *cmd; | ||
67 | struct uwb_rc_evt_confirm reply; | ||
68 | |||
69 | result = -ENOMEM; | ||
70 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
71 | if (cmd == NULL) | ||
72 | goto error_kzalloc; | ||
73 | cmd->rccb.bCommandType = 0xfd; | ||
74 | cmd->rccb.wCommand = cpu_to_le16(0x000e); | ||
75 | cmd->addr = *dstaddr; | ||
76 | cmd->stream = stream; | ||
77 | cmd->owner = owner; | ||
78 | cmd->type = type; | ||
79 | if (mas == NULL) | ||
80 | memset(cmd->baMAS, 0x00, sizeof(cmd->baMAS)); | ||
81 | else | ||
82 | memcpy(cmd->baMAS, mas, sizeof(cmd->baMAS)); | ||
83 | reply.rceb.bEventType = 0xfd; | ||
84 | reply.rceb.wEvent = cpu_to_le16(0x000e); | ||
85 | result = uwb_rc_cmd(rc, "SET-IP-MAS", &cmd->rccb, sizeof(*cmd), | ||
86 | &reply.rceb, sizeof(reply)); | ||
87 | if (result < 0) | ||
88 | goto error_cmd; | ||
89 | if (reply.bResultCode != UWB_RC_RES_FAIL) { | ||
90 | dev_err(&rc->uwb_dev.dev, | ||
91 | "SET-IP-MAS: command execution failed: %d\n", | ||
92 | reply.bResultCode); | ||
93 | result = -EIO; | ||
94 | } | ||
95 | error_cmd: | ||
96 | kfree(cmd); | ||
97 | error_kzalloc: | ||
98 | return result; | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * Inform a WLP interface of a MAS reservation | ||
103 | * | ||
104 | * @rc is assumed refcnted. | ||
105 | */ | ||
106 | /* FIXME: detect if remote device is WLP capable? */ | ||
107 | static int i1480u_mas_set_dev(struct uwb_dev *uwb_dev, struct uwb_rc *rc, | ||
108 | u8 stream, u8 owner, u8 type, unsigned long *mas) | ||
109 | { | ||
110 | int result = 0; | ||
111 | struct device *dev = &rc->uwb_dev.dev; | ||
112 | |||
113 | result = i1480u_set_ip_mas(rc, &uwb_dev->dev_addr, stream, owner, | ||
114 | type, mas); | ||
115 | if (result < 0) { | ||
116 | char rcaddrbuf[UWB_ADDR_STRSIZE], devaddrbuf[UWB_ADDR_STRSIZE]; | ||
117 | uwb_dev_addr_print(rcaddrbuf, sizeof(rcaddrbuf), | ||
118 | &rc->uwb_dev.dev_addr); | ||
119 | uwb_dev_addr_print(devaddrbuf, sizeof(devaddrbuf), | ||
120 | &uwb_dev->dev_addr); | ||
121 | dev_err(dev, "Set IP MAS (%s to %s) failed: %d\n", | ||
122 | rcaddrbuf, devaddrbuf, result); | ||
123 | } | ||
124 | return result; | ||
125 | } | ||
126 | |||
127 | /** | ||
128 | * Called by bandwidth allocator when change occurs in reservation. | ||
129 | * | ||
130 | * @rsv: The reservation that is being established, modified, or | ||
131 | * terminated. | ||
132 | * | ||
133 | * When a reservation is established, modified, or terminated the upper layer | ||
134 | * (WLP here) needs set/update the currently available Media Access Slots | ||
135 | * that can be use for IP traffic. | ||
136 | * | ||
137 | * Our action taken during failure depends on how the reservation is being | ||
138 | * changed: | ||
139 | * - if reservation is being established we do nothing if we cannot set the | ||
140 | * new MAS to be used | ||
141 | * - if reservation is being terminated we revert back to PCA whether the | ||
142 | * SET IP MAS command succeeds or not. | ||
143 | */ | ||
144 | void i1480u_bw_alloc_cb(struct uwb_rsv *rsv) | ||
145 | { | ||
146 | int result = 0; | ||
147 | struct i1480u *i1480u = rsv->pal_priv; | ||
148 | struct device *dev = &i1480u->usb_iface->dev; | ||
149 | struct uwb_dev *target_dev = rsv->target.dev; | ||
150 | struct uwb_rc *rc = i1480u->wlp.rc; | ||
151 | u8 stream = rsv->stream; | ||
152 | int type = rsv->type; | ||
153 | int is_owner = rsv->owner == &rc->uwb_dev; | ||
154 | unsigned long *bmp = rsv->mas.bm; | ||
155 | |||
156 | dev_err(dev, "WLP callback called - sending set ip mas\n"); | ||
157 | /*user cannot change options while setting configuration*/ | ||
158 | mutex_lock(&i1480u->options.mutex); | ||
159 | switch (rsv->state) { | ||
160 | case UWB_RSV_STATE_T_ACCEPTED: | ||
161 | case UWB_RSV_STATE_O_ESTABLISHED: | ||
162 | result = i1480u_mas_set_dev(target_dev, rc, stream, is_owner, | ||
163 | type, bmp); | ||
164 | if (result < 0) { | ||
165 | dev_err(dev, "MAS reservation failed: %d\n", result); | ||
166 | goto out; | ||
167 | } | ||
168 | if (is_owner) { | ||
169 | wlp_tx_hdr_set_delivery_id_type(&i1480u->options.def_tx_hdr, | ||
170 | WLP_DRP | stream); | ||
171 | wlp_tx_hdr_set_rts_cts(&i1480u->options.def_tx_hdr, 0); | ||
172 | } | ||
173 | break; | ||
174 | case UWB_RSV_STATE_NONE: | ||
175 | /* revert back to PCA */ | ||
176 | result = i1480u_mas_set_dev(target_dev, rc, stream, is_owner, | ||
177 | type, bmp); | ||
178 | if (result < 0) | ||
179 | dev_err(dev, "MAS reservation failed: %d\n", result); | ||
180 | /* Revert to PCA even though SET IP MAS failed. */ | ||
181 | wlp_tx_hdr_set_delivery_id_type(&i1480u->options.def_tx_hdr, | ||
182 | i1480u->options.pca_base_priority); | ||
183 | wlp_tx_hdr_set_rts_cts(&i1480u->options.def_tx_hdr, 1); | ||
184 | break; | ||
185 | default: | ||
186 | dev_err(dev, "unexpected WLP reservation state: %s (%d).\n", | ||
187 | uwb_rsv_state_str(rsv->state), rsv->state); | ||
188 | break; | ||
189 | } | ||
190 | out: | ||
191 | mutex_unlock(&i1480u->options.mutex); | ||
192 | return; | ||
193 | } | ||
194 | |||
195 | /** | ||
196 | * | ||
197 | * Called on 'ifconfig up' | ||
198 | */ | ||
199 | int i1480u_open(struct net_device *net_dev) | ||
200 | { | ||
201 | int result; | ||
202 | struct i1480u *i1480u = netdev_priv(net_dev); | ||
203 | struct wlp *wlp = &i1480u->wlp; | ||
204 | struct uwb_rc *rc; | ||
205 | struct device *dev = &i1480u->usb_iface->dev; | ||
206 | |||
207 | rc = wlp->rc; | ||
208 | result = i1480u_rx_setup(i1480u); /* Alloc RX stuff */ | ||
209 | if (result < 0) | ||
210 | goto error_rx_setup; | ||
211 | |||
212 | result = uwb_radio_start(&wlp->pal); | ||
213 | if (result < 0) | ||
214 | goto error_radio_start; | ||
215 | |||
216 | netif_wake_queue(net_dev); | ||
217 | #ifdef i1480u_FLOW_CONTROL | ||
218 | result = usb_submit_urb(i1480u->notif_urb, GFP_KERNEL); | ||
219 | if (result < 0) { | ||
220 | dev_err(dev, "Can't submit notification URB: %d\n", result); | ||
221 | goto error_notif_urb_submit; | ||
222 | } | ||
223 | #endif | ||
224 | /* Interface is up with an address, now we can create WSS */ | ||
225 | result = wlp_wss_setup(net_dev, &wlp->wss); | ||
226 | if (result < 0) { | ||
227 | dev_err(dev, "Can't create WSS: %d. \n", result); | ||
228 | goto error_wss_setup; | ||
229 | } | ||
230 | return 0; | ||
231 | error_wss_setup: | ||
232 | #ifdef i1480u_FLOW_CONTROL | ||
233 | usb_kill_urb(i1480u->notif_urb); | ||
234 | error_notif_urb_submit: | ||
235 | #endif | ||
236 | uwb_radio_stop(&wlp->pal); | ||
237 | error_radio_start: | ||
238 | netif_stop_queue(net_dev); | ||
239 | i1480u_rx_release(i1480u); | ||
240 | error_rx_setup: | ||
241 | return result; | ||
242 | } | ||
243 | |||
244 | |||
245 | /** | ||
246 | * Called on 'ifconfig down' | ||
247 | */ | ||
248 | int i1480u_stop(struct net_device *net_dev) | ||
249 | { | ||
250 | struct i1480u *i1480u = netdev_priv(net_dev); | ||
251 | struct wlp *wlp = &i1480u->wlp; | ||
252 | |||
253 | BUG_ON(wlp->rc == NULL); | ||
254 | wlp_wss_remove(&wlp->wss); | ||
255 | netif_carrier_off(net_dev); | ||
256 | #ifdef i1480u_FLOW_CONTROL | ||
257 | usb_kill_urb(i1480u->notif_urb); | ||
258 | #endif | ||
259 | netif_stop_queue(net_dev); | ||
260 | uwb_radio_stop(&wlp->pal); | ||
261 | i1480u_rx_release(i1480u); | ||
262 | i1480u_tx_release(i1480u); | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * | ||
268 | * Change the interface config--we probably don't have to do anything. | ||
269 | */ | ||
270 | int i1480u_set_config(struct net_device *net_dev, struct ifmap *map) | ||
271 | { | ||
272 | int result; | ||
273 | struct i1480u *i1480u = netdev_priv(net_dev); | ||
274 | BUG_ON(i1480u->wlp.rc == NULL); | ||
275 | result = 0; | ||
276 | return result; | ||
277 | } | ||
278 | |||
279 | /** | ||
280 | * Change the MTU of the interface | ||
281 | */ | ||
282 | int i1480u_change_mtu(struct net_device *net_dev, int mtu) | ||
283 | { | ||
284 | static union { | ||
285 | struct wlp_tx_hdr tx; | ||
286 | struct wlp_rx_hdr rx; | ||
287 | } i1480u_all_hdrs; | ||
288 | |||
289 | if (mtu < ETH_HLEN) /* We encap eth frames */ | ||
290 | return -ERANGE; | ||
291 | if (mtu > 4000 - sizeof(i1480u_all_hdrs)) | ||
292 | return -ERANGE; | ||
293 | net_dev->mtu = mtu; | ||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | /** | ||
298 | * Stop the network queue | ||
299 | * | ||
300 | * Enable WLP substack to stop network queue. We also set the flow control | ||
301 | * threshold at this time to prevent the flow control from restarting the | ||
302 | * queue. | ||
303 | * | ||
304 | * we are loosing the current threshold value here ... FIXME? | ||
305 | */ | ||
306 | void i1480u_stop_queue(struct wlp *wlp) | ||
307 | { | ||
308 | struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp); | ||
309 | struct net_device *net_dev = i1480u->net_dev; | ||
310 | i1480u->tx_inflight.threshold = 0; | ||
311 | netif_stop_queue(net_dev); | ||
312 | } | ||
313 | |||
314 | /** | ||
315 | * Start the network queue | ||
316 | * | ||
317 | * Enable WLP substack to start network queue. Also re-enable the flow | ||
318 | * control to manage the queue again. | ||
319 | * | ||
320 | * We re-enable the flow control by storing the default threshold in the | ||
321 | * flow control threshold. This means that if the user modified the | ||
322 | * threshold before the queue was stopped and restarted that information | ||
323 | * will be lost. FIXME? | ||
324 | */ | ||
325 | void i1480u_start_queue(struct wlp *wlp) | ||
326 | { | ||
327 | struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp); | ||
328 | struct net_device *net_dev = i1480u->net_dev; | ||
329 | i1480u->tx_inflight.threshold = i1480u_TX_INFLIGHT_THRESHOLD; | ||
330 | netif_start_queue(net_dev); | ||
331 | } | ||