]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/uwb/i1480/i1480u-wlp/netdev.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[mirror_ubuntu-artful-kernel.git] / drivers / uwb / i1480 / i1480u-wlp / netdev.c
CommitLineData
a21b963a
IPG
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
5a0e3ad6 42#include <linux/slab.h>
a21b963a
IPG
43#include <linux/if_arp.h>
44#include <linux/etherdevice.h>
a01777ec 45
a21b963a
IPG
46#include "i1480u-wlp.h"
47
48struct 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
58static
59int 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 }
95error_cmd:
96 kfree(cmd);
97error_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? */
107static 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 */
144void 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 }
190out:
191 mutex_unlock(&i1480u->options.mutex);
192 return;
193}
194
195/**
196 *
197 * Called on 'ifconfig up'
198 */
199int 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;
e8e1594c
DV
211
212 result = uwb_radio_start(&wlp->pal);
213 if (result < 0)
214 goto error_radio_start;
215
a21b963a
IPG
216 netif_wake_queue(net_dev);
217#ifdef i1480u_FLOW_CONTROL
a419aef8 218 result = usb_submit_urb(i1480u->notif_urb, GFP_KERNEL);
a21b963a
IPG
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
a21b963a
IPG
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);
e8e1594c 228 goto error_wss_setup;
a21b963a
IPG
229 }
230 return 0;
e8e1594c 231error_wss_setup:
a21b963a 232#ifdef i1480u_FLOW_CONTROL
e8e1594c 233 usb_kill_urb(i1480u->notif_urb);
a21b963a
IPG
234error_notif_urb_submit:
235#endif
e8e1594c
DV
236 uwb_radio_stop(&wlp->pal);
237error_radio_start:
a21b963a
IPG
238 netif_stop_queue(net_dev);
239 i1480u_rx_release(i1480u);
240error_rx_setup:
241 return result;
242}
243
244
245/**
246 * Called on 'ifconfig down'
247 */
248int i1480u_stop(struct net_device *net_dev)
249{
250 struct i1480u *i1480u = netdev_priv(net_dev);
251 struct wlp *wlp = &i1480u->wlp;
a21b963a
IPG
252
253 BUG_ON(wlp->rc == NULL);
254 wlp_wss_remove(&wlp->wss);
a21b963a
IPG
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);
e8e1594c 260 uwb_radio_stop(&wlp->pal);
a21b963a
IPG
261 i1480u_rx_release(i1480u);
262 i1480u_tx_release(i1480u);
263 return 0;
264}
265
a21b963a
IPG
266/**
267 *
268 * Change the interface config--we probably don't have to do anything.
269 */
270int 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 */
282int 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
a21b963a
IPG
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 */
306void 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 */
325void 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}