aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@csr.com>2010-10-25 08:57:32 -0400
committerDavid Vrabel <david.vrabel@csr.com>2010-10-25 09:03:45 -0400
commit446396bfab00392010ebc36b9ccf859935b0f17b (patch)
tree7612ca4ed9f6cbd9e4341e7c3deae1634d3d87d8
parent229aebb873e29726b91e076161649cf45154b0bf (diff)
uwb: Remove the WLP subsystem and drivers
The only Wimedia LLC Protocol (WLP) hardware was an Intel i1480 chip with a beta release of firmware that was never commercially available as a product. This hardware and firmware is no longer available as Intel sold their UWB/WLP IP. I also see little prospect of other WLP capable hardware ever being available. Signed-off-by: David Vrabel <david.vrabel@csr.com>
-rw-r--r--MAINTAINERS12
-rw-r--r--drivers/uwb/Kconfig20
-rw-r--r--drivers/uwb/Makefile1
-rw-r--r--drivers/uwb/i1480/Makefile1
-rw-r--r--drivers/uwb/i1480/i1480-wlp.h200
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/Makefile8
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h283
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/lc.c424
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/netdev.c331
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/rx.c474
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/sysfs.c407
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/tx.c584
-rw-r--r--drivers/uwb/wlp/Makefile10
-rw-r--r--drivers/uwb/wlp/driver.c43
-rw-r--r--drivers/uwb/wlp/eda.c415
-rw-r--r--drivers/uwb/wlp/messages.c1798
-rw-r--r--drivers/uwb/wlp/sysfs.c708
-rw-r--r--drivers/uwb/wlp/txrx.c354
-rw-r--r--drivers/uwb/wlp/wlp-internal.h224
-rw-r--r--drivers/uwb/wlp/wlp-lc.c560
-rw-r--r--drivers/uwb/wlp/wss-lc.c959
-rw-r--r--include/linux/wlp.h736
22 files changed, 1 insertions, 8551 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 69aa8fe060b3..3a3df3f28d37 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5995,9 +5995,6 @@ M: David Vrabel <david.vrabel@csr.com>
5995L: linux-usb@vger.kernel.org 5995L: linux-usb@vger.kernel.org
5996S: Supported 5996S: Supported
5997F: drivers/uwb/ 5997F: drivers/uwb/
5998X: drivers/uwb/wlp/
5999X: drivers/uwb/i1480/i1480u-wlp/
6000X: drivers/uwb/i1480/i1480-wlp.h
6001F: include/linux/uwb.h 5998F: include/linux/uwb.h
6002F: include/linux/uwb/ 5999F: include/linux/uwb/
6003 6000
@@ -6533,15 +6530,6 @@ F: include/linux/wimax/debug.h
6533F: include/net/wimax.h 6530F: include/net/wimax.h
6534F: net/wimax/ 6531F: net/wimax/
6535 6532
6536WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM
6537M: David Vrabel <david.vrabel@csr.com>
6538L: netdev@vger.kernel.org
6539S: Maintained
6540F: include/linux/wlp.h
6541F: drivers/uwb/wlp/
6542F: drivers/uwb/i1480/i1480u-wlp/
6543F: drivers/uwb/i1480/i1480-wlp.h
6544
6545WISTRON LAPTOP BUTTON DRIVER 6533WISTRON LAPTOP BUTTON DRIVER
6546M: Miloslav Trmac <mitr@volny.cz> 6534M: Miloslav Trmac <mitr@volny.cz>
6547S: Maintained 6535S: Maintained
diff --git a/drivers/uwb/Kconfig b/drivers/uwb/Kconfig
index bac8e7a6f17b..d100f54ed650 100644
--- a/drivers/uwb/Kconfig
+++ b/drivers/uwb/Kconfig
@@ -12,8 +12,7 @@ menuconfig UWB
12 technology using a wide spectrum (3.1-10.6GHz). It is 12 technology using a wide spectrum (3.1-10.6GHz). It is
13 optimized for in-room use (480Mbps at 2 meters, 110Mbps at 13 optimized for in-room use (480Mbps at 2 meters, 110Mbps at
14 10m). It serves as the transport layer for other protocols, 14 10m). It serves as the transport layer for other protocols,
15 such as Wireless USB (WUSB), IP (WLP) and upcoming 15 such as Wireless USB (WUSB).
16 Bluetooth and 1394
17 16
18 The topology is peer to peer; however, higher level 17 The topology is peer to peer; however, higher level
19 protocols (such as WUSB) might impose a master/slave 18 protocols (such as WUSB) might impose a master/slave
@@ -58,13 +57,6 @@ config UWB_WHCI
58 To compile this driver select Y (built in) or M (module). It 57 To compile this driver select Y (built in) or M (module). It
59 is safe to select any even if you do not have the hardware. 58 is safe to select any even if you do not have the hardware.
60 59
61config UWB_WLP
62 tristate "Support WiMedia Link Protocol (Ethernet/IP over UWB)"
63 depends on UWB && NET
64 help
65 This is a common library for drivers that implement
66 networking over UWB.
67
68config UWB_I1480U 60config UWB_I1480U
69 tristate "Support for Intel Wireless UWB Link 1480 HWA" 61 tristate "Support for Intel Wireless UWB Link 1480 HWA"
70 depends on UWB_HWA 62 depends on UWB_HWA
@@ -77,14 +69,4 @@ config UWB_I1480U
77 To compile this driver select Y (built in) or M (module). It 69 To compile this driver select Y (built in) or M (module). It
78 is safe to select any even if you do not have the hardware. 70 is safe to select any even if you do not have the hardware.
79 71
80config UWB_I1480U_WLP
81 tristate "Support for Intel Wireless UWB Link 1480 HWA's WLP interface"
82 depends on UWB_I1480U && UWB_WLP && NET
83 help
84 This driver enables WLP support for the i1480 when connected via
85 USB. WLP is the WiMedia Link Protocol, or IP over UWB.
86
87 To compile this driver select Y (built in) or M (module). It
88 is safe to select any even if you don't have the hardware.
89
90endif # UWB 72endif # UWB
diff --git a/drivers/uwb/Makefile b/drivers/uwb/Makefile
index 2f98d080fe78..d47dd6e2942c 100644
--- a/drivers/uwb/Makefile
+++ b/drivers/uwb/Makefile
@@ -1,5 +1,4 @@
1obj-$(CONFIG_UWB) += uwb.o 1obj-$(CONFIG_UWB) += uwb.o
2obj-$(CONFIG_UWB_WLP) += wlp/
3obj-$(CONFIG_UWB_WHCI) += umc.o whci.o whc-rc.o 2obj-$(CONFIG_UWB_WHCI) += umc.o whci.o whc-rc.o
4obj-$(CONFIG_UWB_HWA) += hwa-rc.o 3obj-$(CONFIG_UWB_HWA) += hwa-rc.o
5obj-$(CONFIG_UWB_I1480U) += i1480/ 4obj-$(CONFIG_UWB_I1480U) += i1480/
diff --git a/drivers/uwb/i1480/Makefile b/drivers/uwb/i1480/Makefile
index 212bbc7d4c32..d69da1684cfb 100644
--- a/drivers/uwb/i1480/Makefile
+++ b/drivers/uwb/i1480/Makefile
@@ -1,2 +1 @@
1obj-$(CONFIG_UWB_I1480U) += dfu/ i1480-est.o obj-$(CONFIG_UWB_I1480U) += dfu/ i1480-est.o
2obj-$(CONFIG_UWB_I1480U_WLP) += i1480u-wlp/
diff --git a/drivers/uwb/i1480/i1480-wlp.h b/drivers/uwb/i1480/i1480-wlp.h
deleted file mode 100644
index 18a8b0e4567b..000000000000
--- a/drivers/uwb/i1480/i1480-wlp.h
+++ /dev/null
@@ -1,200 +0,0 @@
1/*
2 * Intel 1480 Wireless UWB Link
3 * WLP specific definitions
4 *
5 *
6 * Copyright (C) 2005-2006 Intel Corporation
7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 *
23 *
24 * FIXME: docs
25 */
26
27#ifndef __i1480_wlp_h__
28#define __i1480_wlp_h__
29
30#include <linux/spinlock.h>
31#include <linux/list.h>
32#include <linux/uwb.h>
33#include <linux/if_ether.h>
34#include <asm/byteorder.h>
35
36/* New simplified header format? */
37#undef WLP_HDR_FMT_2 /* FIXME: rename */
38
39/**
40 * Values of the Delivery ID & Type field when PCA or DRP
41 *
42 * The Delivery ID & Type field in the WLP TX header indicates whether
43 * the frame is PCA or DRP. This is done based on the high level bit of
44 * this field.
45 * We use this constant to test if the traffic is PCA or DRP as follows:
46 * if (wlp_tx_hdr_delivery_id_type(wlp_tx_hdr) & WLP_DRP)
47 * this is DRP traffic
48 * else
49 * this is PCA traffic
50 */
51enum deliver_id_type_bit {
52 WLP_DRP = 8,
53};
54
55/**
56 * WLP TX header
57 *
58 * Indicates UWB/WLP-specific transmission parameters for a network
59 * packet.
60 */
61struct wlp_tx_hdr {
62 /* dword 0 */
63 struct uwb_dev_addr dstaddr;
64 u8 key_index;
65 u8 mac_params;
66 /* dword 1 */
67 u8 phy_params;
68#ifndef WLP_HDR_FMT_2
69 u8 reserved;
70 __le16 oui01; /* FIXME: not so sure if __le16 or u8[2] */
71 /* dword 2 */
72 u8 oui2; /* if all LE, it could be merged */
73 __le16 prid;
74#endif
75} __attribute__((packed));
76
77static inline int wlp_tx_hdr_delivery_id_type(const struct wlp_tx_hdr *hdr)
78{
79 return hdr->mac_params & 0x0f;
80}
81
82static inline int wlp_tx_hdr_ack_policy(const struct wlp_tx_hdr *hdr)
83{
84 return (hdr->mac_params >> 4) & 0x07;
85}
86
87static inline int wlp_tx_hdr_rts_cts(const struct wlp_tx_hdr *hdr)
88{
89 return (hdr->mac_params >> 7) & 0x01;
90}
91
92static inline void wlp_tx_hdr_set_delivery_id_type(struct wlp_tx_hdr *hdr, int id)
93{
94 hdr->mac_params = (hdr->mac_params & ~0x0f) | id;
95}
96
97static inline void wlp_tx_hdr_set_ack_policy(struct wlp_tx_hdr *hdr,
98 enum uwb_ack_pol policy)
99{
100 hdr->mac_params = (hdr->mac_params & ~0x70) | (policy << 4);
101}
102
103static inline void wlp_tx_hdr_set_rts_cts(struct wlp_tx_hdr *hdr, int rts_cts)
104{
105 hdr->mac_params = (hdr->mac_params & ~0x80) | (rts_cts << 7);
106}
107
108static inline enum uwb_phy_rate wlp_tx_hdr_phy_rate(const struct wlp_tx_hdr *hdr)
109{
110 return hdr->phy_params & 0x0f;
111}
112
113static inline int wlp_tx_hdr_tx_power(const struct wlp_tx_hdr *hdr)
114{
115 return (hdr->phy_params >> 4) & 0x0f;
116}
117
118static inline void wlp_tx_hdr_set_phy_rate(struct wlp_tx_hdr *hdr, enum uwb_phy_rate rate)
119{
120 hdr->phy_params = (hdr->phy_params & ~0x0f) | rate;
121}
122
123static inline void wlp_tx_hdr_set_tx_power(struct wlp_tx_hdr *hdr, int pwr)
124{
125 hdr->phy_params = (hdr->phy_params & ~0xf0) | (pwr << 4);
126}
127
128
129/**
130 * WLP RX header
131 *
132 * Provides UWB/WLP-specific transmission data for a received
133 * network packet.
134 */
135struct wlp_rx_hdr {
136 /* dword 0 */
137 struct uwb_dev_addr dstaddr;
138 struct uwb_dev_addr srcaddr;
139 /* dword 1 */
140 u8 LQI;
141 s8 RSSI;
142 u8 reserved3;
143#ifndef WLP_HDR_FMT_2
144 u8 oui0;
145 /* dword 2 */
146 __le16 oui12;
147 __le16 prid;
148#endif
149} __attribute__((packed));
150
151
152/** User configurable options for WLP */
153struct wlp_options {
154 struct mutex mutex; /* access to user configurable options*/
155 struct wlp_tx_hdr def_tx_hdr; /* default tx hdr */
156 u8 pca_base_priority;
157 u8 bw_alloc; /*index into bw_allocs[] for PCA/DRP reservations*/
158};
159
160
161static inline
162void wlp_options_init(struct wlp_options *options)
163{
164 mutex_init(&options->mutex);
165 wlp_tx_hdr_set_ack_policy(&options->def_tx_hdr, UWB_ACK_INM);
166 wlp_tx_hdr_set_rts_cts(&options->def_tx_hdr, 1);
167 /* FIXME: default to phy caps */
168 wlp_tx_hdr_set_phy_rate(&options->def_tx_hdr, UWB_PHY_RATE_480);
169#ifndef WLP_HDR_FMT_2
170 options->def_tx_hdr.prid = cpu_to_le16(0x0000);
171#endif
172}
173
174
175/* sysfs helpers */
176
177extern ssize_t uwb_pca_base_priority_store(struct wlp_options *,
178 const char *, size_t);
179extern ssize_t uwb_pca_base_priority_show(const struct wlp_options *, char *);
180extern ssize_t uwb_bw_alloc_store(struct wlp_options *, const char *, size_t);
181extern ssize_t uwb_bw_alloc_show(const struct wlp_options *, char *);
182extern ssize_t uwb_ack_policy_store(struct wlp_options *,
183 const char *, size_t);
184extern ssize_t uwb_ack_policy_show(const struct wlp_options *, char *);
185extern ssize_t uwb_rts_cts_store(struct wlp_options *, const char *, size_t);
186extern ssize_t uwb_rts_cts_show(const struct wlp_options *, char *);
187extern ssize_t uwb_phy_rate_store(struct wlp_options *, const char *, size_t);
188extern ssize_t uwb_phy_rate_show(const struct wlp_options *, char *);
189
190
191/** Simple bandwidth allocation (temporary and too simple) */
192struct wlp_bw_allocs {
193 const char *name;
194 struct {
195 u8 mask, stream;
196 } tx, rx;
197};
198
199
200#endif /* #ifndef __i1480_wlp_h__ */
diff --git a/drivers/uwb/i1480/i1480u-wlp/Makefile b/drivers/uwb/i1480/i1480u-wlp/Makefile
deleted file mode 100644
index fe6709b8e68b..000000000000
--- a/drivers/uwb/i1480/i1480u-wlp/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
1obj-$(CONFIG_UWB_I1480U_WLP) += i1480u-wlp.o
2
3i1480u-wlp-objs := \
4 lc.o \
5 netdev.o \
6 rx.o \
7 sysfs.o \
8 tx.o
diff --git a/drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h b/drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h
deleted file mode 100644
index 2e31f536a347..000000000000
--- a/drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h
+++ /dev/null
@@ -1,283 +0,0 @@
1/*
2 * Intel 1480 Wireless UWB Link USB
3 * Header formats, constants, general internal interfaces
4 *
5 *
6 * Copyright (C) 2005-2006 Intel Corporation
7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 *
23 *
24 * This is not an standard interface.
25 *
26 * FIXME: docs
27 *
28 * i1480u-wlp is pretty simple: two endpoints, one for tx, one for
29 * rx. rx is polled. Network packets (ethernet, whatever) are wrapped
30 * in i1480 TX or RX headers (for sending over the air), and these
31 * packets are wrapped in UNTD headers (for sending to the WLP UWB
32 * controller).
33 *
34 * UNTD packets (UNTD hdr + i1480 hdr + network packet) packets
35 * cannot be bigger than i1480u_MAX_FRG_SIZE. When this happens, the
36 * i1480 packet is broken in chunks/packets:
37 *
38 * UNTD-1st.hdr + i1480.hdr + payload
39 * UNTD-next.hdr + payload
40 * ...
41 * UNTD-last.hdr + payload
42 *
43 * so that each packet is smaller or equal than i1480u_MAX_FRG_SIZE.
44 *
45 * All HW structures and bitmaps are little endian, so we need to play
46 * ugly tricks when defining bitfields. Hoping for the day GCC
47 * implements __attribute__((endian(1234))).
48 *
49 * FIXME: ROADMAP to the whole implementation
50 */
51
52#ifndef __i1480u_wlp_h__
53#define __i1480u_wlp_h__
54
55#include <linux/usb.h>
56#include <linux/netdevice.h>
57#include <linux/uwb.h> /* struct uwb_rc, struct uwb_notifs_handler */
58#include <linux/wlp.h>
59#include "../i1480-wlp.h"
60
61#undef i1480u_FLOW_CONTROL /* Enable flow control code */
62
63/**
64 * Basic flow control
65 */
66enum {
67 i1480u_TX_INFLIGHT_MAX = 1000,
68 i1480u_TX_INFLIGHT_THRESHOLD = 100,
69};
70
71/** Maximum size of a transaction that we can tx/rx */
72enum {
73 /* Maximum packet size computed as follows: max UNTD header (8) +
74 * i1480 RX header (8) + max Ethernet header and payload (4096) +
75 * Padding added by skb_reserve (2) to make post Ethernet payload
76 * start on 16 byte boundary*/
77 i1480u_MAX_RX_PKT_SIZE = 4114,
78 i1480u_MAX_FRG_SIZE = 512,
79 i1480u_RX_BUFS = 9,
80};
81
82
83/**
84 * UNTD packet type
85 *
86 * We need to fragment any payload whose UNTD packet is going to be
87 * bigger than i1480u_MAX_FRG_SIZE.
88 */
89enum i1480u_pkt_type {
90 i1480u_PKT_FRAG_1ST = 0x1,
91 i1480u_PKT_FRAG_NXT = 0x0,
92 i1480u_PKT_FRAG_LST = 0x2,
93 i1480u_PKT_FRAG_CMP = 0x3
94};
95enum {
96 i1480u_PKT_NONE = 0x4,
97};
98
99/** USB Network Transfer Descriptor - common */
100struct untd_hdr {
101 u8 type;
102 __le16 len;
103} __attribute__((packed));
104
105static inline enum i1480u_pkt_type untd_hdr_type(const struct untd_hdr *hdr)
106{
107 return hdr->type & 0x03;
108}
109
110static inline int untd_hdr_rx_tx(const struct untd_hdr *hdr)
111{
112 return (hdr->type >> 2) & 0x01;
113}
114
115static inline void untd_hdr_set_type(struct untd_hdr *hdr, enum i1480u_pkt_type type)
116{
117 hdr->type = (hdr->type & ~0x03) | type;
118}
119
120static inline void untd_hdr_set_rx_tx(struct untd_hdr *hdr, int rx_tx)
121{
122 hdr->type = (hdr->type & ~0x04) | (rx_tx << 2);
123}
124
125
126/**
127 * USB Network Transfer Descriptor - Complete Packet
128 *
129 * This is for a packet that is smaller (header + payload) than
130 * i1480u_MAX_FRG_SIZE.
131 *
132 * @hdr.total_len is the size of the payload; the payload doesn't
133 * count this header nor the padding, but includes the size of i1480
134 * header.
135 */
136struct untd_hdr_cmp {
137 struct untd_hdr hdr;
138 u8 padding;
139} __attribute__((packed));
140
141
142/**
143 * USB Network Transfer Descriptor - First fragment
144 *
145 * @hdr.len is the size of the *whole packet* (excluding UNTD
146 * headers); @fragment_len is the size of the payload (excluding UNTD
147 * headers, but including i1480 headers).
148 */
149struct untd_hdr_1st {
150 struct untd_hdr hdr;
151 __le16 fragment_len;
152 u8 padding[3];
153} __attribute__((packed));
154
155
156/**
157 * USB Network Transfer Descriptor - Next / Last [Rest]
158 *
159 * @hdr.len is the size of the payload, not including headrs.
160 */
161struct untd_hdr_rst {
162 struct untd_hdr hdr;
163 u8 padding;
164} __attribute__((packed));
165
166
167/**
168 * Transmission context
169 *
170 * Wraps all the stuff needed to track a pending/active tx
171 * operation.
172 */
173struct i1480u_tx {
174 struct list_head list_node;
175 struct i1480u *i1480u;
176 struct urb *urb;
177
178 struct sk_buff *skb;
179 struct wlp_tx_hdr *wlp_tx_hdr;
180
181 void *buf; /* if NULL, no new buf was used */
182 size_t buf_size;
183};
184
185/**
186 * Basic flow control
187 *
188 * We maintain a basic flow control counter. "count" how many TX URBs are
189 * outstanding. Only allow "max"
190 * TX URBs to be outstanding. If this value is reached the queue will be
191 * stopped. The queue will be restarted when there are
192 * "threshold" URBs outstanding.
193 * Maintain a counter of how many time the TX queue needed to be restarted
194 * due to the "max" being exceeded and the "threshold" reached again. The
195 * timestamp "restart_ts" is to keep track from when the counter was last
196 * queried (see sysfs handling of file wlp_tx_inflight).
197 */
198struct i1480u_tx_inflight {
199 atomic_t count;
200 unsigned long max;
201 unsigned long threshold;
202 unsigned long restart_ts;
203 atomic_t restart_count;
204};
205
206/**
207 * Instance of a i1480u WLP interface
208 *
209 * Keeps references to the USB device that wraps it, as well as it's
210 * interface and associated UWB host controller. As well, it also
211 * keeps a link to the netdevice for integration into the networking
212 * stack.
213 * We maintian separate error history for the tx and rx endpoints because
214 * the implementation does not rely on locking - having one shared
215 * structure between endpoints may cause problems. Adding locking to the
216 * implementation will have higher cost than adding a separate structure.
217 */
218struct i1480u {
219 struct usb_device *usb_dev;
220 struct usb_interface *usb_iface;
221 struct net_device *net_dev;
222
223 spinlock_t lock;
224
225 /* RX context handling */
226 struct sk_buff *rx_skb;
227 struct uwb_dev_addr rx_srcaddr;
228 size_t rx_untd_pkt_size;
229 struct i1480u_rx_buf {
230 struct i1480u *i1480u; /* back pointer */
231 struct urb *urb;
232 struct sk_buff *data; /* i1480u_MAX_RX_PKT_SIZE each */
233 } rx_buf[i1480u_RX_BUFS]; /* N bufs */
234
235 spinlock_t tx_list_lock; /* TX context */
236 struct list_head tx_list;
237 u8 tx_stream;
238
239 struct stats lqe_stats, rssi_stats; /* radio statistics */
240
241 /* Options we can set from sysfs */
242 struct wlp_options options;
243 struct uwb_notifs_handler uwb_notifs_handler;
244 struct edc tx_errors;
245 struct edc rx_errors;
246 struct wlp wlp;
247#ifdef i1480u_FLOW_CONTROL
248 struct urb *notif_urb;
249 struct edc notif_edc; /* error density counter */
250 u8 notif_buffer[1];
251#endif
252 struct i1480u_tx_inflight tx_inflight;
253};
254
255/* Internal interfaces */
256extern void i1480u_rx_cb(struct urb *urb);
257extern int i1480u_rx_setup(struct i1480u *);
258extern void i1480u_rx_release(struct i1480u *);
259extern void i1480u_tx_release(struct i1480u *);
260extern int i1480u_xmit_frame(struct wlp *, struct sk_buff *,
261 struct uwb_dev_addr *);
262extern void i1480u_stop_queue(struct wlp *);
263extern void i1480u_start_queue(struct wlp *);
264extern int i1480u_sysfs_setup(struct i1480u *);
265extern void i1480u_sysfs_release(struct i1480u *);
266
267/* netdev interface */
268extern int i1480u_open(struct net_device *);
269extern int i1480u_stop(struct net_device *);
270extern netdev_tx_t i1480u_hard_start_xmit(struct sk_buff *,
271 struct net_device *);
272extern void i1480u_tx_timeout(struct net_device *);
273extern int i1480u_set_config(struct net_device *, struct ifmap *);
274extern int i1480u_change_mtu(struct net_device *, int);
275extern void i1480u_uwb_notifs_cb(void *, struct uwb_dev *, enum uwb_notifs);
276
277/* bandwidth allocation callback */
278extern void i1480u_bw_alloc_cb(struct uwb_rsv *);
279
280/* Sys FS */
281extern struct attribute_group i1480u_wlp_attr_group;
282
283#endif /* #ifndef __i1480u_wlp_h__ */
diff --git a/drivers/uwb/i1480/i1480u-wlp/lc.c b/drivers/uwb/i1480/i1480u-wlp/lc.c
deleted file mode 100644
index def778cf2216..000000000000
--- a/drivers/uwb/i1480/i1480u-wlp/lc.c
+++ /dev/null
@@ -1,424 +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 * This implements a very simple network driver for the WLP USB
26 * device that is associated to a UWB (Ultra Wide Band) host.
27 *
28 * This is seen as an interface of a composite device. Once the UWB
29 * host has an association to another WLP capable device, the
30 * networking interface (aka WLP) can start to send packets back and
31 * forth.
32 *
33 * Limitations:
34 *
35 * - Hand cranked; can't ifup the interface until there is an association
36 *
37 * - BW allocation very simplistic [see i1480u_mas_set() and callees].
38 *
39 *
40 * ROADMAP:
41 *
42 * ENTRY POINTS (driver model):
43 *
44 * i1480u_driver_{exit,init}(): initialization of the driver.
45 *
46 * i1480u_probe(): called by the driver code when a device
47 * matching 'i1480u_id_table' is connected.
48 *
49 * This allocs a netdev instance, inits with
50 * i1480u_add(), then registers_netdev().
51 * i1480u_init()
52 * i1480u_add()
53 *
54 * i1480u_disconnect(): device has been disconnected/module
55 * is being removed.
56 * i1480u_rm()
57 */
58#include <linux/gfp.h>
59#include <linux/if_arp.h>
60#include <linux/etherdevice.h>
61
62#include "i1480u-wlp.h"
63
64
65
66static inline
67void i1480u_init(struct i1480u *i1480u)
68{
69 /* nothing so far... doesn't it suck? */
70 spin_lock_init(&i1480u->lock);
71 INIT_LIST_HEAD(&i1480u->tx_list);
72 spin_lock_init(&i1480u->tx_list_lock);
73 wlp_options_init(&i1480u->options);
74 edc_init(&i1480u->tx_errors);
75 edc_init(&i1480u->rx_errors);
76#ifdef i1480u_FLOW_CONTROL
77 edc_init(&i1480u->notif_edc);
78#endif
79 stats_init(&i1480u->lqe_stats);
80 stats_init(&i1480u->rssi_stats);
81 wlp_init(&i1480u->wlp);
82}
83
84/**
85 * Fill WLP device information structure
86 *
87 * The structure will contain a few character arrays, each ending with a
88 * null terminated string. Each string has to fit (excluding terminating
89 * character) into a specified range obtained from the WLP substack.
90 *
91 * It is still not clear exactly how this device information should be
92 * obtained. Until we find out we use the USB device descriptor as backup, some
93 * information elements have intuitive mappings, other not.
94 */
95static
96void i1480u_fill_device_info(struct wlp *wlp, struct wlp_device_info *dev_info)
97{
98 struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp);
99 struct usb_device *usb_dev = i1480u->usb_dev;
100 /* Treat device name and model name the same */
101 if (usb_dev->descriptor.iProduct) {
102 usb_string(usb_dev, usb_dev->descriptor.iProduct,
103 dev_info->name, sizeof(dev_info->name));
104 usb_string(usb_dev, usb_dev->descriptor.iProduct,
105 dev_info->model_name, sizeof(dev_info->model_name));
106 }
107 if (usb_dev->descriptor.iManufacturer)
108 usb_string(usb_dev, usb_dev->descriptor.iManufacturer,
109 dev_info->manufacturer,
110 sizeof(dev_info->manufacturer));
111 scnprintf(dev_info->model_nr, sizeof(dev_info->model_nr), "%04x",
112 __le16_to_cpu(usb_dev->descriptor.bcdDevice));
113 if (usb_dev->descriptor.iSerialNumber)
114 usb_string(usb_dev, usb_dev->descriptor.iSerialNumber,
115 dev_info->serial, sizeof(dev_info->serial));
116 /* FIXME: where should we obtain category? */
117 dev_info->prim_dev_type.category = cpu_to_le16(WLP_DEV_CAT_OTHER);
118 /* FIXME: Complete OUI and OUIsubdiv attributes */
119}
120
121#ifdef i1480u_FLOW_CONTROL
122/**
123 * Callback for the notification endpoint
124 *
125 * This mostly controls the xon/xoff protocol. In case of hard error,
126 * we stop the queue. If not, we always retry.
127 */
128static
129void i1480u_notif_cb(struct urb *urb, struct pt_regs *regs)
130{
131 struct i1480u *i1480u = urb->context;
132 struct usb_interface *usb_iface = i1480u->usb_iface;
133 struct device *dev = &usb_iface->dev;
134 int result;
135
136 switch (urb->status) {
137 case 0: /* Got valid data, do xon/xoff */
138 switch (i1480u->notif_buffer[0]) {
139 case 'N':
140 dev_err(dev, "XOFF STOPPING queue at %lu\n", jiffies);
141 netif_stop_queue(i1480u->net_dev);
142 break;
143 case 'A':
144 dev_err(dev, "XON STARTING queue at %lu\n", jiffies);
145 netif_start_queue(i1480u->net_dev);
146 break;
147 default:
148 dev_err(dev, "NEP: unknown data 0x%02hhx\n",
149 i1480u->notif_buffer[0]);
150 }
151 break;
152 case -ECONNRESET: /* Controlled situation ... */
153 case -ENOENT: /* we killed the URB... */
154 dev_err(dev, "NEP: URB reset/noent %d\n", urb->status);
155 goto error;
156 case -ESHUTDOWN: /* going away! */
157 dev_err(dev, "NEP: URB down %d\n", urb->status);
158 goto error;
159 default: /* Retry unless it gets ugly */
160 if (edc_inc(&i1480u->notif_edc, EDC_MAX_ERRORS,
161 EDC_ERROR_TIMEFRAME)) {
162 dev_err(dev, "NEP: URB max acceptable errors "
163 "exceeded; resetting device\n");
164 goto error_reset;
165 }
166 dev_err(dev, "NEP: URB error %d\n", urb->status);
167 break;
168 }
169 result = usb_submit_urb(urb, GFP_ATOMIC);
170 if (result < 0) {
171 dev_err(dev, "NEP: Can't resubmit URB: %d; resetting device\n",
172 result);
173 goto error_reset;
174 }
175 return;
176
177error_reset:
178 wlp_reset_all(&i1480-wlp);
179error:
180 netif_stop_queue(i1480u->net_dev);
181 return;
182}
183#endif
184
185static const struct net_device_ops i1480u_netdev_ops = {
186 .ndo_open = i1480u_open,
187 .ndo_stop = i1480u_stop,
188 .ndo_start_xmit = i1480u_hard_start_xmit,
189 .ndo_tx_timeout = i1480u_tx_timeout,
190 .ndo_set_config = i1480u_set_config,
191 .ndo_change_mtu = i1480u_change_mtu,
192};
193
194static
195int i1480u_add(struct i1480u *i1480u, struct usb_interface *iface)
196{
197 int result = -ENODEV;
198 struct wlp *wlp = &i1480u->wlp;
199 struct usb_device *usb_dev = interface_to_usbdev(iface);
200 struct net_device *net_dev = i1480u->net_dev;
201 struct uwb_rc *rc;
202 struct uwb_dev *uwb_dev;
203#ifdef i1480u_FLOW_CONTROL
204 struct usb_endpoint_descriptor *epd;
205#endif
206
207 i1480u->usb_dev = usb_get_dev(usb_dev);
208 i1480u->usb_iface = iface;
209 rc = uwb_rc_get_by_grandpa(&i1480u->usb_dev->dev);
210 if (rc == NULL) {
211 dev_err(&iface->dev, "Cannot get associated UWB Radio "
212 "Controller\n");
213 goto out;
214 }
215 wlp->xmit_frame = i1480u_xmit_frame;
216 wlp->fill_device_info = i1480u_fill_device_info;
217 wlp->stop_queue = i1480u_stop_queue;
218 wlp->start_queue = i1480u_start_queue;
219 result = wlp_setup(wlp, rc, net_dev);
220 if (result < 0) {
221 dev_err(&iface->dev, "Cannot setup WLP\n");
222 goto error_wlp_setup;
223 }
224 result = 0;
225 ether_setup(net_dev); /* make it an etherdevice */
226 uwb_dev = &rc->uwb_dev;
227 /* FIXME: hookup address change notifications? */
228
229 memcpy(net_dev->dev_addr, uwb_dev->mac_addr.data,
230 sizeof(net_dev->dev_addr));
231
232 net_dev->hard_header_len = sizeof(struct untd_hdr_cmp)
233 + sizeof(struct wlp_tx_hdr)
234 + WLP_DATA_HLEN
235 + ETH_HLEN;
236 net_dev->mtu = 3500;
237 net_dev->tx_queue_len = 20; /* FIXME: maybe use 1000? */
238
239/* net_dev->flags &= ~IFF_BROADCAST; FIXME: BUG in firmware */
240 /* FIXME: multicast disabled */
241 net_dev->flags &= ~IFF_MULTICAST;
242 net_dev->features &= ~NETIF_F_SG;
243 net_dev->features &= ~NETIF_F_FRAGLIST;
244 /* All NETIF_F_*_CSUM disabled */
245 net_dev->features |= NETIF_F_HIGHDMA;
246 net_dev->watchdog_timeo = 5*HZ; /* FIXME: a better default? */
247
248 net_dev->netdev_ops = &i1480u_netdev_ops;
249
250#ifdef i1480u_FLOW_CONTROL
251 /* Notification endpoint setup (submitted when we open the device) */
252 i1480u->notif_urb = usb_alloc_urb(0, GFP_KERNEL);
253 if (i1480u->notif_urb == NULL) {
254 dev_err(&iface->dev, "Unable to allocate notification URB\n");
255 result = -ENOMEM;
256 goto error_urb_alloc;
257 }
258 epd = &iface->cur_altsetting->endpoint[0].desc;
259 usb_fill_int_urb(i1480u->notif_urb, usb_dev,
260 usb_rcvintpipe(usb_dev, epd->bEndpointAddress),
261 i1480u->notif_buffer, sizeof(i1480u->notif_buffer),
262 i1480u_notif_cb, i1480u, epd->bInterval);
263
264#endif
265
266 i1480u->tx_inflight.max = i1480u_TX_INFLIGHT_MAX;
267 i1480u->tx_inflight.threshold = i1480u_TX_INFLIGHT_THRESHOLD;
268 i1480u->tx_inflight.restart_ts = jiffies;
269 usb_set_intfdata(iface, i1480u);
270 return result;
271
272#ifdef i1480u_FLOW_CONTROL
273error_urb_alloc:
274#endif
275 wlp_remove(wlp);
276error_wlp_setup:
277 uwb_rc_put(rc);
278out:
279 usb_put_dev(i1480u->usb_dev);
280 return result;
281}
282
283static void i1480u_rm(struct i1480u *i1480u)
284{
285 struct uwb_rc *rc = i1480u->wlp.rc;
286 usb_set_intfdata(i1480u->usb_iface, NULL);
287#ifdef i1480u_FLOW_CONTROL
288 usb_kill_urb(i1480u->notif_urb);
289 usb_free_urb(i1480u->notif_urb);
290#endif
291 wlp_remove(&i1480u->wlp);
292 uwb_rc_put(rc);
293 usb_put_dev(i1480u->usb_dev);
294}
295
296/** Just setup @net_dev's i1480u private data */
297static void i1480u_netdev_setup(struct net_device *net_dev)
298{
299 struct i1480u *i1480u = netdev_priv(net_dev);
300 /* Initialize @i1480u */
301 memset(i1480u, 0, sizeof(*i1480u));
302 i1480u_init(i1480u);
303}
304
305/**
306 * Probe a i1480u interface and register it
307 *
308 * @iface: USB interface to link to
309 * @id: USB class/subclass/protocol id
310 * @returns: 0 if ok, < 0 errno code on error.
311 *
312 * Does basic housekeeping stuff and then allocs a netdev with space
313 * for the i1480u data. Initializes, registers in i1480u, registers in
314 * netdev, ready to go.
315 */
316static int i1480u_probe(struct usb_interface *iface,
317 const struct usb_device_id *id)
318{
319 int result;
320 struct net_device *net_dev;
321 struct device *dev = &iface->dev;
322 struct i1480u *i1480u;
323
324 /* Allocate instance [calls i1480u_netdev_setup() on it] */
325 result = -ENOMEM;
326 net_dev = alloc_netdev(sizeof(*i1480u), "wlp%d", i1480u_netdev_setup);
327 if (net_dev == NULL) {
328 dev_err(dev, "no memory for network device instance\n");
329 goto error_alloc_netdev;
330 }
331 SET_NETDEV_DEV(net_dev, dev);
332 i1480u = netdev_priv(net_dev);
333 i1480u->net_dev = net_dev;
334 result = i1480u_add(i1480u, iface); /* Now setup all the wlp stuff */
335 if (result < 0) {
336 dev_err(dev, "cannot add i1480u device: %d\n", result);
337 goto error_i1480u_add;
338 }
339 result = register_netdev(net_dev); /* Okey dokey, bring it up */
340 if (result < 0) {
341 dev_err(dev, "cannot register network device: %d\n", result);
342 goto error_register_netdev;
343 }
344 i1480u_sysfs_setup(i1480u);
345 if (result < 0)
346 goto error_sysfs_init;
347 return 0;
348
349error_sysfs_init:
350 unregister_netdev(net_dev);
351error_register_netdev:
352 i1480u_rm(i1480u);
353error_i1480u_add:
354 free_netdev(net_dev);
355error_alloc_netdev:
356 return result;
357}
358
359
360/**
361 * Disconect a i1480u from the system.
362 *
363 * i1480u_stop() has been called before, so al the rx and tx contexts
364 * have been taken down already. Make sure the queue is stopped,
365 * unregister netdev and i1480u, free and kill.
366 */
367static void i1480u_disconnect(struct usb_interface *iface)
368{
369 struct i1480u *i1480u;
370 struct net_device *net_dev;
371
372 i1480u = usb_get_intfdata(iface);
373 net_dev = i1480u->net_dev;
374 netif_stop_queue(net_dev);
375#ifdef i1480u_FLOW_CONTROL
376 usb_kill_urb(i1480u->notif_urb);
377#endif
378 i1480u_sysfs_release(i1480u);
379 unregister_netdev(net_dev);
380 i1480u_rm(i1480u);
381 free_netdev(net_dev);
382}
383
384static struct usb_device_id i1480u_id_table[] = {
385 {
386 .match_flags = USB_DEVICE_ID_MATCH_DEVICE \
387 | USB_DEVICE_ID_MATCH_DEV_INFO \
388 | USB_DEVICE_ID_MATCH_INT_INFO,
389 .idVendor = 0x8086,
390 .idProduct = 0x0c3b,
391 .bDeviceClass = 0xef,
392 .bDeviceSubClass = 0x02,
393 .bDeviceProtocol = 0x02,
394 .bInterfaceClass = 0xff,
395 .bInterfaceSubClass = 0xff,
396 .bInterfaceProtocol = 0xff,
397 },
398 {},
399};
400MODULE_DEVICE_TABLE(usb, i1480u_id_table);
401
402static struct usb_driver i1480u_driver = {
403 .name = KBUILD_MODNAME,
404 .probe = i1480u_probe,
405 .disconnect = i1480u_disconnect,
406 .id_table = i1480u_id_table,
407};
408
409static int __init i1480u_driver_init(void)
410{
411 return usb_register(&i1480u_driver);
412}
413module_init(i1480u_driver_init);
414
415
416static void __exit i1480u_driver_exit(void)
417{
418 usb_deregister(&i1480u_driver);
419}
420module_exit(i1480u_driver_exit);
421
422MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>");
423MODULE_DESCRIPTION("i1480 Wireless UWB Link WLP networking for USB");
424MODULE_LICENSE("GPL");
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
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;
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;
231error_wss_setup:
232#ifdef i1480u_FLOW_CONTROL
233 usb_kill_urb(i1480u->notif_urb);
234error_notif_urb_submit:
235#endif
236 uwb_radio_stop(&wlp->pal);
237error_radio_start:
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;
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 */
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
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}
diff --git a/drivers/uwb/i1480/i1480u-wlp/rx.c b/drivers/uwb/i1480/i1480u-wlp/rx.c
deleted file mode 100644
index d4e51e108aa4..000000000000
--- a/drivers/uwb/i1480/i1480u-wlp/rx.c
+++ /dev/null
@@ -1,474 +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 * i1480u's RX handling is simple. i1480u will send the received
24 * network packets broken up in fragments; 1 to N fragments make a
25 * packet, we assemble them together and deliver the packet with netif_rx().
26 *
27 * Beacuse each USB transfer is a *single* fragment (except when the
28 * transfer contains a first fragment), each URB called thus
29 * back contains one or two fragments. So we queue N URBs, each with its own
30 * fragment buffer. When a URB is done, we process it (adding to the
31 * current skb from the fragment buffer until complete). Once
32 * processed, we requeue the URB. There is always a bunch of URBs
33 * ready to take data, so the intergap should be minimal.
34 *
35 * An URB's transfer buffer is the data field of a socket buffer. This
36 * reduces copying as data can be passed directly to network layer. If a
37 * complete packet or 1st fragment is received the URB's transfer buffer is
38 * taken away from it and used to send data to the network layer. In this
39 * case a new transfer buffer is allocated to the URB before being requeued.
40 * If a "NEXT" or "LAST" fragment is received, the fragment contents is
41 * appended to the RX packet under construction and the transfer buffer
42 * is reused. To be able to use this buffer to assemble complete packets
43 * we set each buffer's size to that of the MAX ethernet packet that can
44 * be received. There is thus room for improvement in memory usage.
45 *
46 * When the max tx fragment size increases, we should be able to read
47 * data into the skbs directly with very simple code.
48 *
49 * ROADMAP:
50 *
51 * ENTRY POINTS:
52 *
53 * i1480u_rx_setup(): setup RX context [from i1480u_open()]
54 *
55 * i1480u_rx_release(): release RX context [from i1480u_stop()]
56 *
57 * i1480u_rx_cb(): called when the RX USB URB receives a
58 * packet. It removes the header and pushes it up
59 * the Linux netdev stack with netif_rx().
60 *
61 * i1480u_rx_buffer()
62 * i1480u_drop() and i1480u_fix()
63 * i1480u_skb_deliver
64 *
65 */
66
67#include <linux/gfp.h>
68#include <linux/netdevice.h>
69#include <linux/etherdevice.h>
70#include "i1480u-wlp.h"
71
72/*
73 * Setup the RX context
74 *
75 * Each URB is provided with a transfer_buffer that is the data field
76 * of a new socket buffer.
77 */
78int i1480u_rx_setup(struct i1480u *i1480u)
79{
80 int result, cnt;
81 struct device *dev = &i1480u->usb_iface->dev;
82 struct net_device *net_dev = i1480u->net_dev;
83 struct usb_endpoint_descriptor *epd;
84 struct sk_buff *skb;
85
86 /* Alloc RX stuff */
87 i1480u->rx_skb = NULL; /* not in process of receiving packet */
88 result = -ENOMEM;
89 epd = &i1480u->usb_iface->cur_altsetting->endpoint[1].desc;
90 for (cnt = 0; cnt < i1480u_RX_BUFS; cnt++) {
91 struct i1480u_rx_buf *rx_buf = &i1480u->rx_buf[cnt];
92 rx_buf->i1480u = i1480u;
93 skb = dev_alloc_skb(i1480u_MAX_RX_PKT_SIZE);
94 if (!skb) {
95 dev_err(dev,
96 "RX: cannot allocate RX buffer %d\n", cnt);
97 result = -ENOMEM;
98 goto error;
99 }
100 skb->dev = net_dev;
101 skb->ip_summed = CHECKSUM_NONE;
102 skb_reserve(skb, 2);
103 rx_buf->data = skb;
104 rx_buf->urb = usb_alloc_urb(0, GFP_KERNEL);
105 if (unlikely(rx_buf->urb == NULL)) {
106 dev_err(dev, "RX: cannot allocate URB %d\n", cnt);
107 result = -ENOMEM;
108 goto error;
109 }
110 usb_fill_bulk_urb(rx_buf->urb, i1480u->usb_dev,
111 usb_rcvbulkpipe(i1480u->usb_dev, epd->bEndpointAddress),
112 rx_buf->data->data, i1480u_MAX_RX_PKT_SIZE - 2,
113 i1480u_rx_cb, rx_buf);
114 result = usb_submit_urb(rx_buf->urb, GFP_NOIO);
115 if (unlikely(result < 0)) {
116 dev_err(dev, "RX: cannot submit URB %d: %d\n",
117 cnt, result);
118 goto error;
119 }
120 }
121 return 0;
122
123error:
124 i1480u_rx_release(i1480u);
125 return result;
126}
127
128
129/* Release resources associated to the rx context */
130void i1480u_rx_release(struct i1480u *i1480u)
131{
132 int cnt;
133 for (cnt = 0; cnt < i1480u_RX_BUFS; cnt++) {
134 if (i1480u->rx_buf[cnt].data)
135 dev_kfree_skb(i1480u->rx_buf[cnt].data);
136 if (i1480u->rx_buf[cnt].urb) {
137 usb_kill_urb(i1480u->rx_buf[cnt].urb);
138 usb_free_urb(i1480u->rx_buf[cnt].urb);
139 }
140 }
141 if (i1480u->rx_skb != NULL)
142 dev_kfree_skb(i1480u->rx_skb);
143}
144
145static
146void i1480u_rx_unlink_urbs(struct i1480u *i1480u)
147{
148 int cnt;
149 for (cnt = 0; cnt < i1480u_RX_BUFS; cnt++) {
150 if (i1480u->rx_buf[cnt].urb)
151 usb_unlink_urb(i1480u->rx_buf[cnt].urb);
152 }
153}
154
155/* Fix an out-of-sequence packet */
156#define i1480u_fix(i1480u, msg...) \
157do { \
158 if (printk_ratelimit()) \
159 dev_err(&i1480u->usb_iface->dev, msg); \
160 dev_kfree_skb_irq(i1480u->rx_skb); \
161 i1480u->rx_skb = NULL; \
162 i1480u->rx_untd_pkt_size = 0; \
163} while (0)
164
165
166/* Drop an out-of-sequence packet */
167#define i1480u_drop(i1480u, msg...) \
168do { \
169 if (printk_ratelimit()) \
170 dev_err(&i1480u->usb_iface->dev, msg); \
171 i1480u->net_dev->stats.rx_dropped++; \
172} while (0)
173
174
175
176
177/* Finalizes setting up the SKB and delivers it
178 *
179 * We first pass the incoming frame to WLP substack for verification. It
180 * may also be a WLP association frame in which case WLP will take over the
181 * processing. If WLP does not take it over it will still verify it, if the
182 * frame is invalid the skb will be freed by WLP and we will not continue
183 * parsing.
184 * */
185static
186void i1480u_skb_deliver(struct i1480u *i1480u)
187{
188 int should_parse;
189 struct net_device *net_dev = i1480u->net_dev;
190 struct device *dev = &i1480u->usb_iface->dev;
191
192 should_parse = wlp_receive_frame(dev, &i1480u->wlp, i1480u->rx_skb,
193 &i1480u->rx_srcaddr);
194 if (!should_parse)
195 goto out;
196 i1480u->rx_skb->protocol = eth_type_trans(i1480u->rx_skb, net_dev);
197 net_dev->stats.rx_packets++;
198 net_dev->stats.rx_bytes += i1480u->rx_untd_pkt_size;
199
200 netif_rx(i1480u->rx_skb); /* deliver */
201out:
202 i1480u->rx_skb = NULL;
203 i1480u->rx_untd_pkt_size = 0;
204}
205
206
207/*
208 * Process a buffer of data received from the USB RX endpoint
209 *
210 * First fragment arrives with next or last fragment. All other fragments
211 * arrive alone.
212 *
213 * /me hates long functions.
214 */
215static
216void i1480u_rx_buffer(struct i1480u_rx_buf *rx_buf)
217{
218 unsigned pkt_completed = 0; /* !0 when we got all pkt fragments */
219 size_t untd_hdr_size, untd_frg_size;
220 size_t i1480u_hdr_size;
221 struct wlp_rx_hdr *i1480u_hdr = NULL;
222
223 struct i1480u *i1480u = rx_buf->i1480u;
224 struct sk_buff *skb = rx_buf->data;
225 int size_left = rx_buf->urb->actual_length;
226 void *ptr = rx_buf->urb->transfer_buffer; /* also rx_buf->data->data */
227 struct untd_hdr *untd_hdr;
228
229 struct net_device *net_dev = i1480u->net_dev;
230 struct device *dev = &i1480u->usb_iface->dev;
231 struct sk_buff *new_skb;
232
233#if 0
234 dev_fnstart(dev,
235 "(i1480u %p ptr %p size_left %zu)\n", i1480u, ptr, size_left);
236 dev_err(dev, "RX packet, %zu bytes\n", size_left);
237 dump_bytes(dev, ptr, size_left);
238#endif
239 i1480u_hdr_size = sizeof(struct wlp_rx_hdr);
240
241 while (size_left > 0) {
242 if (pkt_completed) {
243 i1480u_drop(i1480u, "RX: fragment follows completed"
244 "packet in same buffer. Dropping\n");
245 break;
246 }
247 untd_hdr = ptr;
248 if (size_left < sizeof(*untd_hdr)) { /* Check the UNTD header */
249 i1480u_drop(i1480u, "RX: short UNTD header! Dropping\n");
250 goto out;
251 }
252 if (unlikely(untd_hdr_rx_tx(untd_hdr) == 0)) { /* Paranoia: TX set? */
253 i1480u_drop(i1480u, "RX: TX bit set! Dropping\n");
254 goto out;
255 }
256 switch (untd_hdr_type(untd_hdr)) { /* Check the UNTD header type */
257 case i1480u_PKT_FRAG_1ST: {
258 struct untd_hdr_1st *untd_hdr_1st = (void *) untd_hdr;
259 dev_dbg(dev, "1st fragment\n");
260 untd_hdr_size = sizeof(struct untd_hdr_1st);
261 if (i1480u->rx_skb != NULL)
262 i1480u_fix(i1480u, "RX: 1st fragment out of "
263 "sequence! Fixing\n");
264 if (size_left < untd_hdr_size + i1480u_hdr_size) {
265 i1480u_drop(i1480u, "RX: short 1st fragment! "
266 "Dropping\n");
267 goto out;
268 }
269 i1480u->rx_untd_pkt_size = le16_to_cpu(untd_hdr->len)
270 - i1480u_hdr_size;
271 untd_frg_size = le16_to_cpu(untd_hdr_1st->fragment_len);
272 if (size_left < untd_hdr_size + untd_frg_size) {
273 i1480u_drop(i1480u,
274 "RX: short payload! Dropping\n");
275 goto out;
276 }
277 i1480u->rx_skb = skb;
278 i1480u_hdr = (void *) untd_hdr_1st + untd_hdr_size;
279 i1480u->rx_srcaddr = i1480u_hdr->srcaddr;
280 skb_put(i1480u->rx_skb, untd_hdr_size + untd_frg_size);
281 skb_pull(i1480u->rx_skb, untd_hdr_size + i1480u_hdr_size);
282 stats_add_sample(&i1480u->lqe_stats, (s8) i1480u_hdr->LQI - 7);
283 stats_add_sample(&i1480u->rssi_stats, i1480u_hdr->RSSI + 18);
284 rx_buf->data = NULL; /* need to create new buffer */
285 break;
286 }
287 case i1480u_PKT_FRAG_NXT: {
288 dev_dbg(dev, "nxt fragment\n");
289 untd_hdr_size = sizeof(struct untd_hdr_rst);
290 if (i1480u->rx_skb == NULL) {
291 i1480u_drop(i1480u, "RX: next fragment out of "
292 "sequence! Dropping\n");
293 goto out;
294 }
295 if (size_left < untd_hdr_size) {
296 i1480u_drop(i1480u, "RX: short NXT fragment! "
297 "Dropping\n");
298 goto out;
299 }
300 untd_frg_size = le16_to_cpu(untd_hdr->len);
301 if (size_left < untd_hdr_size + untd_frg_size) {
302 i1480u_drop(i1480u,
303 "RX: short payload! Dropping\n");
304 goto out;
305 }
306 memmove(skb_put(i1480u->rx_skb, untd_frg_size),
307 ptr + untd_hdr_size, untd_frg_size);
308 break;
309 }
310 case i1480u_PKT_FRAG_LST: {
311 dev_dbg(dev, "Lst fragment\n");
312 untd_hdr_size = sizeof(struct untd_hdr_rst);
313 if (i1480u->rx_skb == NULL) {
314 i1480u_drop(i1480u, "RX: last fragment out of "
315 "sequence! Dropping\n");
316 goto out;
317 }
318 if (size_left < untd_hdr_size) {
319 i1480u_drop(i1480u, "RX: short LST fragment! "
320 "Dropping\n");
321 goto out;
322 }
323 untd_frg_size = le16_to_cpu(untd_hdr->len);
324 if (size_left < untd_frg_size + untd_hdr_size) {
325 i1480u_drop(i1480u,
326 "RX: short payload! Dropping\n");
327 goto out;
328 }
329 memmove(skb_put(i1480u->rx_skb, untd_frg_size),
330 ptr + untd_hdr_size, untd_frg_size);
331 pkt_completed = 1;
332 break;
333 }
334 case i1480u_PKT_FRAG_CMP: {
335 dev_dbg(dev, "cmp fragment\n");
336 untd_hdr_size = sizeof(struct untd_hdr_cmp);
337 if (i1480u->rx_skb != NULL)
338 i1480u_fix(i1480u, "RX: fix out-of-sequence CMP"
339 " fragment!\n");
340 if (size_left < untd_hdr_size + i1480u_hdr_size) {
341 i1480u_drop(i1480u, "RX: short CMP fragment! "
342 "Dropping\n");
343 goto out;
344 }
345 i1480u->rx_untd_pkt_size = le16_to_cpu(untd_hdr->len);
346 untd_frg_size = i1480u->rx_untd_pkt_size;
347 if (size_left < i1480u->rx_untd_pkt_size + untd_hdr_size) {
348 i1480u_drop(i1480u,
349 "RX: short payload! Dropping\n");
350 goto out;
351 }
352 i1480u->rx_skb = skb;
353 i1480u_hdr = (void *) untd_hdr + untd_hdr_size;
354 i1480u->rx_srcaddr = i1480u_hdr->srcaddr;
355 stats_add_sample(&i1480u->lqe_stats, (s8) i1480u_hdr->LQI - 7);
356 stats_add_sample(&i1480u->rssi_stats, i1480u_hdr->RSSI + 18);
357 skb_put(i1480u->rx_skb, untd_hdr_size + i1480u->rx_untd_pkt_size);
358 skb_pull(i1480u->rx_skb, untd_hdr_size + i1480u_hdr_size);
359 rx_buf->data = NULL; /* for hand off skb to network stack */
360 pkt_completed = 1;
361 i1480u->rx_untd_pkt_size -= i1480u_hdr_size; /* accurate stat */
362 break;
363 }
364 default:
365 i1480u_drop(i1480u, "RX: unknown packet type %u! "
366 "Dropping\n", untd_hdr_type(untd_hdr));
367 goto out;
368 }
369 size_left -= untd_hdr_size + untd_frg_size;
370 if (size_left > 0)
371 ptr += untd_hdr_size + untd_frg_size;
372 }
373 if (pkt_completed)
374 i1480u_skb_deliver(i1480u);
375out:
376 /* recreate needed RX buffers*/
377 if (rx_buf->data == NULL) {
378 /* buffer is being used to receive packet, create new */
379 new_skb = dev_alloc_skb(i1480u_MAX_RX_PKT_SIZE);
380 if (!new_skb) {
381 if (printk_ratelimit())
382 dev_err(dev,
383 "RX: cannot allocate RX buffer\n");
384 } else {
385 new_skb->dev = net_dev;
386 new_skb->ip_summed = CHECKSUM_NONE;
387 skb_reserve(new_skb, 2);
388 rx_buf->data = new_skb;
389 }
390 }
391 return;
392}
393
394
395/*
396 * Called when an RX URB has finished receiving or has found some kind
397 * of error condition.
398 *
399 * LIMITATIONS:
400 *
401 * - We read USB-transfers, each transfer contains a SINGLE fragment
402 * (can contain a complete packet, or a 1st, next, or last fragment
403 * of a packet).
404 * Looks like a transfer can contain more than one fragment (07/18/06)
405 *
406 * - Each transfer buffer is the size of the maximum packet size (minus
407 * headroom), i1480u_MAX_PKT_SIZE - 2
408 *
409 * - We always read the full USB-transfer, no partials.
410 *
411 * - Each transfer is read directly into a skb. This skb will be used to
412 * send data to the upper layers if it is the first fragment or a complete
413 * packet. In the other cases the data will be copied from the skb to
414 * another skb that is being prepared for the upper layers from a prev
415 * first fragment.
416 *
417 * It is simply too much of a pain. Gosh, there should be a unified
418 * SG infrastructure for *everything* [so that I could declare a SG
419 * buffer, pass it to USB for receiving, append some space to it if
420 * I wish, receive more until I have the whole chunk, adapt
421 * pointers on each fragment to remove hardware headers and then
422 * attach that to an skbuff and netif_rx()].
423 */
424void i1480u_rx_cb(struct urb *urb)
425{
426 int result;
427 int do_parse_buffer = 1;
428 struct i1480u_rx_buf *rx_buf = urb->context;
429 struct i1480u *i1480u = rx_buf->i1480u;
430 struct device *dev = &i1480u->usb_iface->dev;
431 unsigned long flags;
432 u8 rx_buf_idx = rx_buf - i1480u->rx_buf;
433
434 switch (urb->status) {
435 case 0:
436 break;
437 case -ECONNRESET: /* Not an error, but a controlled situation; */
438 case -ENOENT: /* (we killed the URB)...so, no broadcast */
439 case -ESHUTDOWN: /* going away! */
440 dev_err(dev, "RX URB[%u]: goind down %d\n",
441 rx_buf_idx, urb->status);
442 goto error;
443 default:
444 dev_err(dev, "RX URB[%u]: unknown status %d\n",
445 rx_buf_idx, urb->status);
446 if (edc_inc(&i1480u->rx_errors, EDC_MAX_ERRORS,
447 EDC_ERROR_TIMEFRAME)) {
448 dev_err(dev, "RX: max acceptable errors exceeded,"
449 " resetting device.\n");
450 i1480u_rx_unlink_urbs(i1480u);
451 wlp_reset_all(&i1480u->wlp);
452 goto error;
453 }
454 do_parse_buffer = 0;
455 break;
456 }
457 spin_lock_irqsave(&i1480u->lock, flags);
458 /* chew the data fragments, extract network packets */
459 if (do_parse_buffer) {
460 i1480u_rx_buffer(rx_buf);
461 if (rx_buf->data) {
462 rx_buf->urb->transfer_buffer = rx_buf->data->data;
463 result = usb_submit_urb(rx_buf->urb, GFP_ATOMIC);
464 if (result < 0) {
465 dev_err(dev, "RX URB[%u]: cannot submit %d\n",
466 rx_buf_idx, result);
467 }
468 }
469 }
470 spin_unlock_irqrestore(&i1480u->lock, flags);
471error:
472 return;
473}
474
diff --git a/drivers/uwb/i1480/i1480u-wlp/sysfs.c b/drivers/uwb/i1480/i1480u-wlp/sysfs.c
deleted file mode 100644
index 4ffaf546cc6c..000000000000
--- a/drivers/uwb/i1480/i1480u-wlp/sysfs.c
+++ /dev/null
@@ -1,407 +0,0 @@
1/*
2 * WUSB Wire Adapter: WLP interface
3 * Sysfs interfaces
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
26#include <linux/netdevice.h>
27#include <linux/etherdevice.h>
28#include <linux/device.h>
29
30#include "i1480u-wlp.h"
31
32
33/**
34 *
35 * @dev: Class device from the net_device; assumed refcnted.
36 *
37 * Yes, I don't lock--we assume it is refcounted and I am getting a
38 * single byte value that is kind of atomic to read.
39 */
40ssize_t uwb_phy_rate_show(const struct wlp_options *options, char *buf)
41{
42 return sprintf(buf, "%u\n",
43 wlp_tx_hdr_phy_rate(&options->def_tx_hdr));
44}
45EXPORT_SYMBOL_GPL(uwb_phy_rate_show);
46
47
48ssize_t uwb_phy_rate_store(struct wlp_options *options,
49 const char *buf, size_t size)
50{
51 ssize_t result;
52 unsigned rate;
53
54 result = sscanf(buf, "%u\n", &rate);
55 if (result != 1) {
56 result = -EINVAL;
57 goto out;
58 }
59 result = -EINVAL;
60 if (rate >= UWB_PHY_RATE_INVALID)
61 goto out;
62 wlp_tx_hdr_set_phy_rate(&options->def_tx_hdr, rate);
63 result = 0;
64out:
65 return result < 0 ? result : size;
66}
67EXPORT_SYMBOL_GPL(uwb_phy_rate_store);
68
69
70ssize_t uwb_rts_cts_show(const struct wlp_options *options, char *buf)
71{
72 return sprintf(buf, "%u\n",
73 wlp_tx_hdr_rts_cts(&options->def_tx_hdr));
74}
75EXPORT_SYMBOL_GPL(uwb_rts_cts_show);
76
77
78ssize_t uwb_rts_cts_store(struct wlp_options *options,
79 const char *buf, size_t size)
80{
81 ssize_t result;
82 unsigned value;
83
84 result = sscanf(buf, "%u\n", &value);
85 if (result != 1) {
86 result = -EINVAL;
87 goto out;
88 }
89 result = -EINVAL;
90 wlp_tx_hdr_set_rts_cts(&options->def_tx_hdr, !!value);
91 result = 0;
92out:
93 return result < 0 ? result : size;
94}
95EXPORT_SYMBOL_GPL(uwb_rts_cts_store);
96
97
98ssize_t uwb_ack_policy_show(const struct wlp_options *options, char *buf)
99{
100 return sprintf(buf, "%u\n",
101 wlp_tx_hdr_ack_policy(&options->def_tx_hdr));
102}
103EXPORT_SYMBOL_GPL(uwb_ack_policy_show);
104
105
106ssize_t uwb_ack_policy_store(struct wlp_options *options,
107 const char *buf, size_t size)
108{
109 ssize_t result;
110 unsigned value;
111
112 result = sscanf(buf, "%u\n", &value);
113 if (result != 1 || value > UWB_ACK_B_REQ) {
114 result = -EINVAL;
115 goto out;
116 }
117 wlp_tx_hdr_set_ack_policy(&options->def_tx_hdr, value);
118 result = 0;
119out:
120 return result < 0 ? result : size;
121}
122EXPORT_SYMBOL_GPL(uwb_ack_policy_store);
123
124
125/**
126 * Show the PCA base priority.
127 *
128 * We can access without locking, as the value is (for now) orthogonal
129 * to other values.
130 */
131ssize_t uwb_pca_base_priority_show(const struct wlp_options *options,
132 char *buf)
133{
134 return sprintf(buf, "%u\n",
135 options->pca_base_priority);
136}
137EXPORT_SYMBOL_GPL(uwb_pca_base_priority_show);
138
139
140/**
141 * Set the PCA base priority.
142 *
143 * We can access without locking, as the value is (for now) orthogonal
144 * to other values.
145 */
146ssize_t uwb_pca_base_priority_store(struct wlp_options *options,
147 const char *buf, size_t size)
148{
149 ssize_t result = -EINVAL;
150 u8 pca_base_priority;
151
152 result = sscanf(buf, "%hhu\n", &pca_base_priority);
153 if (result != 1) {
154 result = -EINVAL;
155 goto out;
156 }
157 result = -EINVAL;
158 if (pca_base_priority >= 8)
159 goto out;
160 options->pca_base_priority = pca_base_priority;
161 /* Update TX header if we are currently using PCA. */
162 if (result >= 0 && (wlp_tx_hdr_delivery_id_type(&options->def_tx_hdr) & WLP_DRP) == 0)
163 wlp_tx_hdr_set_delivery_id_type(&options->def_tx_hdr, options->pca_base_priority);
164 result = 0;
165out:
166 return result < 0 ? result : size;
167}
168EXPORT_SYMBOL_GPL(uwb_pca_base_priority_store);
169
170/**
171 * Show current inflight values
172 *
173 * Will print the current MAX and THRESHOLD values for the basic flow
174 * control. In addition it will report how many times the TX queue needed
175 * to be restarted since the last time this query was made.
176 */
177static ssize_t wlp_tx_inflight_show(struct i1480u_tx_inflight *inflight,
178 char *buf)
179{
180 ssize_t result;
181 unsigned long sec_elapsed = (jiffies - inflight->restart_ts)/HZ;
182 unsigned long restart_count = atomic_read(&inflight->restart_count);
183
184 result = scnprintf(buf, PAGE_SIZE, "%lu %lu %d %lu %lu %lu\n"
185 "#read: threshold max inflight_count restarts "
186 "seconds restarts/sec\n"
187 "#write: threshold max\n",
188 inflight->threshold, inflight->max,
189 atomic_read(&inflight->count),
190 restart_count, sec_elapsed,
191 sec_elapsed == 0 ? 0 : restart_count/sec_elapsed);
192 inflight->restart_ts = jiffies;
193 atomic_set(&inflight->restart_count, 0);
194 return result;
195}
196
197static
198ssize_t wlp_tx_inflight_store(struct i1480u_tx_inflight *inflight,
199 const char *buf, size_t size)
200{
201 unsigned long in_threshold, in_max;
202 ssize_t result;
203 result = sscanf(buf, "%lu %lu", &in_threshold, &in_max);
204 if (result != 2)
205 return -EINVAL;
206 if (in_max <= in_threshold)
207 return -EINVAL;
208 inflight->max = in_max;
209 inflight->threshold = in_threshold;
210 return size;
211}
212/*
213 * Glue (or function adaptors) for accesing info on sysfs
214 *
215 * [we need this indirection because the PCI driver does almost the
216 * same]
217 *
218 * Linux 2.6.21 changed how 'struct netdevice' does attributes (from
219 * having a 'struct class_dev' to having a 'struct device'). That is
220 * quite of a pain.
221 *
222 * So we try to abstract that here. i1480u_SHOW() and i1480u_STORE()
223 * create adaptors for extracting the 'struct i1480u' from a 'struct
224 * dev' and calling a function for doing a sysfs operation (as we have
225 * them factorized already). i1480u_ATTR creates the attribute file
226 * (CLASS_DEVICE_ATTR or DEVICE_ATTR) and i1480u_ATTR_NAME produces a
227 * class_device_attr_NAME or device_attr_NAME (for group registration).
228 */
229
230#define i1480u_SHOW(name, fn, param) \
231static ssize_t i1480u_show_##name(struct device *dev, \
232 struct device_attribute *attr,\
233 char *buf) \
234{ \
235 struct i1480u *i1480u = netdev_priv(to_net_dev(dev)); \
236 return fn(&i1480u->param, buf); \
237}
238
239#define i1480u_STORE(name, fn, param) \
240static ssize_t i1480u_store_##name(struct device *dev, \
241 struct device_attribute *attr,\
242 const char *buf, size_t size)\
243{ \
244 struct i1480u *i1480u = netdev_priv(to_net_dev(dev)); \
245 return fn(&i1480u->param, buf, size); \
246}
247
248#define i1480u_ATTR(name, perm) static DEVICE_ATTR(name, perm, \
249 i1480u_show_##name,\
250 i1480u_store_##name)
251
252#define i1480u_ATTR_SHOW(name) static DEVICE_ATTR(name, \
253 S_IRUGO, \
254 i1480u_show_##name, NULL)
255
256#define i1480u_ATTR_NAME(a) (dev_attr_##a)
257
258
259/*
260 * Sysfs adaptors
261 */
262i1480u_SHOW(uwb_phy_rate, uwb_phy_rate_show, options);
263i1480u_STORE(uwb_phy_rate, uwb_phy_rate_store, options);
264i1480u_ATTR(uwb_phy_rate, S_IRUGO | S_IWUSR);
265
266i1480u_SHOW(uwb_rts_cts, uwb_rts_cts_show, options);
267i1480u_STORE(uwb_rts_cts, uwb_rts_cts_store, options);
268i1480u_ATTR(uwb_rts_cts, S_IRUGO | S_IWUSR);
269
270i1480u_SHOW(uwb_ack_policy, uwb_ack_policy_show, options);
271i1480u_STORE(uwb_ack_policy, uwb_ack_policy_store, options);
272i1480u_ATTR(uwb_ack_policy, S_IRUGO | S_IWUSR);
273
274i1480u_SHOW(uwb_pca_base_priority, uwb_pca_base_priority_show, options);
275i1480u_STORE(uwb_pca_base_priority, uwb_pca_base_priority_store, options);
276i1480u_ATTR(uwb_pca_base_priority, S_IRUGO | S_IWUSR);
277
278i1480u_SHOW(wlp_eda, wlp_eda_show, wlp);
279i1480u_STORE(wlp_eda, wlp_eda_store, wlp);
280i1480u_ATTR(wlp_eda, S_IRUGO | S_IWUSR);
281
282i1480u_SHOW(wlp_uuid, wlp_uuid_show, wlp);
283i1480u_STORE(wlp_uuid, wlp_uuid_store, wlp);
284i1480u_ATTR(wlp_uuid, S_IRUGO | S_IWUSR);
285
286i1480u_SHOW(wlp_dev_name, wlp_dev_name_show, wlp);
287i1480u_STORE(wlp_dev_name, wlp_dev_name_store, wlp);
288i1480u_ATTR(wlp_dev_name, S_IRUGO | S_IWUSR);
289
290i1480u_SHOW(wlp_dev_manufacturer, wlp_dev_manufacturer_show, wlp);
291i1480u_STORE(wlp_dev_manufacturer, wlp_dev_manufacturer_store, wlp);
292i1480u_ATTR(wlp_dev_manufacturer, S_IRUGO | S_IWUSR);
293
294i1480u_SHOW(wlp_dev_model_name, wlp_dev_model_name_show, wlp);
295i1480u_STORE(wlp_dev_model_name, wlp_dev_model_name_store, wlp);
296i1480u_ATTR(wlp_dev_model_name, S_IRUGO | S_IWUSR);
297
298i1480u_SHOW(wlp_dev_model_nr, wlp_dev_model_nr_show, wlp);
299i1480u_STORE(wlp_dev_model_nr, wlp_dev_model_nr_store, wlp);
300i1480u_ATTR(wlp_dev_model_nr, S_IRUGO | S_IWUSR);
301
302i1480u_SHOW(wlp_dev_serial, wlp_dev_serial_show, wlp);
303i1480u_STORE(wlp_dev_serial, wlp_dev_serial_store, wlp);
304i1480u_ATTR(wlp_dev_serial, S_IRUGO | S_IWUSR);
305
306i1480u_SHOW(wlp_dev_prim_category, wlp_dev_prim_category_show, wlp);
307i1480u_STORE(wlp_dev_prim_category, wlp_dev_prim_category_store, wlp);
308i1480u_ATTR(wlp_dev_prim_category, S_IRUGO | S_IWUSR);
309
310i1480u_SHOW(wlp_dev_prim_OUI, wlp_dev_prim_OUI_show, wlp);
311i1480u_STORE(wlp_dev_prim_OUI, wlp_dev_prim_OUI_store, wlp);
312i1480u_ATTR(wlp_dev_prim_OUI, S_IRUGO | S_IWUSR);
313
314i1480u_SHOW(wlp_dev_prim_OUI_sub, wlp_dev_prim_OUI_sub_show, wlp);
315i1480u_STORE(wlp_dev_prim_OUI_sub, wlp_dev_prim_OUI_sub_store, wlp);
316i1480u_ATTR(wlp_dev_prim_OUI_sub, S_IRUGO | S_IWUSR);
317
318i1480u_SHOW(wlp_dev_prim_subcat, wlp_dev_prim_subcat_show, wlp);
319i1480u_STORE(wlp_dev_prim_subcat, wlp_dev_prim_subcat_store, wlp);
320i1480u_ATTR(wlp_dev_prim_subcat, S_IRUGO | S_IWUSR);
321
322i1480u_SHOW(wlp_neighborhood, wlp_neighborhood_show, wlp);
323i1480u_ATTR_SHOW(wlp_neighborhood);
324
325i1480u_SHOW(wss_activate, wlp_wss_activate_show, wlp.wss);
326i1480u_STORE(wss_activate, wlp_wss_activate_store, wlp.wss);
327i1480u_ATTR(wss_activate, S_IRUGO | S_IWUSR);
328
329/*
330 * Show the (min, max, avg) Line Quality Estimate (LQE, in dB) as over
331 * the last 256 received WLP frames (ECMA-368 13.3).
332 *
333 * [the -7dB that have to be substracted from the LQI to make the LQE
334 * are already taken into account].
335 */
336i1480u_SHOW(wlp_lqe, stats_show, lqe_stats);
337i1480u_STORE(wlp_lqe, stats_store, lqe_stats);
338i1480u_ATTR(wlp_lqe, S_IRUGO | S_IWUSR);
339
340/*
341 * Show the Receive Signal Strength Indicator averaged over all the
342 * received WLP frames (ECMA-368 13.3). Still is not clear what
343 * this value is, but is kind of a percentage of the signal strength
344 * at the antenna.
345 */
346i1480u_SHOW(wlp_rssi, stats_show, rssi_stats);
347i1480u_STORE(wlp_rssi, stats_store, rssi_stats);
348i1480u_ATTR(wlp_rssi, S_IRUGO | S_IWUSR);
349
350/**
351 * We maintain a basic flow control counter. "count" how many TX URBs are
352 * outstanding. Only allow "max"
353 * TX URBs to be outstanding. If this value is reached the queue will be
354 * stopped. The queue will be restarted when there are
355 * "threshold" URBs outstanding.
356 */
357i1480u_SHOW(wlp_tx_inflight, wlp_tx_inflight_show, tx_inflight);
358i1480u_STORE(wlp_tx_inflight, wlp_tx_inflight_store, tx_inflight);
359i1480u_ATTR(wlp_tx_inflight, S_IRUGO | S_IWUSR);
360
361static struct attribute *i1480u_attrs[] = {
362 &i1480u_ATTR_NAME(uwb_phy_rate).attr,
363 &i1480u_ATTR_NAME(uwb_rts_cts).attr,
364 &i1480u_ATTR_NAME(uwb_ack_policy).attr,
365 &i1480u_ATTR_NAME(uwb_pca_base_priority).attr,
366 &i1480u_ATTR_NAME(wlp_lqe).attr,
367 &i1480u_ATTR_NAME(wlp_rssi).attr,
368 &i1480u_ATTR_NAME(wlp_eda).attr,
369 &i1480u_ATTR_NAME(wlp_uuid).attr,
370 &i1480u_ATTR_NAME(wlp_dev_name).attr,
371 &i1480u_ATTR_NAME(wlp_dev_manufacturer).attr,
372 &i1480u_ATTR_NAME(wlp_dev_model_name).attr,
373 &i1480u_ATTR_NAME(wlp_dev_model_nr).attr,
374 &i1480u_ATTR_NAME(wlp_dev_serial).attr,
375 &i1480u_ATTR_NAME(wlp_dev_prim_category).attr,
376 &i1480u_ATTR_NAME(wlp_dev_prim_OUI).attr,
377 &i1480u_ATTR_NAME(wlp_dev_prim_OUI_sub).attr,
378 &i1480u_ATTR_NAME(wlp_dev_prim_subcat).attr,
379 &i1480u_ATTR_NAME(wlp_neighborhood).attr,
380 &i1480u_ATTR_NAME(wss_activate).attr,
381 &i1480u_ATTR_NAME(wlp_tx_inflight).attr,
382 NULL,
383};
384
385static struct attribute_group i1480u_attr_group = {
386 .name = NULL, /* we want them in the same directory */
387 .attrs = i1480u_attrs,
388};
389
390int i1480u_sysfs_setup(struct i1480u *i1480u)
391{
392 int result;
393 struct device *dev = &i1480u->usb_iface->dev;
394 result = sysfs_create_group(&i1480u->net_dev->dev.kobj,
395 &i1480u_attr_group);
396 if (result < 0)
397 dev_err(dev, "cannot initialize sysfs attributes: %d\n",
398 result);
399 return result;
400}
401
402
403void i1480u_sysfs_release(struct i1480u *i1480u)
404{
405 sysfs_remove_group(&i1480u->net_dev->dev.kobj,
406 &i1480u_attr_group);
407}
diff --git a/drivers/uwb/i1480/i1480u-wlp/tx.c b/drivers/uwb/i1480/i1480u-wlp/tx.c
deleted file mode 100644
index 3c117a364564..000000000000
--- a/drivers/uwb/i1480/i1480u-wlp/tx.c
+++ /dev/null
@@ -1,584 +0,0 @@
1/*
2 * WUSB Wire Adapter: WLP interface
3 * Deal with TX (massaging data to transmit, handling it)
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 * Transmission engine. Get an skb, create from that a WLP transmit
24 * context, add a WLP TX header (which we keep prefilled in the
25 * device's instance), fill out the target-specific fields and
26 * fire it.
27 *
28 * ROADMAP:
29 *
30 * Entry points:
31 *
32 * i1480u_tx_release(): called by i1480u_disconnect() to release
33 * pending tx contexts.
34 *
35 * i1480u_tx_cb(): callback for TX contexts (USB URBs)
36 * i1480u_tx_destroy():
37 *
38 * i1480u_tx_timeout(): called for timeout handling from the
39 * network stack.
40 *
41 * i1480u_hard_start_xmit(): called for transmitting an skb from
42 * the network stack. Will interact with WLP
43 * substack to verify and prepare frame.
44 * i1480u_xmit_frame(): actual transmission on hardware
45 *
46 * i1480u_tx_create() Creates TX context
47 * i1480u_tx_create_1() For packets in 1 fragment
48 * i1480u_tx_create_n() For packets in >1 fragments
49 *
50 * TODO:
51 *
52 * - FIXME: rewrite using usb_sg_*(), add asynch support to
53 * usb_sg_*(). It might not make too much sense as most of
54 * the times the MTU will be smaller than one page...
55 */
56
57#include <linux/slab.h>
58#include "i1480u-wlp.h"
59
60enum {
61 /* This is only for Next and Last TX packets */
62 i1480u_MAX_PL_SIZE = i1480u_MAX_FRG_SIZE
63 - sizeof(struct untd_hdr_rst),
64};
65
66/* Free resources allocated to a i1480u tx context. */
67static
68void i1480u_tx_free(struct i1480u_tx *wtx)
69{
70 kfree(wtx->buf);
71 if (wtx->skb)
72 dev_kfree_skb_irq(wtx->skb);
73 usb_free_urb(wtx->urb);
74 kfree(wtx);
75}
76
77static
78void i1480u_tx_destroy(struct i1480u *i1480u, struct i1480u_tx *wtx)
79{
80 unsigned long flags;
81 spin_lock_irqsave(&i1480u->tx_list_lock, flags); /* not active any more */
82 list_del(&wtx->list_node);
83 i1480u_tx_free(wtx);
84 spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
85}
86
87static
88void i1480u_tx_unlink_urbs(struct i1480u *i1480u)
89{
90 unsigned long flags;
91 struct i1480u_tx *wtx, *next;
92
93 spin_lock_irqsave(&i1480u->tx_list_lock, flags);
94 list_for_each_entry_safe(wtx, next, &i1480u->tx_list, list_node) {
95 usb_unlink_urb(wtx->urb);
96 }
97 spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
98}
99
100
101/*
102 * Callback for a completed tx USB URB.
103 *
104 * TODO:
105 *
106 * - FIXME: recover errors more gracefully
107 * - FIXME: handle NAKs (I dont think they come here) for flow ctl
108 */
109static
110void i1480u_tx_cb(struct urb *urb)
111{
112 struct i1480u_tx *wtx = urb->context;
113 struct i1480u *i1480u = wtx->i1480u;
114 struct net_device *net_dev = i1480u->net_dev;
115 struct device *dev = &i1480u->usb_iface->dev;
116 unsigned long flags;
117
118 switch (urb->status) {
119 case 0:
120 spin_lock_irqsave(&i1480u->lock, flags);
121 net_dev->stats.tx_packets++;
122 net_dev->stats.tx_bytes += urb->actual_length;
123 spin_unlock_irqrestore(&i1480u->lock, flags);
124 break;
125 case -ECONNRESET: /* Not an error, but a controlled situation; */
126 case -ENOENT: /* (we killed the URB)...so, no broadcast */
127 dev_dbg(dev, "notif endp: reset/noent %d\n", urb->status);
128 netif_stop_queue(net_dev);
129 break;
130 case -ESHUTDOWN: /* going away! */
131 dev_dbg(dev, "notif endp: down %d\n", urb->status);
132 netif_stop_queue(net_dev);
133 break;
134 default:
135 dev_err(dev, "TX: unknown URB status %d\n", urb->status);
136 if (edc_inc(&i1480u->tx_errors, EDC_MAX_ERRORS,
137 EDC_ERROR_TIMEFRAME)) {
138 dev_err(dev, "TX: max acceptable errors exceeded."
139 "Reset device.\n");
140 netif_stop_queue(net_dev);
141 i1480u_tx_unlink_urbs(i1480u);
142 wlp_reset_all(&i1480u->wlp);
143 }
144 break;
145 }
146 i1480u_tx_destroy(i1480u, wtx);
147 if (atomic_dec_return(&i1480u->tx_inflight.count)
148 <= i1480u->tx_inflight.threshold
149 && netif_queue_stopped(net_dev)
150 && i1480u->tx_inflight.threshold != 0) {
151 netif_start_queue(net_dev);
152 atomic_inc(&i1480u->tx_inflight.restart_count);
153 }
154 return;
155}
156
157
158/*
159 * Given a buffer that doesn't fit in a single fragment, create an
160 * scatter/gather structure for delivery to the USB pipe.
161 *
162 * Implements functionality of i1480u_tx_create().
163 *
164 * @wtx: tx descriptor
165 * @skb: skb to send
166 * @gfp_mask: gfp allocation mask
167 * @returns: Pointer to @wtx if ok, NULL on error.
168 *
169 * Sorry, TOO LONG a function, but breaking it up is kind of hard
170 *
171 * This will break the buffer in chunks smaller than
172 * i1480u_MAX_FRG_SIZE (including the header) and add proper headers
173 * to each:
174 *
175 * 1st header \
176 * i1480 tx header | fragment 1
177 * fragment data /
178 * nxt header \ fragment 2
179 * fragment data /
180 * ..
181 * ..
182 * last header \ fragment 3
183 * last fragment data /
184 *
185 * This does not fill the i1480 TX header, it is left up to the
186 * caller to do that; you can get it from @wtx->wlp_tx_hdr.
187 *
188 * This function consumes the skb unless there is an error.
189 */
190static
191int i1480u_tx_create_n(struct i1480u_tx *wtx, struct sk_buff *skb,
192 gfp_t gfp_mask)
193{
194 int result;
195 void *pl;
196 size_t pl_size;
197
198 void *pl_itr, *buf_itr;
199 size_t pl_size_left, frgs, pl_size_1st, frg_pl_size = 0;
200 struct untd_hdr_1st *untd_hdr_1st;
201 struct wlp_tx_hdr *wlp_tx_hdr;
202 struct untd_hdr_rst *untd_hdr_rst;
203
204 wtx->skb = NULL;
205 pl = skb->data;
206 pl_itr = pl;
207 pl_size = skb->len;
208 pl_size_left = pl_size; /* payload size */
209 /* First fragment; fits as much as i1480u_MAX_FRG_SIZE minus
210 * the headers */
211 pl_size_1st = i1480u_MAX_FRG_SIZE
212 - sizeof(struct untd_hdr_1st) - sizeof(struct wlp_tx_hdr);
213 BUG_ON(pl_size_1st > pl_size);
214 pl_size_left -= pl_size_1st;
215 /* The rest have an smaller header (no i1480 TX header). We
216 * need to break up the payload in blocks smaller than
217 * i1480u_MAX_PL_SIZE (payload excluding header). */
218 frgs = (pl_size_left + i1480u_MAX_PL_SIZE - 1) / i1480u_MAX_PL_SIZE;
219 /* Allocate space for the new buffer. In this new buffer we'll
220 * place the headers followed by the data fragment, headers,
221 * data fragments, etc..
222 */
223 result = -ENOMEM;
224 wtx->buf_size = sizeof(*untd_hdr_1st)
225 + sizeof(*wlp_tx_hdr)
226 + frgs * sizeof(*untd_hdr_rst)
227 + pl_size;
228 wtx->buf = kmalloc(wtx->buf_size, gfp_mask);
229 if (wtx->buf == NULL)
230 goto error_buf_alloc;
231
232 buf_itr = wtx->buf; /* We got the space, let's fill it up */
233 /* Fill 1st fragment */
234 untd_hdr_1st = buf_itr;
235 buf_itr += sizeof(*untd_hdr_1st);
236 untd_hdr_set_type(&untd_hdr_1st->hdr, i1480u_PKT_FRAG_1ST);
237 untd_hdr_set_rx_tx(&untd_hdr_1st->hdr, 0);
238 untd_hdr_1st->hdr.len = cpu_to_le16(pl_size + sizeof(*wlp_tx_hdr));
239 untd_hdr_1st->fragment_len =
240 cpu_to_le16(pl_size_1st + sizeof(*wlp_tx_hdr));
241 memset(untd_hdr_1st->padding, 0, sizeof(untd_hdr_1st->padding));
242 /* Set up i1480 header info */
243 wlp_tx_hdr = wtx->wlp_tx_hdr = buf_itr;
244 buf_itr += sizeof(*wlp_tx_hdr);
245 /* Copy the first fragment */
246 memcpy(buf_itr, pl_itr, pl_size_1st);
247 pl_itr += pl_size_1st;
248 buf_itr += pl_size_1st;
249
250 /* Now do each remaining fragment */
251 result = -EINVAL;
252 while (pl_size_left > 0) {
253 if (buf_itr + sizeof(*untd_hdr_rst) - wtx->buf
254 > wtx->buf_size) {
255 printk(KERN_ERR "BUG: no space for header\n");
256 goto error_bug;
257 }
258 untd_hdr_rst = buf_itr;
259 buf_itr += sizeof(*untd_hdr_rst);
260 if (pl_size_left > i1480u_MAX_PL_SIZE) {
261 frg_pl_size = i1480u_MAX_PL_SIZE;
262 untd_hdr_set_type(&untd_hdr_rst->hdr, i1480u_PKT_FRAG_NXT);
263 } else {
264 frg_pl_size = pl_size_left;
265 untd_hdr_set_type(&untd_hdr_rst->hdr, i1480u_PKT_FRAG_LST);
266 }
267 untd_hdr_set_rx_tx(&untd_hdr_rst->hdr, 0);
268 untd_hdr_rst->hdr.len = cpu_to_le16(frg_pl_size);
269 untd_hdr_rst->padding = 0;
270 if (buf_itr + frg_pl_size - wtx->buf
271 > wtx->buf_size) {
272 printk(KERN_ERR "BUG: no space for payload\n");
273 goto error_bug;
274 }
275 memcpy(buf_itr, pl_itr, frg_pl_size);
276 buf_itr += frg_pl_size;
277 pl_itr += frg_pl_size;
278 pl_size_left -= frg_pl_size;
279 }
280 dev_kfree_skb_irq(skb);
281 return 0;
282
283error_bug:
284 printk(KERN_ERR
285 "BUG: skb %u bytes\n"
286 "BUG: frg_pl_size %zd i1480u_MAX_FRG_SIZE %u\n"
287 "BUG: buf_itr %zu buf_size %zu pl_size_left %zu\n",
288 skb->len,
289 frg_pl_size, i1480u_MAX_FRG_SIZE,
290 buf_itr - wtx->buf, wtx->buf_size, pl_size_left);
291
292 kfree(wtx->buf);
293error_buf_alloc:
294 return result;
295}
296
297
298/*
299 * Given a buffer that fits in a single fragment, fill out a @wtx
300 * struct for transmitting it down the USB pipe.
301 *
302 * Uses the fact that we have space reserved in front of the skbuff
303 * for hardware headers :]
304 *
305 * This does not fill the i1480 TX header, it is left up to the
306 * caller to do that; you can get it from @wtx->wlp_tx_hdr.
307 *
308 * @pl: pointer to payload data
309 * @pl_size: size of the payuload
310 *
311 * This function does not consume the @skb.
312 */
313static
314int i1480u_tx_create_1(struct i1480u_tx *wtx, struct sk_buff *skb,
315 gfp_t gfp_mask)
316{
317 struct untd_hdr_cmp *untd_hdr_cmp;
318 struct wlp_tx_hdr *wlp_tx_hdr;
319
320 wtx->buf = NULL;
321 wtx->skb = skb;
322 BUG_ON(skb_headroom(skb) < sizeof(*wlp_tx_hdr));
323 wlp_tx_hdr = (void *) __skb_push(skb, sizeof(*wlp_tx_hdr));
324 wtx->wlp_tx_hdr = wlp_tx_hdr;
325 BUG_ON(skb_headroom(skb) < sizeof(*untd_hdr_cmp));
326 untd_hdr_cmp = (void *) __skb_push(skb, sizeof(*untd_hdr_cmp));
327
328 untd_hdr_set_type(&untd_hdr_cmp->hdr, i1480u_PKT_FRAG_CMP);
329 untd_hdr_set_rx_tx(&untd_hdr_cmp->hdr, 0);
330 untd_hdr_cmp->hdr.len = cpu_to_le16(skb->len - sizeof(*untd_hdr_cmp));
331 untd_hdr_cmp->padding = 0;
332 return 0;
333}
334
335
336/*
337 * Given a skb to transmit, massage it to become palatable for the TX pipe
338 *
339 * This will break the buffer in chunks smaller than
340 * i1480u_MAX_FRG_SIZE and add proper headers to each.
341 *
342 * 1st header \
343 * i1480 tx header | fragment 1
344 * fragment data /
345 * nxt header \ fragment 2
346 * fragment data /
347 * ..
348 * ..
349 * last header \ fragment 3
350 * last fragment data /
351 *
352 * Each fragment will be always smaller or equal to i1480u_MAX_FRG_SIZE.
353 *
354 * If the first fragment is smaller than i1480u_MAX_FRG_SIZE, then the
355 * following is composed:
356 *
357 * complete header \
358 * i1480 tx header | single fragment
359 * packet data /
360 *
361 * We were going to use s/g support, but because the interface is
362 * synch and at the end there is plenty of overhead to do it, it
363 * didn't seem that worth for data that is going to be smaller than
364 * one page.
365 */
366static
367struct i1480u_tx *i1480u_tx_create(struct i1480u *i1480u,
368 struct sk_buff *skb, gfp_t gfp_mask)
369{
370 int result;
371 struct usb_endpoint_descriptor *epd;
372 int usb_pipe;
373 unsigned long flags;
374
375 struct i1480u_tx *wtx;
376 const size_t pl_max_size =
377 i1480u_MAX_FRG_SIZE - sizeof(struct untd_hdr_cmp)
378 - sizeof(struct wlp_tx_hdr);
379
380 wtx = kmalloc(sizeof(*wtx), gfp_mask);
381 if (wtx == NULL)
382 goto error_wtx_alloc;
383 wtx->urb = usb_alloc_urb(0, gfp_mask);
384 if (wtx->urb == NULL)
385 goto error_urb_alloc;
386 epd = &i1480u->usb_iface->cur_altsetting->endpoint[2].desc;
387 usb_pipe = usb_sndbulkpipe(i1480u->usb_dev, epd->bEndpointAddress);
388 /* Fits in a single complete packet or need to split? */
389 if (skb->len > pl_max_size) {
390 result = i1480u_tx_create_n(wtx, skb, gfp_mask);
391 if (result < 0)
392 goto error_create;
393 usb_fill_bulk_urb(wtx->urb, i1480u->usb_dev, usb_pipe,
394 wtx->buf, wtx->buf_size, i1480u_tx_cb, wtx);
395 } else {
396 result = i1480u_tx_create_1(wtx, skb, gfp_mask);
397 if (result < 0)
398 goto error_create;
399 usb_fill_bulk_urb(wtx->urb, i1480u->usb_dev, usb_pipe,
400 skb->data, skb->len, i1480u_tx_cb, wtx);
401 }
402 spin_lock_irqsave(&i1480u->tx_list_lock, flags);
403 list_add(&wtx->list_node, &i1480u->tx_list);
404 spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
405 return wtx;
406
407error_create:
408 kfree(wtx->urb);
409error_urb_alloc:
410 kfree(wtx);
411error_wtx_alloc:
412 return NULL;
413}
414
415/*
416 * Actual fragmentation and transmission of frame
417 *
418 * @wlp: WLP substack data structure
419 * @skb: To be transmitted
420 * @dst: Device address of destination
421 * @returns: 0 on success, <0 on failure
422 *
423 * This function can also be called directly (not just from
424 * hard_start_xmit), so we also check here if the interface is up before
425 * taking sending anything.
426 */
427int i1480u_xmit_frame(struct wlp *wlp, struct sk_buff *skb,
428 struct uwb_dev_addr *dst)
429{
430 int result = -ENXIO;
431 struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp);
432 struct device *dev = &i1480u->usb_iface->dev;
433 struct net_device *net_dev = i1480u->net_dev;
434 struct i1480u_tx *wtx;
435 struct wlp_tx_hdr *wlp_tx_hdr;
436 static unsigned char dev_bcast[2] = { 0xff, 0xff };
437
438 BUG_ON(i1480u->wlp.rc == NULL);
439 if ((net_dev->flags & IFF_UP) == 0)
440 goto out;
441 result = -EBUSY;
442 if (atomic_read(&i1480u->tx_inflight.count) >= i1480u->tx_inflight.max) {
443 netif_stop_queue(net_dev);
444 goto error_max_inflight;
445 }
446 result = -ENOMEM;
447 wtx = i1480u_tx_create(i1480u, skb, GFP_ATOMIC);
448 if (unlikely(wtx == NULL)) {
449 if (printk_ratelimit())
450 dev_err(dev, "TX: no memory for WLP TX URB,"
451 "dropping packet (in flight %d)\n",
452 atomic_read(&i1480u->tx_inflight.count));
453 netif_stop_queue(net_dev);
454 goto error_wtx_alloc;
455 }
456 wtx->i1480u = i1480u;
457 /* Fill out the i1480 header; @i1480u->def_tx_hdr read without
458 * locking. We do so because they are kind of orthogonal to
459 * each other (and thus not changed in an atomic batch).
460 * The ETH header is right after the WLP TX header. */
461 wlp_tx_hdr = wtx->wlp_tx_hdr;
462 *wlp_tx_hdr = i1480u->options.def_tx_hdr;
463 wlp_tx_hdr->dstaddr = *dst;
464 if (!memcmp(&wlp_tx_hdr->dstaddr, dev_bcast, sizeof(dev_bcast))
465 && (wlp_tx_hdr_delivery_id_type(wlp_tx_hdr) & WLP_DRP)) {
466 /*Broadcast message directed to DRP host. Send as best effort
467 * on PCA. */
468 wlp_tx_hdr_set_delivery_id_type(wlp_tx_hdr, i1480u->options.pca_base_priority);
469 }
470
471 result = usb_submit_urb(wtx->urb, GFP_ATOMIC); /* Go baby */
472 if (result < 0) {
473 dev_err(dev, "TX: cannot submit URB: %d\n", result);
474 /* We leave the freeing of skb to calling function */
475 wtx->skb = NULL;
476 goto error_tx_urb_submit;
477 }
478 atomic_inc(&i1480u->tx_inflight.count);
479 net_dev->trans_start = jiffies;
480 return result;
481
482error_tx_urb_submit:
483 i1480u_tx_destroy(i1480u, wtx);
484error_wtx_alloc:
485error_max_inflight:
486out:
487 return result;
488}
489
490
491/*
492 * Transmit an skb Called when an skbuf has to be transmitted
493 *
494 * The skb is first passed to WLP substack to ensure this is a valid
495 * frame. If valid the device address of destination will be filled and
496 * the WLP header prepended to the skb. If this step fails we fake sending
497 * the frame, if we return an error the network stack will just keep trying.
498 *
499 * Broadcast frames inside a WSS needs to be treated special as multicast is
500 * not supported. A broadcast frame is sent as unicast to each member of the
501 * WSS - this is done by the WLP substack when it finds a broadcast frame.
502 * So, we test if the WLP substack took over the skb and only transmit it
503 * if it has not (been taken over).
504 *
505 * @net_dev->xmit_lock is held
506 */
507netdev_tx_t i1480u_hard_start_xmit(struct sk_buff *skb,
508 struct net_device *net_dev)
509{
510 int result;
511 struct i1480u *i1480u = netdev_priv(net_dev);
512 struct device *dev = &i1480u->usb_iface->dev;
513 struct uwb_dev_addr dst;
514
515 if ((net_dev->flags & IFF_UP) == 0)
516 goto error;
517 result = wlp_prepare_tx_frame(dev, &i1480u->wlp, skb, &dst);
518 if (result < 0) {
519 dev_err(dev, "WLP verification of TX frame failed (%d). "
520 "Dropping packet.\n", result);
521 goto error;
522 } else if (result == 1) {
523 /* trans_start time will be set when WLP actually transmits
524 * the frame */
525 goto out;
526 }
527 result = i1480u_xmit_frame(&i1480u->wlp, skb, &dst);
528 if (result < 0) {
529 dev_err(dev, "Frame TX failed (%d).\n", result);
530 goto error;
531 }
532 return NETDEV_TX_OK;
533error:
534 dev_kfree_skb_any(skb);
535 net_dev->stats.tx_dropped++;
536out:
537 return NETDEV_TX_OK;
538}
539
540
541/*
542 * Called when a pkt transmission doesn't complete in a reasonable period
543 * Device reset may sleep - do it outside of interrupt context (delayed)
544 */
545void i1480u_tx_timeout(struct net_device *net_dev)
546{
547 struct i1480u *i1480u = netdev_priv(net_dev);
548
549 wlp_reset_all(&i1480u->wlp);
550}
551
552
553void i1480u_tx_release(struct i1480u *i1480u)
554{
555 unsigned long flags;
556 struct i1480u_tx *wtx, *next;
557 int count = 0, empty;
558
559 spin_lock_irqsave(&i1480u->tx_list_lock, flags);
560 list_for_each_entry_safe(wtx, next, &i1480u->tx_list, list_node) {
561 count++;
562 usb_unlink_urb(wtx->urb);
563 }
564 spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
565 count = count*10; /* i1480ut 200ms per unlinked urb (intervals of 20ms) */
566 /*
567 * We don't like this sollution too much (dirty as it is), but
568 * it is cheaper than putting a refcount on each i1480u_tx and
569 * i1480uting for all of them to go away...
570 *
571 * Called when no more packets can be added to tx_list
572 * so can i1480ut for it to be empty.
573 */
574 while (1) {
575 spin_lock_irqsave(&i1480u->tx_list_lock, flags);
576 empty = list_empty(&i1480u->tx_list);
577 spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
578 if (empty)
579 break;
580 count--;
581 BUG_ON(count == 0);
582 msleep(20);
583 }
584}
diff --git a/drivers/uwb/wlp/Makefile b/drivers/uwb/wlp/Makefile
deleted file mode 100644
index c72c11db5b1b..000000000000
--- a/drivers/uwb/wlp/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
1obj-$(CONFIG_UWB_WLP) := wlp.o
2
3wlp-objs := \
4 driver.o \
5 eda.o \
6 messages.o \
7 sysfs.o \
8 txrx.o \
9 wlp-lc.o \
10 wss-lc.o
diff --git a/drivers/uwb/wlp/driver.c b/drivers/uwb/wlp/driver.c
deleted file mode 100644
index cb8d699b6a67..000000000000
--- a/drivers/uwb/wlp/driver.c
+++ /dev/null
@@ -1,43 +0,0 @@
1/*
2 * WiMedia Logical Link Control Protocol (WLP)
3 *
4 * Copyright (C) 2007 Intel Corporation
5 * Reinette Chatre <reinette.chatre@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * Life cycle of WLP substack
23 *
24 * FIXME: Docs
25 */
26
27#include <linux/module.h>
28
29static int __init wlp_subsys_init(void)
30{
31 return 0;
32}
33module_init(wlp_subsys_init);
34
35static void __exit wlp_subsys_exit(void)
36{
37 return;
38}
39module_exit(wlp_subsys_exit);
40
41MODULE_AUTHOR("Reinette Chatre <reinette.chatre@intel.com>");
42MODULE_DESCRIPTION("WiMedia Logical Link Control Protocol (WLP)");
43MODULE_LICENSE("GPL");
diff --git a/drivers/uwb/wlp/eda.c b/drivers/uwb/wlp/eda.c
deleted file mode 100644
index 086fc0cf9401..000000000000
--- a/drivers/uwb/wlp/eda.c
+++ /dev/null
@@ -1,415 +0,0 @@
1/*
2 * WUSB Wire Adapter: WLP interface
3 * Ethernet to device address cache
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 * We need to be able to map ethernet addresses to device addresses
24 * and back because there is not explicit relationship between the eth
25 * addresses used in the ETH frames and the device addresses (no, it
26 * would not have been simpler to force as ETH address the MBOA MAC
27 * address...no, not at all :).
28 *
29 * A device has one MBOA MAC address and one device address. It is possible
30 * for a device to have more than one virtual MAC address (although a
31 * virtual address can be the same as the MBOA MAC address). The device
32 * address is guaranteed to be unique among the devices in the extended
33 * beacon group (see ECMA 17.1.1). We thus use the device address as index
34 * to this cache. We do allow searching based on virtual address as this
35 * is how Ethernet frames will be addressed.
36 *
37 * We need to support virtual EUI-48. Although, right now the virtual
38 * EUI-48 will always be the same as the MAC SAP address. The EDA cache
39 * entry thus contains a MAC SAP address as well as the virtual address
40 * (used to map the network stack address to a neighbor). When we move
41 * to support more than one virtual MAC on a host then this organization
42 * will have to change. Perhaps a neighbor has a list of WSSs, each with a
43 * tag and virtual EUI-48.
44 *
45 * On data transmission
46 * it is used to determine if the neighbor is connected and what WSS it
47 * belongs to. With this we know what tag to add to the WLP frame. Storing
48 * the WSS in the EDA cache may be overkill because we only support one
49 * WSS. Hopefully we will support more than one WSS at some point.
50 * On data reception it is used to determine the WSS based on
51 * the tag and address of the transmitting neighbor.
52 */
53
54#include <linux/netdevice.h>
55#include <linux/etherdevice.h>
56#include <linux/slab.h>
57#include <linux/wlp.h>
58#include "wlp-internal.h"
59
60
61/* FIXME: cache is not purged, only on device close */
62
63/* FIXME: does not scale, change to dynamic array */
64
65/*
66 * Initialize the EDA cache
67 *
68 * @returns 0 if ok, < 0 errno code on error
69 *
70 * Call when the interface is being brought up
71 *
72 * NOTE: Keep it as a separate function as the implementation will
73 * change and be more complex.
74 */
75void wlp_eda_init(struct wlp_eda *eda)
76{
77 INIT_LIST_HEAD(&eda->cache);
78 spin_lock_init(&eda->lock);
79}
80
81/*
82 * Release the EDA cache
83 *
84 * @returns 0 if ok, < 0 errno code on error
85 *
86 * Called when the interface is brought down
87 */
88void wlp_eda_release(struct wlp_eda *eda)
89{
90 unsigned long flags;
91 struct wlp_eda_node *itr, *next;
92
93 spin_lock_irqsave(&eda->lock, flags);
94 list_for_each_entry_safe(itr, next, &eda->cache, list_node) {
95 list_del(&itr->list_node);
96 kfree(itr);
97 }
98 spin_unlock_irqrestore(&eda->lock, flags);
99}
100
101/*
102 * Add an address mapping
103 *
104 * @returns 0 if ok, < 0 errno code on error
105 *
106 * An address mapping is initially created when the neighbor device is seen
107 * for the first time (it is "onair"). At this time the neighbor is not
108 * connected or associated with a WSS so we only populate the Ethernet and
109 * Device address fields.
110 *
111 */
112int wlp_eda_create_node(struct wlp_eda *eda,
113 const unsigned char eth_addr[ETH_ALEN],
114 const struct uwb_dev_addr *dev_addr)
115{
116 int result = 0;
117 struct wlp_eda_node *itr;
118 unsigned long flags;
119
120 BUG_ON(dev_addr == NULL || eth_addr == NULL);
121 spin_lock_irqsave(&eda->lock, flags);
122 list_for_each_entry(itr, &eda->cache, list_node) {
123 if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
124 printk(KERN_ERR "EDA cache already contains entry "
125 "for neighbor %02x:%02x\n",
126 dev_addr->data[1], dev_addr->data[0]);
127 result = -EEXIST;
128 goto out_unlock;
129 }
130 }
131 itr = kzalloc(sizeof(*itr), GFP_ATOMIC);
132 if (itr != NULL) {
133 memcpy(itr->eth_addr, eth_addr, sizeof(itr->eth_addr));
134 itr->dev_addr = *dev_addr;
135 list_add(&itr->list_node, &eda->cache);
136 } else
137 result = -ENOMEM;
138out_unlock:
139 spin_unlock_irqrestore(&eda->lock, flags);
140 return result;
141}
142
143/*
144 * Remove entry from EDA cache
145 *
146 * This is done when the device goes off air.
147 */
148void wlp_eda_rm_node(struct wlp_eda *eda, const struct uwb_dev_addr *dev_addr)
149{
150 struct wlp_eda_node *itr, *next;
151 unsigned long flags;
152
153 spin_lock_irqsave(&eda->lock, flags);
154 list_for_each_entry_safe(itr, next, &eda->cache, list_node) {
155 if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
156 list_del(&itr->list_node);
157 kfree(itr);
158 break;
159 }
160 }
161 spin_unlock_irqrestore(&eda->lock, flags);
162}
163
164/*
165 * Update an address mapping
166 *
167 * @returns 0 if ok, < 0 errno code on error
168 */
169int wlp_eda_update_node(struct wlp_eda *eda,
170 const struct uwb_dev_addr *dev_addr,
171 struct wlp_wss *wss,
172 const unsigned char virt_addr[ETH_ALEN],
173 const u8 tag, const enum wlp_wss_connect state)
174{
175 int result = -ENOENT;
176 struct wlp_eda_node *itr;
177 unsigned long flags;
178
179 spin_lock_irqsave(&eda->lock, flags);
180 list_for_each_entry(itr, &eda->cache, list_node) {
181 if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
182 /* Found it, update it */
183 itr->wss = wss;
184 memcpy(itr->virt_addr, virt_addr,
185 sizeof(itr->virt_addr));
186 itr->tag = tag;
187 itr->state = state;
188 result = 0;
189 goto out_unlock;
190 }
191 }
192 /* Not found */
193out_unlock:
194 spin_unlock_irqrestore(&eda->lock, flags);
195 return result;
196}
197
198/*
199 * Update only state field of an address mapping
200 *
201 * @returns 0 if ok, < 0 errno code on error
202 */
203int wlp_eda_update_node_state(struct wlp_eda *eda,
204 const struct uwb_dev_addr *dev_addr,
205 const enum wlp_wss_connect state)
206{
207 int result = -ENOENT;
208 struct wlp_eda_node *itr;
209 unsigned long flags;
210
211 spin_lock_irqsave(&eda->lock, flags);
212 list_for_each_entry(itr, &eda->cache, list_node) {
213 if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
214 /* Found it, update it */
215 itr->state = state;
216 result = 0;
217 goto out_unlock;
218 }
219 }
220 /* Not found */
221out_unlock:
222 spin_unlock_irqrestore(&eda->lock, flags);
223 return result;
224}
225
226/*
227 * Return contents of EDA cache entry
228 *
229 * @dev_addr: index to EDA cache
230 * @eda_entry: pointer to where contents of EDA cache will be copied
231 */
232int wlp_copy_eda_node(struct wlp_eda *eda, struct uwb_dev_addr *dev_addr,
233 struct wlp_eda_node *eda_entry)
234{
235 int result = -ENOENT;
236 struct wlp_eda_node *itr;
237 unsigned long flags;
238
239 spin_lock_irqsave(&eda->lock, flags);
240 list_for_each_entry(itr, &eda->cache, list_node) {
241 if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
242 *eda_entry = *itr;
243 result = 0;
244 goto out_unlock;
245 }
246 }
247 /* Not found */
248out_unlock:
249 spin_unlock_irqrestore(&eda->lock, flags);
250 return result;
251}
252
253/*
254 * Execute function for every element in the cache
255 *
256 * @function: function to execute on element of cache (must be atomic)
257 * @priv: private data of function
258 * @returns: result of first function that failed, or last function
259 * executed if no function failed.
260 *
261 * Stop executing when function returns error for any element in cache.
262 *
263 * IMPORTANT: We are using a spinlock here: the function executed on each
264 * element has to be atomic.
265 */
266int wlp_eda_for_each(struct wlp_eda *eda, wlp_eda_for_each_f function,
267 void *priv)
268{
269 int result = 0;
270 struct wlp *wlp = container_of(eda, struct wlp, eda);
271 struct wlp_eda_node *entry;
272 unsigned long flags;
273
274 spin_lock_irqsave(&eda->lock, flags);
275 list_for_each_entry(entry, &eda->cache, list_node) {
276 result = (*function)(wlp, entry, priv);
277 if (result < 0)
278 break;
279 }
280 spin_unlock_irqrestore(&eda->lock, flags);
281 return result;
282}
283
284/*
285 * Execute function for single element in the cache (return dev addr)
286 *
287 * @virt_addr: index into EDA cache used to determine which element to
288 * execute the function on
289 * @dev_addr: device address of element in cache will be returned using
290 * @dev_addr
291 * @function: function to execute on element of cache (must be atomic)
292 * @priv: private data of function
293 * @returns: result of function
294 *
295 * IMPORTANT: We are using a spinlock here: the function executed on the
296 * element has to be atomic.
297 */
298int wlp_eda_for_virtual(struct wlp_eda *eda,
299 const unsigned char virt_addr[ETH_ALEN],
300 struct uwb_dev_addr *dev_addr,
301 wlp_eda_for_each_f function,
302 void *priv)
303{
304 int result = 0;
305 struct wlp *wlp = container_of(eda, struct wlp, eda);
306 struct wlp_eda_node *itr;
307 unsigned long flags;
308 int found = 0;
309
310 spin_lock_irqsave(&eda->lock, flags);
311 list_for_each_entry(itr, &eda->cache, list_node) {
312 if (!memcmp(itr->virt_addr, virt_addr,
313 sizeof(itr->virt_addr))) {
314 result = (*function)(wlp, itr, priv);
315 *dev_addr = itr->dev_addr;
316 found = 1;
317 break;
318 }
319 }
320 if (!found)
321 result = -ENODEV;
322 spin_unlock_irqrestore(&eda->lock, flags);
323 return result;
324}
325
326static const char *__wlp_wss_connect_state[] = { "WLP_WSS_UNCONNECTED",
327 "WLP_WSS_CONNECTED",
328 "WLP_WSS_CONNECT_FAILED",
329};
330
331static const char *wlp_wss_connect_state_str(unsigned id)
332{
333 if (id >= ARRAY_SIZE(__wlp_wss_connect_state))
334 return "unknown WSS connection state";
335 return __wlp_wss_connect_state[id];
336}
337
338/*
339 * View EDA cache from user space
340 *
341 * A debugging feature to give user visibility into the EDA cache. Also
342 * used to display members of WSS to user (called from wlp_wss_members_show())
343 */
344ssize_t wlp_eda_show(struct wlp *wlp, char *buf)
345{
346 ssize_t result = 0;
347 struct wlp_eda_node *entry;
348 unsigned long flags;
349 struct wlp_eda *eda = &wlp->eda;
350 spin_lock_irqsave(&eda->lock, flags);
351 result = scnprintf(buf, PAGE_SIZE, "#eth_addr dev_addr wss_ptr "
352 "tag state virt_addr\n");
353 list_for_each_entry(entry, &eda->cache, list_node) {
354 result += scnprintf(buf + result, PAGE_SIZE - result,
355 "%pM %02x:%02x %p 0x%02x %s %pM\n",
356 entry->eth_addr,
357 entry->dev_addr.data[1],
358 entry->dev_addr.data[0], entry->wss,
359 entry->tag,
360 wlp_wss_connect_state_str(entry->state),
361 entry->virt_addr);
362 if (result >= PAGE_SIZE)
363 break;
364 }
365 spin_unlock_irqrestore(&eda->lock, flags);
366 return result;
367}
368EXPORT_SYMBOL_GPL(wlp_eda_show);
369
370/*
371 * Add new EDA cache entry based on user input in sysfs
372 *
373 * Should only be used for debugging.
374 *
375 * The WSS is assumed to be the only WSS supported. This needs to be
376 * redesigned when we support more than one WSS.
377 */
378ssize_t wlp_eda_store(struct wlp *wlp, const char *buf, size_t size)
379{
380 ssize_t result;
381 struct wlp_eda *eda = &wlp->eda;
382 u8 eth_addr[6];
383 struct uwb_dev_addr dev_addr;
384 u8 tag;
385 unsigned state;
386
387 result = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx "
388 "%02hhx:%02hhx %02hhx %u\n",
389 &eth_addr[0], &eth_addr[1],
390 &eth_addr[2], &eth_addr[3],
391 &eth_addr[4], &eth_addr[5],
392 &dev_addr.data[1], &dev_addr.data[0], &tag, &state);
393 switch (result) {
394 case 6: /* no dev addr specified -- remove entry NOT IMPLEMENTED */
395 /*result = wlp_eda_rm(eda, eth_addr, &dev_addr);*/
396 result = -ENOSYS;
397 break;
398 case 10:
399 state = state >= 1 ? 1 : 0;
400 result = wlp_eda_create_node(eda, eth_addr, &dev_addr);
401 if (result < 0 && result != -EEXIST)
402 goto error;
403 /* Set virtual addr to be same as MAC */
404 result = wlp_eda_update_node(eda, &dev_addr, &wlp->wss,
405 eth_addr, tag, state);
406 if (result < 0)
407 goto error;
408 break;
409 default: /* bad format */
410 result = -EINVAL;
411 }
412error:
413 return result < 0 ? result : size;
414}
415EXPORT_SYMBOL_GPL(wlp_eda_store);
diff --git a/drivers/uwb/wlp/messages.c b/drivers/uwb/wlp/messages.c
deleted file mode 100644
index 3a8e033dce21..000000000000
--- a/drivers/uwb/wlp/messages.c
+++ /dev/null
@@ -1,1798 +0,0 @@
1/*
2 * WiMedia Logical Link Control Protocol (WLP)
3 * Message construction and parsing
4 *
5 * Copyright (C) 2007 Intel Corporation
6 * Reinette Chatre <reinette.chatre@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
26#include <linux/wlp.h>
27#include <linux/slab.h>
28
29#include "wlp-internal.h"
30
31static
32const char *__wlp_assoc_frame[] = {
33 [WLP_ASSOC_D1] = "WLP_ASSOC_D1",
34 [WLP_ASSOC_D2] = "WLP_ASSOC_D2",
35 [WLP_ASSOC_M1] = "WLP_ASSOC_M1",
36 [WLP_ASSOC_M2] = "WLP_ASSOC_M2",
37 [WLP_ASSOC_M3] = "WLP_ASSOC_M3",
38 [WLP_ASSOC_M4] = "WLP_ASSOC_M4",
39 [WLP_ASSOC_M5] = "WLP_ASSOC_M5",
40 [WLP_ASSOC_M6] = "WLP_ASSOC_M6",
41 [WLP_ASSOC_M7] = "WLP_ASSOC_M7",
42 [WLP_ASSOC_M8] = "WLP_ASSOC_M8",
43 [WLP_ASSOC_F0] = "WLP_ASSOC_F0",
44 [WLP_ASSOC_E1] = "WLP_ASSOC_E1",
45 [WLP_ASSOC_E2] = "WLP_ASSOC_E2",
46 [WLP_ASSOC_C1] = "WLP_ASSOC_C1",
47 [WLP_ASSOC_C2] = "WLP_ASSOC_C2",
48 [WLP_ASSOC_C3] = "WLP_ASSOC_C3",
49 [WLP_ASSOC_C4] = "WLP_ASSOC_C4",
50};
51
52static const char *wlp_assoc_frame_str(unsigned id)
53{
54 if (id >= ARRAY_SIZE(__wlp_assoc_frame))
55 return "unknown association frame";
56 return __wlp_assoc_frame[id];
57}
58
59static const char *__wlp_assc_error[] = {
60 "none",
61 "Authenticator Failure",
62 "Rogue activity suspected",
63 "Device busy",
64 "Setup Locked",
65 "Registrar not ready",
66 "Invalid WSS selection",
67 "Message timeout",
68 "Enrollment session timeout",
69 "Device password invalid",
70 "Unsupported version",
71 "Internal error",
72 "Undefined error",
73 "Numeric comparison failure",
74 "Waiting for user input",
75};
76
77static const char *wlp_assc_error_str(unsigned id)
78{
79 if (id >= ARRAY_SIZE(__wlp_assc_error))
80 return "unknown WLP association error";
81 return __wlp_assc_error[id];
82}
83
84static inline void wlp_set_attr_hdr(struct wlp_attr_hdr *hdr, unsigned type,
85 size_t len)
86{
87 hdr->type = cpu_to_le16(type);
88 hdr->length = cpu_to_le16(len);
89}
90
91/*
92 * Populate fields of a constant sized attribute
93 *
94 * @returns: total size of attribute including size of new value
95 *
96 * We have two instances of this function (wlp_pset and wlp_set): one takes
97 * the value as a parameter, the other takes a pointer to the value as
98 * parameter. They thus only differ in how the value is assigned to the
99 * attribute.
100 *
101 * We use sizeof(*attr) - sizeof(struct wlp_attr_hdr) instead of
102 * sizeof(type) to be able to use this same code for the structures that
103 * contain 8bit enum values and be able to deal with pointer types.
104 */
105#define wlp_set(type, type_code, name) \
106static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \
107{ \
108 wlp_set_attr_hdr(&attr->hdr, type_code, \
109 sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \
110 attr->name = value; \
111 return sizeof(*attr); \
112}
113
114#define wlp_pset(type, type_code, name) \
115static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \
116{ \
117 wlp_set_attr_hdr(&attr->hdr, type_code, \
118 sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \
119 attr->name = *value; \
120 return sizeof(*attr); \
121}
122
123/**
124 * Populate fields of a variable attribute
125 *
126 * @returns: total size of attribute including size of new value
127 *
128 * Provided with a pointer to the memory area reserved for the
129 * attribute structure, the field is populated with the value. The
130 * reserved memory has to contain enough space for the value.
131 */
132#define wlp_vset(type, type_code, name) \
133static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value, \
134 size_t len) \
135{ \
136 wlp_set_attr_hdr(&attr->hdr, type_code, len); \
137 memcpy(attr->name, value, len); \
138 return sizeof(*attr) + len; \
139}
140
141wlp_vset(char *, WLP_ATTR_DEV_NAME, dev_name)
142wlp_vset(char *, WLP_ATTR_MANUF, manufacturer)
143wlp_set(enum wlp_assoc_type, WLP_ATTR_MSG_TYPE, msg_type)
144wlp_vset(char *, WLP_ATTR_MODEL_NAME, model_name)
145wlp_vset(char *, WLP_ATTR_MODEL_NR, model_nr)
146wlp_vset(char *, WLP_ATTR_SERIAL, serial)
147wlp_vset(char *, WLP_ATTR_WSS_NAME, wss_name)
148wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_E, uuid_e)
149wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_R, uuid_r)
150wlp_pset(struct wlp_uuid *, WLP_ATTR_WSSID, wssid)
151wlp_pset(struct wlp_dev_type *, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type)
152/*wlp_pset(struct wlp_dev_type *, WLP_ATTR_SEC_DEV_TYPE, sec_dev_type)*/
153wlp_set(u8, WLP_ATTR_WLP_VER, version)
154wlp_set(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err)
155wlp_set(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd)
156wlp_set(u8, WLP_ATTR_ACC_ENRL, accept_enrl)
157wlp_set(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status)
158wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_BCAST, wss_bcast)
159wlp_pset(struct wlp_nonce *, WLP_ATTR_ENRL_NONCE, enonce)
160wlp_pset(struct wlp_nonce *, WLP_ATTR_REG_NONCE, rnonce)
161wlp_set(u8, WLP_ATTR_WSS_TAG, wss_tag)
162wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_VIRT, wss_virt)
163
164/**
165 * Fill in the WSS information attributes
166 *
167 * We currently only support one WSS, and this is assumed in this function
168 * that can populate only one WSS information attribute.
169 */
170static size_t wlp_set_wss_info(struct wlp_attr_wss_info *attr,
171 struct wlp_wss *wss)
172{
173 size_t datalen;
174 void *ptr = attr->wss_info;
175 size_t used = sizeof(*attr);
176
177 datalen = sizeof(struct wlp_wss_info) + strlen(wss->name);
178 wlp_set_attr_hdr(&attr->hdr, WLP_ATTR_WSS_INFO, datalen);
179 used = wlp_set_wssid(ptr, &wss->wssid);
180 used += wlp_set_wss_name(ptr + used, wss->name, strlen(wss->name));
181 used += wlp_set_accept_enrl(ptr + used, wss->accept_enroll);
182 used += wlp_set_wss_sec_status(ptr + used, wss->secure_status);
183 used += wlp_set_wss_bcast(ptr + used, &wss->bcast);
184 return sizeof(*attr) + used;
185}
186
187/**
188 * Verify attribute header
189 *
190 * @hdr: Pointer to attribute header that will be verified.
191 * @type: Expected attribute type.
192 * @len: Expected length of attribute value (excluding header).
193 *
194 * Most attribute values have a known length even when they do have a
195 * length field. This knowledge can be used via this function to verify
196 * that the length field matches the expected value.
197 */
198static int wlp_check_attr_hdr(struct wlp *wlp, struct wlp_attr_hdr *hdr,
199 enum wlp_attr_type type, unsigned len)
200{
201 struct device *dev = &wlp->rc->uwb_dev.dev;
202
203 if (le16_to_cpu(hdr->type) != type) {
204 dev_err(dev, "WLP: unexpected header type. Expected "
205 "%u, got %u.\n", type, le16_to_cpu(hdr->type));
206 return -EINVAL;
207 }
208 if (le16_to_cpu(hdr->length) != len) {
209 dev_err(dev, "WLP: unexpected length in header. Expected "
210 "%u, got %u.\n", len, le16_to_cpu(hdr->length));
211 return -EINVAL;
212 }
213 return 0;
214}
215
216/**
217 * Check if header of WSS information attribute valid
218 *
219 * @returns: length of WSS attributes (value of length attribute field) if
220 * valid WSS information attribute found
221 * -ENODATA if no WSS information attribute found
222 * -EIO other error occured
223 *
224 * The WSS information attribute is optional. The function will be provided
225 * with a pointer to data that could _potentially_ be a WSS information
226 * attribute. If a valid WSS information attribute is found it will return
227 * 0, if no WSS information attribute is found it will return -ENODATA, and
228 * another error will be returned if it is a WSS information attribute, but
229 * some parsing failure occured.
230 */
231static int wlp_check_wss_info_attr_hdr(struct wlp *wlp,
232 struct wlp_attr_hdr *hdr, size_t buflen)
233{
234 struct device *dev = &wlp->rc->uwb_dev.dev;
235 size_t len;
236 int result = 0;
237
238 if (buflen < sizeof(*hdr)) {
239 dev_err(dev, "WLP: Not enough space in buffer to parse"
240 " WSS information attribute header.\n");
241 result = -EIO;
242 goto out;
243 }
244 if (le16_to_cpu(hdr->type) != WLP_ATTR_WSS_INFO) {
245 /* WSS information is optional */
246 result = -ENODATA;
247 goto out;
248 }
249 len = le16_to_cpu(hdr->length);
250 if (buflen < sizeof(*hdr) + len) {
251 dev_err(dev, "WLP: Not enough space in buffer to parse "
252 "variable data. Got %d, expected %d.\n",
253 (int)buflen, (int)(sizeof(*hdr) + len));
254 result = -EIO;
255 goto out;
256 }
257 result = len;
258out:
259 return result;
260}
261
262
263static ssize_t wlp_get_attribute(struct wlp *wlp, u16 type_code,
264 struct wlp_attr_hdr *attr_hdr, void *value, ssize_t value_len,
265 ssize_t buflen)
266{
267 struct device *dev = &wlp->rc->uwb_dev.dev;
268 ssize_t attr_len = sizeof(*attr_hdr) + value_len;
269 if (buflen < 0)
270 return -EINVAL;
271 if (buflen < attr_len) {
272 dev_err(dev, "WLP: Not enough space in buffer to parse"
273 " attribute field. Need %d, received %zu\n",
274 (int)attr_len, buflen);
275 return -EIO;
276 }
277 if (wlp_check_attr_hdr(wlp, attr_hdr, type_code, value_len) < 0) {
278 dev_err(dev, "WLP: Header verification failed. \n");
279 return -EINVAL;
280 }
281 memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), value_len);
282 return attr_len;
283}
284
285static ssize_t wlp_vget_attribute(struct wlp *wlp, u16 type_code,
286 struct wlp_attr_hdr *attr_hdr, void *value, ssize_t max_value_len,
287 ssize_t buflen)
288{
289 struct device *dev = &wlp->rc->uwb_dev.dev;
290 size_t len;
291 if (buflen < 0)
292 return -EINVAL;
293 if (buflen < sizeof(*attr_hdr)) {
294 dev_err(dev, "WLP: Not enough space in buffer to parse"
295 " header.\n");
296 return -EIO;
297 }
298 if (le16_to_cpu(attr_hdr->type) != type_code) {
299 dev_err(dev, "WLP: Unexpected attribute type. Got %u, "
300 "expected %u.\n", le16_to_cpu(attr_hdr->type),
301 type_code);
302 return -EINVAL;
303 }
304 len = le16_to_cpu(attr_hdr->length);
305 if (len > max_value_len) {
306 dev_err(dev, "WLP: Attribute larger than maximum "
307 "allowed. Received %zu, max is %d.\n", len,
308 (int)max_value_len);
309 return -EFBIG;
310 }
311 if (buflen < sizeof(*attr_hdr) + len) {
312 dev_err(dev, "WLP: Not enough space in buffer to parse "
313 "variable data.\n");
314 return -EIO;
315 }
316 memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), len);
317 return sizeof(*attr_hdr) + len;
318}
319
320/**
321 * Get value of attribute from fixed size attribute field.
322 *
323 * @attr: Pointer to attribute field.
324 * @value: Pointer to variable in which attribute value will be placed.
325 * @buflen: Size of buffer in which attribute field (including header)
326 * can be found.
327 * @returns: Amount of given buffer consumed by parsing for this attribute.
328 *
329 * The size and type of the value is known by the type of the attribute.
330 */
331#define wlp_get(type, type_code, name) \
332ssize_t wlp_get_##name(struct wlp *wlp, struct wlp_attr_##name *attr, \
333 type *value, ssize_t buflen) \
334{ \
335 return wlp_get_attribute(wlp, (type_code), &attr->hdr, \
336 value, sizeof(*value), buflen); \
337}
338
339#define wlp_get_sparse(type, type_code, name) \
340 static wlp_get(type, type_code, name)
341
342/**
343 * Get value of attribute from variable sized attribute field.
344 *
345 * @max: The maximum size of this attribute. This value is dictated by
346 * the maximum value from the WLP specification.
347 *
348 * @attr: Pointer to attribute field.
349 * @value: Pointer to variable that will contain the value. The memory
350 * must already have been allocated for this value.
351 * @buflen: Size of buffer in which attribute field (including header)
352 * can be found.
353 * @returns: Amount of given bufferconsumed by parsing for this attribute.
354 */
355#define wlp_vget(type_val, type_code, name, max) \
356static ssize_t wlp_get_##name(struct wlp *wlp, \
357 struct wlp_attr_##name *attr, \
358 type_val *value, ssize_t buflen) \
359{ \
360 return wlp_vget_attribute(wlp, (type_code), &attr->hdr, \
361 value, (max), buflen); \
362}
363
364wlp_get(u8, WLP_ATTR_WLP_VER, version)
365wlp_get_sparse(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd)
366wlp_get_sparse(struct wlp_dev_type, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type)
367wlp_get_sparse(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err)
368wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_E, uuid_e)
369wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_R, uuid_r)
370wlp_get(struct wlp_uuid, WLP_ATTR_WSSID, wssid)
371wlp_get_sparse(u8, WLP_ATTR_ACC_ENRL, accept_enrl)
372wlp_get_sparse(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status)
373wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_BCAST, wss_bcast)
374wlp_get_sparse(u8, WLP_ATTR_WSS_TAG, wss_tag)
375wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_VIRT, wss_virt)
376wlp_get_sparse(struct wlp_nonce, WLP_ATTR_ENRL_NONCE, enonce)
377wlp_get_sparse(struct wlp_nonce, WLP_ATTR_REG_NONCE, rnonce)
378
379/* The buffers for the device info attributes can be found in the
380 * wlp_device_info struct. These buffers contain one byte more than the
381 * max allowed by the spec - this is done to be able to add the
382 * terminating \0 for user display. This terminating byte is not required
383 * in the actual attribute field (because it has a length field) so the
384 * maximum allowed for this value is one less than its size in the
385 * structure.
386 */
387wlp_vget(char, WLP_ATTR_WSS_NAME, wss_name,
388 FIELD_SIZEOF(struct wlp_wss, name) - 1)
389wlp_vget(char, WLP_ATTR_DEV_NAME, dev_name,
390 FIELD_SIZEOF(struct wlp_device_info, name) - 1)
391wlp_vget(char, WLP_ATTR_MANUF, manufacturer,
392 FIELD_SIZEOF(struct wlp_device_info, manufacturer) - 1)
393wlp_vget(char, WLP_ATTR_MODEL_NAME, model_name,
394 FIELD_SIZEOF(struct wlp_device_info, model_name) - 1)
395wlp_vget(char, WLP_ATTR_MODEL_NR, model_nr,
396 FIELD_SIZEOF(struct wlp_device_info, model_nr) - 1)
397wlp_vget(char, WLP_ATTR_SERIAL, serial,
398 FIELD_SIZEOF(struct wlp_device_info, serial) - 1)
399
400/**
401 * Retrieve WSS Name, Accept enroll, Secure status, Broadcast from WSS info
402 *
403 * @attr: pointer to WSS name attribute in WSS information attribute field
404 * @info: structure that will be populated with data from WSS information
405 * field (WSS name, Accept enroll, secure status, broadcast address)
406 * @buflen: size of buffer
407 *
408 * Although the WSSID attribute forms part of the WSS info attribute it is
409 * retrieved separately and stored in a different location.
410 */
411static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp,
412 struct wlp_attr_hdr *attr,
413 struct wlp_wss_tmp_info *info,
414 ssize_t buflen)
415{
416 struct device *dev = &wlp->rc->uwb_dev.dev;
417 void *ptr = attr;
418 size_t used = 0;
419 ssize_t result = -EINVAL;
420
421 result = wlp_get_wss_name(wlp, ptr, info->name, buflen);
422 if (result < 0) {
423 dev_err(dev, "WLP: unable to obtain WSS name from "
424 "WSS info in D2 message.\n");
425 goto error_parse;
426 }
427 used += result;
428
429 result = wlp_get_accept_enrl(wlp, ptr + used, &info->accept_enroll,
430 buflen - used);
431 if (result < 0) {
432 dev_err(dev, "WLP: unable to obtain accepting "
433 "enrollment from WSS info in D2 message.\n");
434 goto error_parse;
435 }
436 if (info->accept_enroll != 0 && info->accept_enroll != 1) {
437 dev_err(dev, "WLP: invalid value for accepting "
438 "enrollment in D2 message.\n");
439 result = -EINVAL;
440 goto error_parse;
441 }
442 used += result;
443
444 result = wlp_get_wss_sec_status(wlp, ptr + used, &info->sec_status,
445 buflen - used);
446 if (result < 0) {
447 dev_err(dev, "WLP: unable to obtain secure "
448 "status from WSS info in D2 message.\n");
449 goto error_parse;
450 }
451 if (info->sec_status != 0 && info->sec_status != 1) {
452 dev_err(dev, "WLP: invalid value for secure "
453 "status in D2 message.\n");
454 result = -EINVAL;
455 goto error_parse;
456 }
457 used += result;
458
459 result = wlp_get_wss_bcast(wlp, ptr + used, &info->bcast,
460 buflen - used);
461 if (result < 0) {
462 dev_err(dev, "WLP: unable to obtain broadcast "
463 "address from WSS info in D2 message.\n");
464 goto error_parse;
465 }
466 used += result;
467 result = used;
468error_parse:
469 return result;
470}
471
472/**
473 * Create a new WSSID entry for the neighbor, allocate temporary storage
474 *
475 * Each neighbor can have many WSS active. We maintain a list of WSSIDs
476 * advertised by neighbor. During discovery we also cache information about
477 * these WSS in temporary storage.
478 *
479 * The temporary storage will be removed after it has been used (eg.
480 * displayed to user), the wssid element will be removed from the list when
481 * the neighbor is rediscovered or when it disappears.
482 */
483static struct wlp_wssid_e *wlp_create_wssid_e(struct wlp *wlp,
484 struct wlp_neighbor_e *neighbor)
485{
486 struct device *dev = &wlp->rc->uwb_dev.dev;
487 struct wlp_wssid_e *wssid_e;
488
489 wssid_e = kzalloc(sizeof(*wssid_e), GFP_KERNEL);
490 if (wssid_e == NULL) {
491 dev_err(dev, "WLP: unable to allocate memory "
492 "for WSS information.\n");
493 goto error_alloc;
494 }
495 wssid_e->info = kzalloc(sizeof(struct wlp_wss_tmp_info), GFP_KERNEL);
496 if (wssid_e->info == NULL) {
497 dev_err(dev, "WLP: unable to allocate memory "
498 "for temporary WSS information.\n");
499 kfree(wssid_e);
500 wssid_e = NULL;
501 goto error_alloc;
502 }
503 list_add(&wssid_e->node, &neighbor->wssid);
504error_alloc:
505 return wssid_e;
506}
507
508/**
509 * Parse WSS information attribute
510 *
511 * @attr: pointer to WSS information attribute header
512 * @buflen: size of buffer in which WSS information attribute appears
513 * @wssid: will place wssid from WSS info attribute in this location
514 * @wss_info: will place other information from WSS information attribute
515 * in this location
516 *
517 * memory for @wssid and @wss_info must be allocated when calling this
518 */
519static ssize_t wlp_get_wss_info(struct wlp *wlp, struct wlp_attr_wss_info *attr,
520 size_t buflen, struct wlp_uuid *wssid,
521 struct wlp_wss_tmp_info *wss_info)
522{
523 struct device *dev = &wlp->rc->uwb_dev.dev;
524 ssize_t result;
525 size_t len;
526 size_t used = 0;
527 void *ptr;
528
529 result = wlp_check_wss_info_attr_hdr(wlp, (struct wlp_attr_hdr *)attr,
530 buflen);
531 if (result < 0)
532 goto out;
533 len = result;
534 used = sizeof(*attr);
535 ptr = attr;
536
537 result = wlp_get_wssid(wlp, ptr + used, wssid, buflen - used);
538 if (result < 0) {
539 dev_err(dev, "WLP: unable to obtain WSSID from WSS info.\n");
540 goto out;
541 }
542 used += result;
543 result = wlp_get_wss_info_attrs(wlp, ptr + used, wss_info,
544 buflen - used);
545 if (result < 0) {
546 dev_err(dev, "WLP: unable to obtain WSS information "
547 "from WSS information attributes. \n");
548 goto out;
549 }
550 used += result;
551 if (len + sizeof(*attr) != used) {
552 dev_err(dev, "WLP: Amount of data parsed does not "
553 "match length field. Parsed %zu, length "
554 "field %zu. \n", used, len);
555 result = -EINVAL;
556 goto out;
557 }
558 result = used;
559out:
560 return result;
561}
562
563/**
564 * Retrieve WSS info from association frame
565 *
566 * @attr: pointer to WSS information attribute
567 * @neighbor: ptr to neighbor being discovered, NULL if enrollment in
568 * progress
569 * @wss: ptr to WSS being enrolled in, NULL if discovery in progress
570 * @buflen: size of buffer in which WSS information appears
571 *
572 * The WSS information attribute appears in the D2 association message.
573 * This message is used in two ways: to discover all neighbors or to enroll
574 * into a WSS activated by a neighbor. During discovery we only want to
575 * store the WSS info in a cache, to be deleted right after it has been
576 * used (eg. displayed to the user). During enrollment we store the WSS
577 * information for the lifetime of enrollment.
578 *
579 * During discovery we are interested in all WSS information, during
580 * enrollment we are only interested in the WSS being enrolled in. Even so,
581 * when in enrollment we keep parsing the message after finding the WSS of
582 * interest, this simplifies the calling routine in that it can be sure
583 * that all WSS information attributes have been parsed out of the message.
584 *
585 * Association frame is process with nbmutex held. The list access is safe.
586 */
587static ssize_t wlp_get_all_wss_info(struct wlp *wlp,
588 struct wlp_attr_wss_info *attr,
589 struct wlp_neighbor_e *neighbor,
590 struct wlp_wss *wss, ssize_t buflen)
591{
592 struct device *dev = &wlp->rc->uwb_dev.dev;
593 size_t used = 0;
594 ssize_t result = -EINVAL;
595 struct wlp_attr_wss_info *cur;
596 struct wlp_uuid wssid;
597 struct wlp_wss_tmp_info wss_info;
598 unsigned enroll; /* 0 - discovery to cache, 1 - enrollment */
599 struct wlp_wssid_e *wssid_e;
600 char buf[WLP_WSS_UUID_STRSIZE];
601
602 if (buflen < 0)
603 goto out;
604
605 if (neighbor != NULL && wss == NULL)
606 enroll = 0; /* discovery */
607 else if (wss != NULL && neighbor == NULL)
608 enroll = 1; /* enrollment */
609 else
610 goto out;
611
612 cur = attr;
613 while (buflen - used > 0) {
614 memset(&wss_info, 0, sizeof(wss_info));
615 cur = (void *)cur + used;
616 result = wlp_get_wss_info(wlp, cur, buflen - used, &wssid,
617 &wss_info);
618 if (result == -ENODATA) {
619 result = used;
620 goto out;
621 } else if (result < 0) {
622 dev_err(dev, "WLP: Unable to parse WSS information "
623 "from WSS information attribute. \n");
624 result = -EINVAL;
625 goto error_parse;
626 }
627 if (enroll && !memcmp(&wssid, &wss->wssid, sizeof(wssid))) {
628 if (wss_info.accept_enroll != 1) {
629 dev_err(dev, "WLP: Requested WSS does "
630 "not accept enrollment.\n");
631 result = -EINVAL;
632 goto out;
633 }
634 memcpy(wss->name, wss_info.name, sizeof(wss->name));
635 wss->bcast = wss_info.bcast;
636 wss->secure_status = wss_info.sec_status;
637 wss->accept_enroll = wss_info.accept_enroll;
638 wss->state = WLP_WSS_STATE_PART_ENROLLED;
639 wlp_wss_uuid_print(buf, sizeof(buf), &wssid);
640 dev_dbg(dev, "WLP: Found WSS %s. Enrolling.\n", buf);
641 } else {
642 wssid_e = wlp_create_wssid_e(wlp, neighbor);
643 if (wssid_e == NULL) {
644 dev_err(dev, "WLP: Cannot create new WSSID "
645 "entry for neighbor %02x:%02x.\n",
646 neighbor->uwb_dev->dev_addr.data[1],
647 neighbor->uwb_dev->dev_addr.data[0]);
648 result = -ENOMEM;
649 goto out;
650 }
651 wssid_e->wssid = wssid;
652 *wssid_e->info = wss_info;
653 }
654 used += result;
655 }
656 result = used;
657error_parse:
658 if (result < 0 && !enroll) /* this was a discovery */
659 wlp_remove_neighbor_tmp_info(neighbor);
660out:
661 return result;
662
663}
664
665/**
666 * Parse WSS information attributes into cache for discovery
667 *
668 * @attr: the first WSS information attribute in message
669 * @neighbor: the neighbor whose cache will be populated
670 * @buflen: size of the input buffer
671 */
672static ssize_t wlp_get_wss_info_to_cache(struct wlp *wlp,
673 struct wlp_attr_wss_info *attr,
674 struct wlp_neighbor_e *neighbor,
675 ssize_t buflen)
676{
677 return wlp_get_all_wss_info(wlp, attr, neighbor, NULL, buflen);
678}
679
680/**
681 * Parse WSS information attributes into WSS struct for enrollment
682 *
683 * @attr: the first WSS information attribute in message
684 * @wss: the WSS that will be enrolled
685 * @buflen: size of the input buffer
686 */
687static ssize_t wlp_get_wss_info_to_enroll(struct wlp *wlp,
688 struct wlp_attr_wss_info *attr,
689 struct wlp_wss *wss, ssize_t buflen)
690{
691 return wlp_get_all_wss_info(wlp, attr, NULL, wss, buflen);
692}
693
694/**
695 * Construct a D1 association frame
696 *
697 * We use the radio control functions to determine the values of the device
698 * properties. These are of variable length and the total space needed is
699 * tallied first before we start constructing the message. The radio
700 * control functions return strings that are terminated with \0. This
701 * character should not be included in the message (there is a length field
702 * accompanying it in the attribute).
703 */
704static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss,
705 struct sk_buff **skb)
706{
707
708 struct device *dev = &wlp->rc->uwb_dev.dev;
709 int result = 0;
710 struct wlp_device_info *info;
711 size_t used = 0;
712 struct wlp_frame_assoc *_d1;
713 struct sk_buff *_skb;
714 void *d1_itr;
715
716 if (wlp->dev_info == NULL) {
717 result = __wlp_setup_device_info(wlp);
718 if (result < 0) {
719 dev_err(dev, "WLP: Unable to setup device "
720 "information for D1 message.\n");
721 goto error;
722 }
723 }
724 info = wlp->dev_info;
725 _skb = dev_alloc_skb(sizeof(*_d1)
726 + sizeof(struct wlp_attr_uuid_e)
727 + sizeof(struct wlp_attr_wss_sel_mthd)
728 + sizeof(struct wlp_attr_dev_name)
729 + strlen(info->name)
730 + sizeof(struct wlp_attr_manufacturer)
731 + strlen(info->manufacturer)
732 + sizeof(struct wlp_attr_model_name)
733 + strlen(info->model_name)
734 + sizeof(struct wlp_attr_model_nr)
735 + strlen(info->model_nr)
736 + sizeof(struct wlp_attr_serial)
737 + strlen(info->serial)
738 + sizeof(struct wlp_attr_prim_dev_type)
739 + sizeof(struct wlp_attr_wlp_assc_err));
740 if (_skb == NULL) {
741 dev_err(dev, "WLP: Cannot allocate memory for association "
742 "message.\n");
743 result = -ENOMEM;
744 goto error;
745 }
746 _d1 = (void *) _skb->data;
747 _d1->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
748 _d1->hdr.type = WLP_FRAME_ASSOCIATION;
749 _d1->type = WLP_ASSOC_D1;
750
751 wlp_set_version(&_d1->version, WLP_VERSION);
752 wlp_set_msg_type(&_d1->msg_type, WLP_ASSOC_D1);
753 d1_itr = _d1->attr;
754 used = wlp_set_uuid_e(d1_itr, &wlp->uuid);
755 used += wlp_set_wss_sel_mthd(d1_itr + used, WLP_WSS_REG_SELECT);
756 used += wlp_set_dev_name(d1_itr + used, info->name,
757 strlen(info->name));
758 used += wlp_set_manufacturer(d1_itr + used, info->manufacturer,
759 strlen(info->manufacturer));
760 used += wlp_set_model_name(d1_itr + used, info->model_name,
761 strlen(info->model_name));
762 used += wlp_set_model_nr(d1_itr + used, info->model_nr,
763 strlen(info->model_nr));
764 used += wlp_set_serial(d1_itr + used, info->serial,
765 strlen(info->serial));
766 used += wlp_set_prim_dev_type(d1_itr + used, &info->prim_dev_type);
767 used += wlp_set_wlp_assc_err(d1_itr + used, WLP_ASSOC_ERROR_NONE);
768 skb_put(_skb, sizeof(*_d1) + used);
769 *skb = _skb;
770error:
771 return result;
772}
773
774/**
775 * Construct a D2 association frame
776 *
777 * We use the radio control functions to determine the values of the device
778 * properties. These are of variable length and the total space needed is
779 * tallied first before we start constructing the message. The radio
780 * control functions return strings that are terminated with \0. This
781 * character should not be included in the message (there is a length field
782 * accompanying it in the attribute).
783 */
784static
785int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss,
786 struct sk_buff **skb, struct wlp_uuid *uuid_e)
787{
788
789 struct device *dev = &wlp->rc->uwb_dev.dev;
790 int result = 0;
791 struct wlp_device_info *info;
792 size_t used = 0;
793 struct wlp_frame_assoc *_d2;
794 struct sk_buff *_skb;
795 void *d2_itr;
796 size_t mem_needed;
797
798 if (wlp->dev_info == NULL) {
799 result = __wlp_setup_device_info(wlp);
800 if (result < 0) {
801 dev_err(dev, "WLP: Unable to setup device "
802 "information for D2 message.\n");
803 goto error;
804 }
805 }
806 info = wlp->dev_info;
807 mem_needed = sizeof(*_d2)
808 + sizeof(struct wlp_attr_uuid_e)
809 + sizeof(struct wlp_attr_uuid_r)
810 + sizeof(struct wlp_attr_dev_name)
811 + strlen(info->name)
812 + sizeof(struct wlp_attr_manufacturer)
813 + strlen(info->manufacturer)
814 + sizeof(struct wlp_attr_model_name)
815 + strlen(info->model_name)
816 + sizeof(struct wlp_attr_model_nr)
817 + strlen(info->model_nr)
818 + sizeof(struct wlp_attr_serial)
819 + strlen(info->serial)
820 + sizeof(struct wlp_attr_prim_dev_type)
821 + sizeof(struct wlp_attr_wlp_assc_err);
822 if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE)
823 mem_needed += sizeof(struct wlp_attr_wss_info)
824 + sizeof(struct wlp_wss_info)
825 + strlen(wlp->wss.name);
826 _skb = dev_alloc_skb(mem_needed);
827 if (_skb == NULL) {
828 dev_err(dev, "WLP: Cannot allocate memory for association "
829 "message.\n");
830 result = -ENOMEM;
831 goto error;
832 }
833 _d2 = (void *) _skb->data;
834 _d2->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
835 _d2->hdr.type = WLP_FRAME_ASSOCIATION;
836 _d2->type = WLP_ASSOC_D2;
837
838 wlp_set_version(&_d2->version, WLP_VERSION);
839 wlp_set_msg_type(&_d2->msg_type, WLP_ASSOC_D2);
840 d2_itr = _d2->attr;
841 used = wlp_set_uuid_e(d2_itr, uuid_e);
842 used += wlp_set_uuid_r(d2_itr + used, &wlp->uuid);
843 if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE)
844 used += wlp_set_wss_info(d2_itr + used, &wlp->wss);
845 used += wlp_set_dev_name(d2_itr + used, info->name,
846 strlen(info->name));
847 used += wlp_set_manufacturer(d2_itr + used, info->manufacturer,
848 strlen(info->manufacturer));
849 used += wlp_set_model_name(d2_itr + used, info->model_name,
850 strlen(info->model_name));
851 used += wlp_set_model_nr(d2_itr + used, info->model_nr,
852 strlen(info->model_nr));
853 used += wlp_set_serial(d2_itr + used, info->serial,
854 strlen(info->serial));
855 used += wlp_set_prim_dev_type(d2_itr + used, &info->prim_dev_type);
856 used += wlp_set_wlp_assc_err(d2_itr + used, WLP_ASSOC_ERROR_NONE);
857 skb_put(_skb, sizeof(*_d2) + used);
858 *skb = _skb;
859error:
860 return result;
861}
862
863/**
864 * Allocate memory for and populate fields of F0 association frame
865 *
866 * Currently (while focusing on unsecure enrollment) we ignore the
867 * nonce's that could be placed in the message. Only the error field is
868 * populated by the value provided by the caller.
869 */
870static
871int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb,
872 enum wlp_assc_error error)
873{
874 struct device *dev = &wlp->rc->uwb_dev.dev;
875 int result = -ENOMEM;
876 struct {
877 struct wlp_frame_assoc f0_hdr;
878 struct wlp_attr_enonce enonce;
879 struct wlp_attr_rnonce rnonce;
880 struct wlp_attr_wlp_assc_err assc_err;
881 } *f0;
882 struct sk_buff *_skb;
883 struct wlp_nonce tmp;
884
885 _skb = dev_alloc_skb(sizeof(*f0));
886 if (_skb == NULL) {
887 dev_err(dev, "WLP: Unable to allocate memory for F0 "
888 "association frame. \n");
889 goto error_alloc;
890 }
891 f0 = (void *) _skb->data;
892 f0->f0_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
893 f0->f0_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
894 f0->f0_hdr.type = WLP_ASSOC_F0;
895 wlp_set_version(&f0->f0_hdr.version, WLP_VERSION);
896 wlp_set_msg_type(&f0->f0_hdr.msg_type, WLP_ASSOC_F0);
897 memset(&tmp, 0, sizeof(tmp));
898 wlp_set_enonce(&f0->enonce, &tmp);
899 wlp_set_rnonce(&f0->rnonce, &tmp);
900 wlp_set_wlp_assc_err(&f0->assc_err, error);
901 skb_put(_skb, sizeof(*f0));
902 *skb = _skb;
903 result = 0;
904error_alloc:
905 return result;
906}
907
908/**
909 * Parse F0 frame
910 *
911 * We just retrieve the values and print it as an error to the user.
912 * Calling function already knows an error occured (F0 indicates error), so
913 * we just parse the content as debug for higher layers.
914 */
915int wlp_parse_f0(struct wlp *wlp, struct sk_buff *skb)
916{
917 struct device *dev = &wlp->rc->uwb_dev.dev;
918 struct wlp_frame_assoc *f0 = (void *) skb->data;
919 void *ptr = skb->data;
920 size_t len = skb->len;
921 size_t used;
922 ssize_t result;
923 struct wlp_nonce enonce, rnonce;
924 enum wlp_assc_error assc_err;
925 char enonce_buf[WLP_WSS_NONCE_STRSIZE];
926 char rnonce_buf[WLP_WSS_NONCE_STRSIZE];
927
928 used = sizeof(*f0);
929 result = wlp_get_enonce(wlp, ptr + used, &enonce, len - used);
930 if (result < 0) {
931 dev_err(dev, "WLP: unable to obtain Enrollee nonce "
932 "attribute from F0 message.\n");
933 goto error_parse;
934 }
935 used += result;
936 result = wlp_get_rnonce(wlp, ptr + used, &rnonce, len - used);
937 if (result < 0) {
938 dev_err(dev, "WLP: unable to obtain Registrar nonce "
939 "attribute from F0 message.\n");
940 goto error_parse;
941 }
942 used += result;
943 result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
944 if (result < 0) {
945 dev_err(dev, "WLP: unable to obtain WLP Association error "
946 "attribute from F0 message.\n");
947 goto error_parse;
948 }
949 wlp_wss_nonce_print(enonce_buf, sizeof(enonce_buf), &enonce);
950 wlp_wss_nonce_print(rnonce_buf, sizeof(rnonce_buf), &rnonce);
951 dev_err(dev, "WLP: Received F0 error frame from neighbor. Enrollee "
952 "nonce: %s, Registrar nonce: %s, WLP Association error: %s.\n",
953 enonce_buf, rnonce_buf, wlp_assc_error_str(assc_err));
954 result = 0;
955error_parse:
956 return result;
957}
958
959/**
960 * Retrieve variable device information from association message
961 *
962 * The device information parsed is not required in any message. This
963 * routine will thus not fail if an attribute is not present.
964 * The attributes are expected in a certain order, even if all are not
965 * present. The "attribute type" value is used to ensure the attributes
966 * are parsed in the correct order.
967 *
968 * If an error is encountered during parsing the function will return an
969 * error code, when this happens the given device_info structure may be
970 * partially filled.
971 */
972static
973int wlp_get_variable_info(struct wlp *wlp, void *data,
974 struct wlp_device_info *dev_info, ssize_t len)
975{
976 struct device *dev = &wlp->rc->uwb_dev.dev;
977 size_t used = 0;
978 struct wlp_attr_hdr *hdr;
979 ssize_t result = 0;
980 unsigned last = 0;
981
982 while (len - used > 0) {
983 if (len - used < sizeof(*hdr)) {
984 dev_err(dev, "WLP: Partial data in frame, cannot "
985 "parse. \n");
986 goto error_parse;
987 }
988 hdr = data + used;
989 switch (le16_to_cpu(hdr->type)) {
990 case WLP_ATTR_MANUF:
991 if (last >= WLP_ATTR_MANUF) {
992 dev_err(dev, "WLP: Incorrect order of "
993 "attribute values in D1 msg.\n");
994 goto error_parse;
995 }
996 result = wlp_get_manufacturer(wlp, data + used,
997 dev_info->manufacturer,
998 len - used);
999 if (result < 0) {
1000 dev_err(dev, "WLP: Unable to obtain "
1001 "Manufacturer attribute from D1 "
1002 "message.\n");
1003 goto error_parse;
1004 }
1005 last = WLP_ATTR_MANUF;
1006 used += result;
1007 break;
1008 case WLP_ATTR_MODEL_NAME:
1009 if (last >= WLP_ATTR_MODEL_NAME) {
1010 dev_err(dev, "WLP: Incorrect order of "
1011 "attribute values in D1 msg.\n");
1012 goto error_parse;
1013 }
1014 result = wlp_get_model_name(wlp, data + used,
1015 dev_info->model_name,
1016 len - used);
1017 if (result < 0) {
1018 dev_err(dev, "WLP: Unable to obtain Model "
1019 "name attribute from D1 message.\n");
1020 goto error_parse;
1021 }
1022 last = WLP_ATTR_MODEL_NAME;
1023 used += result;
1024 break;
1025 case WLP_ATTR_MODEL_NR:
1026 if (last >= WLP_ATTR_MODEL_NR) {
1027 dev_err(dev, "WLP: Incorrect order of "
1028 "attribute values in D1 msg.\n");
1029 goto error_parse;
1030 }
1031 result = wlp_get_model_nr(wlp, data + used,
1032 dev_info->model_nr,
1033 len - used);
1034 if (result < 0) {
1035 dev_err(dev, "WLP: Unable to obtain Model "
1036 "number attribute from D1 message.\n");
1037 goto error_parse;
1038 }
1039 last = WLP_ATTR_MODEL_NR;
1040 used += result;
1041 break;
1042 case WLP_ATTR_SERIAL:
1043 if (last >= WLP_ATTR_SERIAL) {
1044 dev_err(dev, "WLP: Incorrect order of "
1045 "attribute values in D1 msg.\n");
1046 goto error_parse;
1047 }
1048 result = wlp_get_serial(wlp, data + used,
1049 dev_info->serial, len - used);
1050 if (result < 0) {
1051 dev_err(dev, "WLP: Unable to obtain Serial "
1052 "number attribute from D1 message.\n");
1053 goto error_parse;
1054 }
1055 last = WLP_ATTR_SERIAL;
1056 used += result;
1057 break;
1058 case WLP_ATTR_PRI_DEV_TYPE:
1059 if (last >= WLP_ATTR_PRI_DEV_TYPE) {
1060 dev_err(dev, "WLP: Incorrect order of "
1061 "attribute values in D1 msg.\n");
1062 goto error_parse;
1063 }
1064 result = wlp_get_prim_dev_type(wlp, data + used,
1065 &dev_info->prim_dev_type,
1066 len - used);
1067 if (result < 0) {
1068 dev_err(dev, "WLP: Unable to obtain Primary "
1069 "device type attribute from D1 "
1070 "message.\n");
1071 goto error_parse;
1072 }
1073 dev_info->prim_dev_type.category =
1074 le16_to_cpu(dev_info->prim_dev_type.category);
1075 dev_info->prim_dev_type.subID =
1076 le16_to_cpu(dev_info->prim_dev_type.subID);
1077 last = WLP_ATTR_PRI_DEV_TYPE;
1078 used += result;
1079 break;
1080 default:
1081 /* This is not variable device information. */
1082 goto out;
1083 break;
1084 }
1085 }
1086out:
1087 return used;
1088error_parse:
1089 return -EINVAL;
1090}
1091
1092/**
1093 * Parse incoming D1 frame, populate attribute values
1094 *
1095 * Caller provides pointers to memory already allocated for attributes
1096 * expected in the D1 frame. These variables will be populated.
1097 */
1098static
1099int wlp_parse_d1_frame(struct wlp *wlp, struct sk_buff *skb,
1100 struct wlp_uuid *uuid_e,
1101 enum wlp_wss_sel_mthd *sel_mthd,
1102 struct wlp_device_info *dev_info,
1103 enum wlp_assc_error *assc_err)
1104{
1105 struct device *dev = &wlp->rc->uwb_dev.dev;
1106 struct wlp_frame_assoc *d1 = (void *) skb->data;
1107 void *ptr = skb->data;
1108 size_t len = skb->len;
1109 size_t used;
1110 ssize_t result;
1111
1112 used = sizeof(*d1);
1113 result = wlp_get_uuid_e(wlp, ptr + used, uuid_e, len - used);
1114 if (result < 0) {
1115 dev_err(dev, "WLP: unable to obtain UUID-E attribute from D1 "
1116 "message.\n");
1117 goto error_parse;
1118 }
1119 used += result;
1120 result = wlp_get_wss_sel_mthd(wlp, ptr + used, sel_mthd, len - used);
1121 if (result < 0) {
1122 dev_err(dev, "WLP: unable to obtain WSS selection method "
1123 "from D1 message.\n");
1124 goto error_parse;
1125 }
1126 used += result;
1127 result = wlp_get_dev_name(wlp, ptr + used, dev_info->name,
1128 len - used);
1129 if (result < 0) {
1130 dev_err(dev, "WLP: unable to obtain Device Name from D1 "
1131 "message.\n");
1132 goto error_parse;
1133 }
1134 used += result;
1135 result = wlp_get_variable_info(wlp, ptr + used, dev_info, len - used);
1136 if (result < 0) {
1137 dev_err(dev, "WLP: unable to obtain Device Information from "
1138 "D1 message.\n");
1139 goto error_parse;
1140 }
1141 used += result;
1142 result = wlp_get_wlp_assc_err(wlp, ptr + used, assc_err, len - used);
1143 if (result < 0) {
1144 dev_err(dev, "WLP: unable to obtain WLP Association Error "
1145 "Information from D1 message.\n");
1146 goto error_parse;
1147 }
1148 result = 0;
1149error_parse:
1150 return result;
1151}
1152/**
1153 * Handle incoming D1 frame
1154 *
1155 * The frame has already been verified to contain an Association header with
1156 * the correct version number. Parse the incoming frame, construct and send
1157 * a D2 frame in response.
1158 *
1159 * It is not clear what to do with most fields in the incoming D1 frame. We
1160 * retrieve and discard the information here for now.
1161 */
1162void wlp_handle_d1_frame(struct work_struct *ws)
1163{
1164 struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1165 struct wlp_assoc_frame_ctx,
1166 ws);
1167 struct wlp *wlp = frame_ctx->wlp;
1168 struct wlp_wss *wss = &wlp->wss;
1169 struct sk_buff *skb = frame_ctx->skb;
1170 struct uwb_dev_addr *src = &frame_ctx->src;
1171 int result;
1172 struct device *dev = &wlp->rc->uwb_dev.dev;
1173 struct wlp_uuid uuid_e;
1174 enum wlp_wss_sel_mthd sel_mthd = 0;
1175 struct wlp_device_info dev_info;
1176 enum wlp_assc_error assc_err;
1177 struct sk_buff *resp = NULL;
1178
1179 /* Parse D1 frame */
1180 mutex_lock(&wss->mutex);
1181 mutex_lock(&wlp->mutex); /* to access wlp->uuid */
1182 memset(&dev_info, 0, sizeof(dev_info));
1183 result = wlp_parse_d1_frame(wlp, skb, &uuid_e, &sel_mthd, &dev_info,
1184 &assc_err);
1185 if (result < 0) {
1186 dev_err(dev, "WLP: Unable to parse incoming D1 frame.\n");
1187 kfree_skb(skb);
1188 goto out;
1189 }
1190
1191 kfree_skb(skb);
1192 if (!wlp_uuid_is_set(&wlp->uuid)) {
1193 dev_err(dev, "WLP: UUID is not set. Set via sysfs to "
1194 "proceed. Respong to D1 message with error F0.\n");
1195 result = wlp_build_assoc_f0(wlp, &resp,
1196 WLP_ASSOC_ERROR_NOT_READY);
1197 if (result < 0) {
1198 dev_err(dev, "WLP: Unable to construct F0 message.\n");
1199 goto out;
1200 }
1201 } else {
1202 /* Construct D2 frame */
1203 result = wlp_build_assoc_d2(wlp, wss, &resp, &uuid_e);
1204 if (result < 0) {
1205 dev_err(dev, "WLP: Unable to construct D2 message.\n");
1206 goto out;
1207 }
1208 }
1209 /* Send D2 frame */
1210 BUG_ON(wlp->xmit_frame == NULL);
1211 result = wlp->xmit_frame(wlp, resp, src);
1212 if (result < 0) {
1213 dev_err(dev, "WLP: Unable to transmit D2 association "
1214 "message: %d\n", result);
1215 if (result == -ENXIO)
1216 dev_err(dev, "WLP: Is network interface up? \n");
1217 /* We could try again ... */
1218 dev_kfree_skb_any(resp); /* we need to free if tx fails */
1219 }
1220out:
1221 kfree(frame_ctx);
1222 mutex_unlock(&wlp->mutex);
1223 mutex_unlock(&wss->mutex);
1224}
1225
1226/**
1227 * Parse incoming D2 frame, create and populate temporary cache
1228 *
1229 * @skb: socket buffer in which D2 frame can be found
1230 * @neighbor: the neighbor that sent the D2 frame
1231 *
1232 * Will allocate memory for temporary storage of information learned during
1233 * discovery.
1234 */
1235int wlp_parse_d2_frame_to_cache(struct wlp *wlp, struct sk_buff *skb,
1236 struct wlp_neighbor_e *neighbor)
1237{
1238 struct device *dev = &wlp->rc->uwb_dev.dev;
1239 struct wlp_frame_assoc *d2 = (void *) skb->data;
1240 void *ptr = skb->data;
1241 size_t len = skb->len;
1242 size_t used;
1243 ssize_t result;
1244 struct wlp_uuid uuid_e;
1245 struct wlp_device_info *nb_info;
1246 enum wlp_assc_error assc_err;
1247
1248 used = sizeof(*d2);
1249 result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used);
1250 if (result < 0) {
1251 dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 "
1252 "message.\n");
1253 goto error_parse;
1254 }
1255 if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) {
1256 dev_err(dev, "WLP: UUID-E in incoming D2 does not match "
1257 "local UUID sent in D1. \n");
1258 goto error_parse;
1259 }
1260 used += result;
1261 result = wlp_get_uuid_r(wlp, ptr + used, &neighbor->uuid, len - used);
1262 if (result < 0) {
1263 dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 "
1264 "message.\n");
1265 goto error_parse;
1266 }
1267 used += result;
1268 result = wlp_get_wss_info_to_cache(wlp, ptr + used, neighbor,
1269 len - used);
1270 if (result < 0) {
1271 dev_err(dev, "WLP: unable to obtain WSS information "
1272 "from D2 message.\n");
1273 goto error_parse;
1274 }
1275 used += result;
1276 neighbor->info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
1277 if (neighbor->info == NULL) {
1278 dev_err(dev, "WLP: cannot allocate memory to store device "
1279 "info.\n");
1280 result = -ENOMEM;
1281 goto error_parse;
1282 }
1283 nb_info = neighbor->info;
1284 result = wlp_get_dev_name(wlp, ptr + used, nb_info->name,
1285 len - used);
1286 if (result < 0) {
1287 dev_err(dev, "WLP: unable to obtain Device Name from D2 "
1288 "message.\n");
1289 goto error_parse;
1290 }
1291 used += result;
1292 result = wlp_get_variable_info(wlp, ptr + used, nb_info, len - used);
1293 if (result < 0) {
1294 dev_err(dev, "WLP: unable to obtain Device Information from "
1295 "D2 message.\n");
1296 goto error_parse;
1297 }
1298 used += result;
1299 result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
1300 if (result < 0) {
1301 dev_err(dev, "WLP: unable to obtain WLP Association Error "
1302 "Information from D2 message.\n");
1303 goto error_parse;
1304 }
1305 if (assc_err != WLP_ASSOC_ERROR_NONE) {
1306 dev_err(dev, "WLP: neighbor device returned association "
1307 "error %d\n", assc_err);
1308 result = -EINVAL;
1309 goto error_parse;
1310 }
1311 result = 0;
1312error_parse:
1313 if (result < 0)
1314 wlp_remove_neighbor_tmp_info(neighbor);
1315 return result;
1316}
1317
1318/**
1319 * Parse incoming D2 frame, populate attribute values of WSS bein enrolled in
1320 *
1321 * @wss: our WSS that will be enrolled
1322 * @skb: socket buffer in which D2 frame can be found
1323 * @neighbor: the neighbor that sent the D2 frame
1324 * @wssid: the wssid of the WSS in which we want to enroll
1325 *
1326 * Forms part of enrollment sequence. We are trying to enroll in WSS with
1327 * @wssid by using @neighbor as registrar. A D1 message was sent to
1328 * @neighbor and now we need to parse the D2 response. The neighbor's
1329 * response is searched for the requested WSS and if found (and it accepts
1330 * enrollment), we store the information.
1331 */
1332int wlp_parse_d2_frame_to_enroll(struct wlp_wss *wss, struct sk_buff *skb,
1333 struct wlp_neighbor_e *neighbor,
1334 struct wlp_uuid *wssid)
1335{
1336 struct wlp *wlp = container_of(wss, struct wlp, wss);
1337 struct device *dev = &wlp->rc->uwb_dev.dev;
1338 void *ptr = skb->data;
1339 size_t len = skb->len;
1340 size_t used;
1341 ssize_t result;
1342 struct wlp_uuid uuid_e;
1343 struct wlp_uuid uuid_r;
1344 struct wlp_device_info nb_info;
1345 enum wlp_assc_error assc_err;
1346 char uuid_bufA[WLP_WSS_UUID_STRSIZE];
1347 char uuid_bufB[WLP_WSS_UUID_STRSIZE];
1348
1349 used = sizeof(struct wlp_frame_assoc);
1350 result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used);
1351 if (result < 0) {
1352 dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 "
1353 "message.\n");
1354 goto error_parse;
1355 }
1356 if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) {
1357 dev_err(dev, "WLP: UUID-E in incoming D2 does not match "
1358 "local UUID sent in D1. \n");
1359 goto error_parse;
1360 }
1361 used += result;
1362 result = wlp_get_uuid_r(wlp, ptr + used, &uuid_r, len - used);
1363 if (result < 0) {
1364 dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 "
1365 "message.\n");
1366 goto error_parse;
1367 }
1368 if (memcmp(&uuid_r, &neighbor->uuid, sizeof(uuid_r))) {
1369 wlp_wss_uuid_print(uuid_bufA, sizeof(uuid_bufA),
1370 &neighbor->uuid);
1371 wlp_wss_uuid_print(uuid_bufB, sizeof(uuid_bufB), &uuid_r);
1372 dev_err(dev, "WLP: UUID of neighbor does not match UUID "
1373 "learned during discovery. Originally discovered: %s, "
1374 "now from D2 message: %s\n", uuid_bufA, uuid_bufB);
1375 result = -EINVAL;
1376 goto error_parse;
1377 }
1378 used += result;
1379 wss->wssid = *wssid;
1380 result = wlp_get_wss_info_to_enroll(wlp, ptr + used, wss, len - used);
1381 if (result < 0) {
1382 dev_err(dev, "WLP: unable to obtain WSS information "
1383 "from D2 message.\n");
1384 goto error_parse;
1385 }
1386 if (wss->state != WLP_WSS_STATE_PART_ENROLLED) {
1387 dev_err(dev, "WLP: D2 message did not contain information "
1388 "for successful enrollment. \n");
1389 result = -EINVAL;
1390 goto error_parse;
1391 }
1392 used += result;
1393 /* Place device information on stack to continue parsing of message */
1394 result = wlp_get_dev_name(wlp, ptr + used, nb_info.name,
1395 len - used);
1396 if (result < 0) {
1397 dev_err(dev, "WLP: unable to obtain Device Name from D2 "
1398 "message.\n");
1399 goto error_parse;
1400 }
1401 used += result;
1402 result = wlp_get_variable_info(wlp, ptr + used, &nb_info, len - used);
1403 if (result < 0) {
1404 dev_err(dev, "WLP: unable to obtain Device Information from "
1405 "D2 message.\n");
1406 goto error_parse;
1407 }
1408 used += result;
1409 result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
1410 if (result < 0) {
1411 dev_err(dev, "WLP: unable to obtain WLP Association Error "
1412 "Information from D2 message.\n");
1413 goto error_parse;
1414 }
1415 if (assc_err != WLP_ASSOC_ERROR_NONE) {
1416 dev_err(dev, "WLP: neighbor device returned association "
1417 "error %d\n", assc_err);
1418 if (wss->state == WLP_WSS_STATE_PART_ENROLLED) {
1419 dev_err(dev, "WLP: Enrolled in WSS (should not "
1420 "happen according to spec). Undoing. \n");
1421 wlp_wss_reset(wss);
1422 }
1423 result = -EINVAL;
1424 goto error_parse;
1425 }
1426 result = 0;
1427error_parse:
1428 return result;
1429}
1430
1431/**
1432 * Parse C3/C4 frame into provided variables
1433 *
1434 * @wssid: will point to copy of wssid retrieved from C3/C4 frame
1435 * @tag: will point to copy of tag retrieved from C3/C4 frame
1436 * @virt_addr: will point to copy of virtual address retrieved from C3/C4
1437 * frame.
1438 *
1439 * Calling function has to allocate memory for these values.
1440 *
1441 * skb contains a valid C3/C4 frame, return the individual fields of this
1442 * frame in the provided variables.
1443 */
1444int wlp_parse_c3c4_frame(struct wlp *wlp, struct sk_buff *skb,
1445 struct wlp_uuid *wssid, u8 *tag,
1446 struct uwb_mac_addr *virt_addr)
1447{
1448 struct device *dev = &wlp->rc->uwb_dev.dev;
1449 int result;
1450 void *ptr = skb->data;
1451 size_t len = skb->len;
1452 size_t used;
1453 struct wlp_frame_assoc *assoc = ptr;
1454
1455 used = sizeof(*assoc);
1456 result = wlp_get_wssid(wlp, ptr + used, wssid, len - used);
1457 if (result < 0) {
1458 dev_err(dev, "WLP: unable to obtain WSSID attribute from "
1459 "%s message.\n", wlp_assoc_frame_str(assoc->type));
1460 goto error_parse;
1461 }
1462 used += result;
1463 result = wlp_get_wss_tag(wlp, ptr + used, tag, len - used);
1464 if (result < 0) {
1465 dev_err(dev, "WLP: unable to obtain WSS tag attribute from "
1466 "%s message.\n", wlp_assoc_frame_str(assoc->type));
1467 goto error_parse;
1468 }
1469 used += result;
1470 result = wlp_get_wss_virt(wlp, ptr + used, virt_addr, len - used);
1471 if (result < 0) {
1472 dev_err(dev, "WLP: unable to obtain WSS virtual address "
1473 "attribute from %s message.\n",
1474 wlp_assoc_frame_str(assoc->type));
1475 goto error_parse;
1476 }
1477error_parse:
1478 return result;
1479}
1480
1481/**
1482 * Allocate memory for and populate fields of C1 or C2 association frame
1483 *
1484 * The C1 and C2 association frames appear identical - except for the type.
1485 */
1486static
1487int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss,
1488 struct sk_buff **skb, enum wlp_assoc_type type)
1489{
1490 struct device *dev = &wlp->rc->uwb_dev.dev;
1491 int result = -ENOMEM;
1492 struct {
1493 struct wlp_frame_assoc c_hdr;
1494 struct wlp_attr_wssid wssid;
1495 } *c;
1496 struct sk_buff *_skb;
1497
1498 _skb = dev_alloc_skb(sizeof(*c));
1499 if (_skb == NULL) {
1500 dev_err(dev, "WLP: Unable to allocate memory for C1/C2 "
1501 "association frame. \n");
1502 goto error_alloc;
1503 }
1504 c = (void *) _skb->data;
1505 c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
1506 c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
1507 c->c_hdr.type = type;
1508 wlp_set_version(&c->c_hdr.version, WLP_VERSION);
1509 wlp_set_msg_type(&c->c_hdr.msg_type, type);
1510 wlp_set_wssid(&c->wssid, &wss->wssid);
1511 skb_put(_skb, sizeof(*c));
1512 *skb = _skb;
1513 result = 0;
1514error_alloc:
1515 return result;
1516}
1517
1518
1519static
1520int wlp_build_assoc_c1(struct wlp *wlp, struct wlp_wss *wss,
1521 struct sk_buff **skb)
1522{
1523 return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C1);
1524}
1525
1526static
1527int wlp_build_assoc_c2(struct wlp *wlp, struct wlp_wss *wss,
1528 struct sk_buff **skb)
1529{
1530 return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C2);
1531}
1532
1533
1534/**
1535 * Allocate memory for and populate fields of C3 or C4 association frame
1536 *
1537 * The C3 and C4 association frames appear identical - except for the type.
1538 */
1539static
1540int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss,
1541 struct sk_buff **skb, enum wlp_assoc_type type)
1542{
1543 struct device *dev = &wlp->rc->uwb_dev.dev;
1544 int result = -ENOMEM;
1545 struct {
1546 struct wlp_frame_assoc c_hdr;
1547 struct wlp_attr_wssid wssid;
1548 struct wlp_attr_wss_tag wss_tag;
1549 struct wlp_attr_wss_virt wss_virt;
1550 } *c;
1551 struct sk_buff *_skb;
1552
1553 _skb = dev_alloc_skb(sizeof(*c));
1554 if (_skb == NULL) {
1555 dev_err(dev, "WLP: Unable to allocate memory for C3/C4 "
1556 "association frame. \n");
1557 goto error_alloc;
1558 }
1559 c = (void *) _skb->data;
1560 c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
1561 c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
1562 c->c_hdr.type = type;
1563 wlp_set_version(&c->c_hdr.version, WLP_VERSION);
1564 wlp_set_msg_type(&c->c_hdr.msg_type, type);
1565 wlp_set_wssid(&c->wssid, &wss->wssid);
1566 wlp_set_wss_tag(&c->wss_tag, wss->tag);
1567 wlp_set_wss_virt(&c->wss_virt, &wss->virtual_addr);
1568 skb_put(_skb, sizeof(*c));
1569 *skb = _skb;
1570 result = 0;
1571error_alloc:
1572 return result;
1573}
1574
1575static
1576int wlp_build_assoc_c3(struct wlp *wlp, struct wlp_wss *wss,
1577 struct sk_buff **skb)
1578{
1579 return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C3);
1580}
1581
1582static
1583int wlp_build_assoc_c4(struct wlp *wlp, struct wlp_wss *wss,
1584 struct sk_buff **skb)
1585{
1586 return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C4);
1587}
1588
1589
1590#define wlp_send_assoc(type, id) \
1591static int wlp_send_assoc_##type(struct wlp *wlp, struct wlp_wss *wss, \
1592 struct uwb_dev_addr *dev_addr) \
1593{ \
1594 struct device *dev = &wlp->rc->uwb_dev.dev; \
1595 int result; \
1596 struct sk_buff *skb = NULL; \
1597 \
1598 /* Build the frame */ \
1599 result = wlp_build_assoc_##type(wlp, wss, &skb); \
1600 if (result < 0) { \
1601 dev_err(dev, "WLP: Unable to construct %s association " \
1602 "frame: %d\n", wlp_assoc_frame_str(id), result);\
1603 goto error_build_assoc; \
1604 } \
1605 /* Send the frame */ \
1606 BUG_ON(wlp->xmit_frame == NULL); \
1607 result = wlp->xmit_frame(wlp, skb, dev_addr); \
1608 if (result < 0) { \
1609 dev_err(dev, "WLP: Unable to transmit %s association " \
1610 "message: %d\n", wlp_assoc_frame_str(id), \
1611 result); \
1612 if (result == -ENXIO) \
1613 dev_err(dev, "WLP: Is network interface " \
1614 "up? \n"); \
1615 goto error_xmit; \
1616 } \
1617 return 0; \
1618error_xmit: \
1619 /* We could try again ... */ \
1620 dev_kfree_skb_any(skb);/*we need to free if tx fails*/ \
1621error_build_assoc: \
1622 return result; \
1623}
1624
1625wlp_send_assoc(d1, WLP_ASSOC_D1)
1626wlp_send_assoc(c1, WLP_ASSOC_C1)
1627wlp_send_assoc(c3, WLP_ASSOC_C3)
1628
1629int wlp_send_assoc_frame(struct wlp *wlp, struct wlp_wss *wss,
1630 struct uwb_dev_addr *dev_addr,
1631 enum wlp_assoc_type type)
1632{
1633 int result = 0;
1634 struct device *dev = &wlp->rc->uwb_dev.dev;
1635 switch (type) {
1636 case WLP_ASSOC_D1:
1637 result = wlp_send_assoc_d1(wlp, wss, dev_addr);
1638 break;
1639 case WLP_ASSOC_C1:
1640 result = wlp_send_assoc_c1(wlp, wss, dev_addr);
1641 break;
1642 case WLP_ASSOC_C3:
1643 result = wlp_send_assoc_c3(wlp, wss, dev_addr);
1644 break;
1645 default:
1646 dev_err(dev, "WLP: Received request to send unknown "
1647 "association message.\n");
1648 result = -EINVAL;
1649 break;
1650 }
1651 return result;
1652}
1653
1654/**
1655 * Handle incoming C1 frame
1656 *
1657 * The frame has already been verified to contain an Association header with
1658 * the correct version number. Parse the incoming frame, construct and send
1659 * a C2 frame in response.
1660 */
1661void wlp_handle_c1_frame(struct work_struct *ws)
1662{
1663 struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1664 struct wlp_assoc_frame_ctx,
1665 ws);
1666 struct wlp *wlp = frame_ctx->wlp;
1667 struct wlp_wss *wss = &wlp->wss;
1668 struct device *dev = &wlp->rc->uwb_dev.dev;
1669 struct wlp_frame_assoc *c1 = (void *) frame_ctx->skb->data;
1670 unsigned int len = frame_ctx->skb->len;
1671 struct uwb_dev_addr *src = &frame_ctx->src;
1672 int result;
1673 struct wlp_uuid wssid;
1674 struct sk_buff *resp = NULL;
1675
1676 /* Parse C1 frame */
1677 mutex_lock(&wss->mutex);
1678 result = wlp_get_wssid(wlp, (void *)c1 + sizeof(*c1), &wssid,
1679 len - sizeof(*c1));
1680 if (result < 0) {
1681 dev_err(dev, "WLP: unable to obtain WSSID from C1 frame.\n");
1682 goto out;
1683 }
1684 if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))
1685 && wss->state == WLP_WSS_STATE_ACTIVE) {
1686 /* Construct C2 frame */
1687 result = wlp_build_assoc_c2(wlp, wss, &resp);
1688 if (result < 0) {
1689 dev_err(dev, "WLP: Unable to construct C2 message.\n");
1690 goto out;
1691 }
1692 } else {
1693 /* Construct F0 frame */
1694 result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV);
1695 if (result < 0) {
1696 dev_err(dev, "WLP: Unable to construct F0 message.\n");
1697 goto out;
1698 }
1699 }
1700 /* Send C2 frame */
1701 BUG_ON(wlp->xmit_frame == NULL);
1702 result = wlp->xmit_frame(wlp, resp, src);
1703 if (result < 0) {
1704 dev_err(dev, "WLP: Unable to transmit response association "
1705 "message: %d\n", result);
1706 if (result == -ENXIO)
1707 dev_err(dev, "WLP: Is network interface up? \n");
1708 /* We could try again ... */
1709 dev_kfree_skb_any(resp); /* we need to free if tx fails */
1710 }
1711out:
1712 kfree_skb(frame_ctx->skb);
1713 kfree(frame_ctx);
1714 mutex_unlock(&wss->mutex);
1715}
1716
1717/**
1718 * Handle incoming C3 frame
1719 *
1720 * The frame has already been verified to contain an Association header with
1721 * the correct version number. Parse the incoming frame, construct and send
1722 * a C4 frame in response. If the C3 frame identifies a WSS that is locally
1723 * active then we connect to this neighbor (add it to our EDA cache).
1724 */
1725void wlp_handle_c3_frame(struct work_struct *ws)
1726{
1727 struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1728 struct wlp_assoc_frame_ctx,
1729 ws);
1730 struct wlp *wlp = frame_ctx->wlp;
1731 struct wlp_wss *wss = &wlp->wss;
1732 struct device *dev = &wlp->rc->uwb_dev.dev;
1733 struct sk_buff *skb = frame_ctx->skb;
1734 struct uwb_dev_addr *src = &frame_ctx->src;
1735 int result;
1736 struct sk_buff *resp = NULL;
1737 struct wlp_uuid wssid;
1738 u8 tag;
1739 struct uwb_mac_addr virt_addr;
1740
1741 /* Parse C3 frame */
1742 mutex_lock(&wss->mutex);
1743 result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr);
1744 if (result < 0) {
1745 dev_err(dev, "WLP: unable to obtain values from C3 frame.\n");
1746 goto out;
1747 }
1748 if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))
1749 && wss->state >= WLP_WSS_STATE_ACTIVE) {
1750 result = wlp_eda_update_node(&wlp->eda, src, wss,
1751 (void *) virt_addr.data, tag,
1752 WLP_WSS_CONNECTED);
1753 if (result < 0) {
1754 dev_err(dev, "WLP: Unable to update EDA cache "
1755 "with new connected neighbor information.\n");
1756 result = wlp_build_assoc_f0(wlp, &resp,
1757 WLP_ASSOC_ERROR_INT);
1758 if (result < 0) {
1759 dev_err(dev, "WLP: Unable to construct F0 "
1760 "message.\n");
1761 goto out;
1762 }
1763 } else {
1764 wss->state = WLP_WSS_STATE_CONNECTED;
1765 /* Construct C4 frame */
1766 result = wlp_build_assoc_c4(wlp, wss, &resp);
1767 if (result < 0) {
1768 dev_err(dev, "WLP: Unable to construct C4 "
1769 "message.\n");
1770 goto out;
1771 }
1772 }
1773 } else {
1774 /* Construct F0 frame */
1775 result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV);
1776 if (result < 0) {
1777 dev_err(dev, "WLP: Unable to construct F0 message.\n");
1778 goto out;
1779 }
1780 }
1781 /* Send C4 frame */
1782 BUG_ON(wlp->xmit_frame == NULL);
1783 result = wlp->xmit_frame(wlp, resp, src);
1784 if (result < 0) {
1785 dev_err(dev, "WLP: Unable to transmit response association "
1786 "message: %d\n", result);
1787 if (result == -ENXIO)
1788 dev_err(dev, "WLP: Is network interface up? \n");
1789 /* We could try again ... */
1790 dev_kfree_skb_any(resp); /* we need to free if tx fails */
1791 }
1792out:
1793 kfree_skb(frame_ctx->skb);
1794 kfree(frame_ctx);
1795 mutex_unlock(&wss->mutex);
1796}
1797
1798
diff --git a/drivers/uwb/wlp/sysfs.c b/drivers/uwb/wlp/sysfs.c
deleted file mode 100644
index 6627c94cc854..000000000000
--- a/drivers/uwb/wlp/sysfs.c
+++ /dev/null
@@ -1,708 +0,0 @@
1/*
2 * WiMedia Logical Link Control Protocol (WLP)
3 * sysfs functions
4 *
5 * Copyright (C) 2007 Intel Corporation
6 * Reinette Chatre <reinette.chatre@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 */
26#include <linux/wlp.h>
27
28#include "wlp-internal.h"
29
30static
31size_t wlp_wss_wssid_e_print(char *buf, size_t bufsize,
32 struct wlp_wssid_e *wssid_e)
33{
34 size_t used = 0;
35 used += scnprintf(buf, bufsize, " WSS: ");
36 used += wlp_wss_uuid_print(buf + used, bufsize - used,
37 &wssid_e->wssid);
38
39 if (wssid_e->info != NULL) {
40 used += scnprintf(buf + used, bufsize - used, " ");
41 used += uwb_mac_addr_print(buf + used, bufsize - used,
42 &wssid_e->info->bcast);
43 used += scnprintf(buf + used, bufsize - used, " %u %u %s\n",
44 wssid_e->info->accept_enroll,
45 wssid_e->info->sec_status,
46 wssid_e->info->name);
47 }
48 return used;
49}
50
51/**
52 * Print out information learned from neighbor discovery
53 *
54 * Some fields being printed may not be included in the device discovery
55 * information (it is not mandatory). We are thus careful how the
56 * information is printed to ensure it is clear to the user what field is
57 * being referenced.
58 * The information being printed is for one time use - temporary storage is
59 * cleaned after it is printed.
60 *
61 * Ideally sysfs output should be on one line. The information printed here
62 * contain a few strings so it will be hard to parse if they are all
63 * printed on the same line - without agreeing on a standard field
64 * separator.
65 */
66static
67ssize_t wlp_wss_neighborhood_print_remove(struct wlp *wlp, char *buf,
68 size_t bufsize)
69{
70 size_t used = 0;
71 struct wlp_neighbor_e *neighb;
72 struct wlp_wssid_e *wssid_e;
73
74 mutex_lock(&wlp->nbmutex);
75 used = scnprintf(buf, bufsize, "#Neighbor information\n"
76 "#uuid dev_addr\n"
77 "# Device Name:\n# Model Name:\n# Manufacturer:\n"
78 "# Model Nr:\n# Serial:\n"
79 "# Pri Dev type: CategoryID OUI OUISubdiv "
80 "SubcategoryID\n"
81 "# WSS: WSSID WSS_name accept_enroll sec_status "
82 "bcast\n"
83 "# WSS: WSSID WSS_name accept_enroll sec_status "
84 "bcast\n\n");
85 list_for_each_entry(neighb, &wlp->neighbors, node) {
86 if (bufsize - used <= 0)
87 goto out;
88 used += wlp_wss_uuid_print(buf + used, bufsize - used,
89 &neighb->uuid);
90 buf[used++] = ' ';
91 used += uwb_dev_addr_print(buf + used, bufsize - used,
92 &neighb->uwb_dev->dev_addr);
93 if (neighb->info != NULL)
94 used += scnprintf(buf + used, bufsize - used,
95 "\n Device Name: %s\n"
96 " Model Name: %s\n"
97 " Manufacturer:%s \n"
98 " Model Nr: %s\n"
99 " Serial: %s\n"
100 " Pri Dev type: "
101 "%u %02x:%02x:%02x %u %u\n",
102 neighb->info->name,
103 neighb->info->model_name,
104 neighb->info->manufacturer,
105 neighb->info->model_nr,
106 neighb->info->serial,
107 neighb->info->prim_dev_type.category,
108 neighb->info->prim_dev_type.OUI[0],
109 neighb->info->prim_dev_type.OUI[1],
110 neighb->info->prim_dev_type.OUI[2],
111 neighb->info->prim_dev_type.OUIsubdiv,
112 neighb->info->prim_dev_type.subID);
113 list_for_each_entry(wssid_e, &neighb->wssid, node) {
114 used += wlp_wss_wssid_e_print(buf + used,
115 bufsize - used,
116 wssid_e);
117 }
118 buf[used++] = '\n';
119 wlp_remove_neighbor_tmp_info(neighb);
120 }
121
122
123out:
124 mutex_unlock(&wlp->nbmutex);
125 return used;
126}
127
128
129/**
130 * Show properties of all WSS in neighborhood.
131 *
132 * Will trigger a complete discovery of WSS activated by this device and
133 * its neighbors.
134 */
135ssize_t wlp_neighborhood_show(struct wlp *wlp, char *buf)
136{
137 wlp_discover(wlp);
138 return wlp_wss_neighborhood_print_remove(wlp, buf, PAGE_SIZE);
139}
140EXPORT_SYMBOL_GPL(wlp_neighborhood_show);
141
142static
143ssize_t __wlp_wss_properties_show(struct wlp_wss *wss, char *buf,
144 size_t bufsize)
145{
146 ssize_t result;
147
148 result = wlp_wss_uuid_print(buf, bufsize, &wss->wssid);
149 result += scnprintf(buf + result, bufsize - result, " ");
150 result += uwb_mac_addr_print(buf + result, bufsize - result,
151 &wss->bcast);
152 result += scnprintf(buf + result, bufsize - result,
153 " 0x%02x %u ", wss->hash, wss->secure_status);
154 result += wlp_wss_key_print(buf + result, bufsize - result,
155 wss->master_key);
156 result += scnprintf(buf + result, bufsize - result, " 0x%02x ",
157 wss->tag);
158 result += uwb_mac_addr_print(buf + result, bufsize - result,
159 &wss->virtual_addr);
160 result += scnprintf(buf + result, bufsize - result, " %s", wss->name);
161 result += scnprintf(buf + result, bufsize - result,
162 "\n\n#WSSID\n#WSS broadcast address\n"
163 "#WSS hash\n#WSS secure status\n"
164 "#WSS master key\n#WSS local tag\n"
165 "#WSS local virtual EUI-48\n#WSS name\n");
166 return result;
167}
168
169/**
170 * Show which WSS is activated.
171 */
172ssize_t wlp_wss_activate_show(struct wlp_wss *wss, char *buf)
173{
174 int result = 0;
175
176 if (mutex_lock_interruptible(&wss->mutex))
177 goto out;
178 if (wss->state >= WLP_WSS_STATE_ACTIVE)
179 result = __wlp_wss_properties_show(wss, buf, PAGE_SIZE);
180 else
181 result = scnprintf(buf, PAGE_SIZE, "No local WSS active.\n");
182 result += scnprintf(buf + result, PAGE_SIZE - result,
183 "\n\n"
184 "# echo WSSID SECURE_STATUS ACCEPT_ENROLLMENT "
185 "NAME #create new WSS\n"
186 "# echo WSSID [DEV ADDR] #enroll in and activate "
187 "existing WSS, can request registrar\n"
188 "#\n"
189 "# WSSID is a 16 byte hex array. Eg. 12 A3 3B ... \n"
190 "# SECURE_STATUS 0 - unsecure, 1 - secure (default)\n"
191 "# ACCEPT_ENROLLMENT 0 - no, 1 - yes (default)\n"
192 "# NAME is the text string identifying the WSS\n"
193 "# DEV ADDR is the device address of neighbor "
194 "that should be registrar. Eg. 32:AB\n");
195
196 mutex_unlock(&wss->mutex);
197out:
198 return result;
199
200}
201EXPORT_SYMBOL_GPL(wlp_wss_activate_show);
202
203/**
204 * Create/activate a new WSS or enroll/activate in neighboring WSS
205 *
206 * The user can provide the WSSID of a WSS in which it wants to enroll.
207 * Only the WSSID is necessary if the WSS have been discovered before. If
208 * the WSS has not been discovered before, or the user wants to use a
209 * particular neighbor as its registrar, then the user can also provide a
210 * device address or the neighbor that will be used as registrar.
211 *
212 * A new WSS is created when the user provides a WSSID, secure status, and
213 * WSS name.
214 */
215ssize_t wlp_wss_activate_store(struct wlp_wss *wss,
216 const char *buf, size_t size)
217{
218 ssize_t result = -EINVAL;
219 struct wlp_uuid wssid;
220 struct uwb_dev_addr dev;
221 struct uwb_dev_addr bcast = {.data = {0xff, 0xff} };
222 char name[65];
223 unsigned sec_status, accept;
224 memset(name, 0, sizeof(name));
225 result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx "
226 "%02hhx %02hhx %02hhx %02hhx "
227 "%02hhx %02hhx %02hhx %02hhx "
228 "%02hhx %02hhx %02hhx %02hhx "
229 "%02hhx:%02hhx",
230 &wssid.data[0] , &wssid.data[1],
231 &wssid.data[2] , &wssid.data[3],
232 &wssid.data[4] , &wssid.data[5],
233 &wssid.data[6] , &wssid.data[7],
234 &wssid.data[8] , &wssid.data[9],
235 &wssid.data[10], &wssid.data[11],
236 &wssid.data[12], &wssid.data[13],
237 &wssid.data[14], &wssid.data[15],
238 &dev.data[1], &dev.data[0]);
239 if (result == 16 || result == 17) {
240 result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx "
241 "%02hhx %02hhx %02hhx %02hhx "
242 "%02hhx %02hhx %02hhx %02hhx "
243 "%02hhx %02hhx %02hhx %02hhx "
244 "%u %u %64c",
245 &wssid.data[0] , &wssid.data[1],
246 &wssid.data[2] , &wssid.data[3],
247 &wssid.data[4] , &wssid.data[5],
248 &wssid.data[6] , &wssid.data[7],
249 &wssid.data[8] , &wssid.data[9],
250 &wssid.data[10], &wssid.data[11],
251 &wssid.data[12], &wssid.data[13],
252 &wssid.data[14], &wssid.data[15],
253 &sec_status, &accept, name);
254 if (result == 16)
255 result = wlp_wss_enroll_activate(wss, &wssid, &bcast);
256 else if (result == 19) {
257 sec_status = sec_status == 0 ? 0 : 1;
258 accept = accept == 0 ? 0 : 1;
259 /* We read name using %c, so the newline needs to be
260 * removed */
261 if (strlen(name) != sizeof(name) - 1)
262 name[strlen(name) - 1] = '\0';
263 result = wlp_wss_create_activate(wss, &wssid, name,
264 sec_status, accept);
265 } else
266 result = -EINVAL;
267 } else if (result == 18)
268 result = wlp_wss_enroll_activate(wss, &wssid, &dev);
269 else
270 result = -EINVAL;
271 return result < 0 ? result : size;
272}
273EXPORT_SYMBOL_GPL(wlp_wss_activate_store);
274
275/**
276 * Show the UUID of this host
277 */
278ssize_t wlp_uuid_show(struct wlp *wlp, char *buf)
279{
280 ssize_t result = 0;
281
282 mutex_lock(&wlp->mutex);
283 result = wlp_wss_uuid_print(buf, PAGE_SIZE, &wlp->uuid);
284 buf[result++] = '\n';
285 mutex_unlock(&wlp->mutex);
286 return result;
287}
288EXPORT_SYMBOL_GPL(wlp_uuid_show);
289
290/**
291 * Store a new UUID for this host
292 *
293 * According to the spec this should be encoded as an octet string in the
294 * order the octets are shown in string representation in RFC 4122 (WLP
295 * 0.99 [Table 6])
296 *
297 * We do not check value provided by user.
298 */
299ssize_t wlp_uuid_store(struct wlp *wlp, const char *buf, size_t size)
300{
301 ssize_t result;
302 struct wlp_uuid uuid;
303
304 mutex_lock(&wlp->mutex);
305 result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx "
306 "%02hhx %02hhx %02hhx %02hhx "
307 "%02hhx %02hhx %02hhx %02hhx "
308 "%02hhx %02hhx %02hhx %02hhx ",
309 &uuid.data[0] , &uuid.data[1],
310 &uuid.data[2] , &uuid.data[3],
311 &uuid.data[4] , &uuid.data[5],
312 &uuid.data[6] , &uuid.data[7],
313 &uuid.data[8] , &uuid.data[9],
314 &uuid.data[10], &uuid.data[11],
315 &uuid.data[12], &uuid.data[13],
316 &uuid.data[14], &uuid.data[15]);
317 if (result != 16) {
318 result = -EINVAL;
319 goto error;
320 }
321 wlp->uuid = uuid;
322error:
323 mutex_unlock(&wlp->mutex);
324 return result < 0 ? result : size;
325}
326EXPORT_SYMBOL_GPL(wlp_uuid_store);
327
328/**
329 * Show contents of members of device information structure
330 */
331#define wlp_dev_info_show(type) \
332ssize_t wlp_dev_##type##_show(struct wlp *wlp, char *buf) \
333{ \
334 ssize_t result = 0; \
335 mutex_lock(&wlp->mutex); \
336 if (wlp->dev_info == NULL) { \
337 result = __wlp_setup_device_info(wlp); \
338 if (result < 0) \
339 goto out; \
340 } \
341 result = scnprintf(buf, PAGE_SIZE, "%s\n", wlp->dev_info->type);\
342out: \
343 mutex_unlock(&wlp->mutex); \
344 return result; \
345} \
346EXPORT_SYMBOL_GPL(wlp_dev_##type##_show);
347
348wlp_dev_info_show(name)
349wlp_dev_info_show(model_name)
350wlp_dev_info_show(model_nr)
351wlp_dev_info_show(manufacturer)
352wlp_dev_info_show(serial)
353
354/**
355 * Store contents of members of device information structure
356 */
357#define wlp_dev_info_store(type, len) \
358ssize_t wlp_dev_##type##_store(struct wlp *wlp, const char *buf, size_t size)\
359{ \
360 ssize_t result; \
361 char format[10]; \
362 mutex_lock(&wlp->mutex); \
363 if (wlp->dev_info == NULL) { \
364 result = __wlp_alloc_device_info(wlp); \
365 if (result < 0) \
366 goto out; \
367 } \
368 memset(wlp->dev_info->type, 0, sizeof(wlp->dev_info->type)); \
369 sprintf(format, "%%%uc", len); \
370 result = sscanf(buf, format, wlp->dev_info->type); \
371out: \
372 mutex_unlock(&wlp->mutex); \
373 return result < 0 ? result : size; \
374} \
375EXPORT_SYMBOL_GPL(wlp_dev_##type##_store);
376
377wlp_dev_info_store(name, 32)
378wlp_dev_info_store(manufacturer, 64)
379wlp_dev_info_store(model_name, 32)
380wlp_dev_info_store(model_nr, 32)
381wlp_dev_info_store(serial, 32)
382
383static
384const char *__wlp_dev_category[] = {
385 [WLP_DEV_CAT_COMPUTER] = "Computer",
386 [WLP_DEV_CAT_INPUT] = "Input device",
387 [WLP_DEV_CAT_PRINT_SCAN_FAX_COPIER] = "Printer, scanner, FAX, or "
388 "Copier",
389 [WLP_DEV_CAT_CAMERA] = "Camera",
390 [WLP_DEV_CAT_STORAGE] = "Storage Network",
391 [WLP_DEV_CAT_INFRASTRUCTURE] = "Infrastructure",
392 [WLP_DEV_CAT_DISPLAY] = "Display",
393 [WLP_DEV_CAT_MULTIM] = "Multimedia device",
394 [WLP_DEV_CAT_GAMING] = "Gaming device",
395 [WLP_DEV_CAT_TELEPHONE] = "Telephone",
396 [WLP_DEV_CAT_OTHER] = "Other",
397};
398
399static
400const char *wlp_dev_category_str(unsigned cat)
401{
402 if ((cat >= WLP_DEV_CAT_COMPUTER && cat <= WLP_DEV_CAT_TELEPHONE)
403 || cat == WLP_DEV_CAT_OTHER)
404 return __wlp_dev_category[cat];
405 return "unknown category";
406}
407
408ssize_t wlp_dev_prim_category_show(struct wlp *wlp, char *buf)
409{
410 ssize_t result = 0;
411 mutex_lock(&wlp->mutex);
412 if (wlp->dev_info == NULL) {
413 result = __wlp_setup_device_info(wlp);
414 if (result < 0)
415 goto out;
416 }
417 result = scnprintf(buf, PAGE_SIZE, "%s\n",
418 wlp_dev_category_str(wlp->dev_info->prim_dev_type.category));
419out:
420 mutex_unlock(&wlp->mutex);
421 return result;
422}
423EXPORT_SYMBOL_GPL(wlp_dev_prim_category_show);
424
425ssize_t wlp_dev_prim_category_store(struct wlp *wlp, const char *buf,
426 size_t size)
427{
428 ssize_t result;
429 u16 cat;
430 mutex_lock(&wlp->mutex);
431 if (wlp->dev_info == NULL) {
432 result = __wlp_alloc_device_info(wlp);
433 if (result < 0)
434 goto out;
435 }
436 result = sscanf(buf, "%hu", &cat);
437 if ((cat >= WLP_DEV_CAT_COMPUTER && cat <= WLP_DEV_CAT_TELEPHONE)
438 || cat == WLP_DEV_CAT_OTHER)
439 wlp->dev_info->prim_dev_type.category = cat;
440 else
441 result = -EINVAL;
442out:
443 mutex_unlock(&wlp->mutex);
444 return result < 0 ? result : size;
445}
446EXPORT_SYMBOL_GPL(wlp_dev_prim_category_store);
447
448ssize_t wlp_dev_prim_OUI_show(struct wlp *wlp, char *buf)
449{
450 ssize_t result = 0;
451 mutex_lock(&wlp->mutex);
452 if (wlp->dev_info == NULL) {
453 result = __wlp_setup_device_info(wlp);
454 if (result < 0)
455 goto out;
456 }
457 result = scnprintf(buf, PAGE_SIZE, "%02x:%02x:%02x\n",
458 wlp->dev_info->prim_dev_type.OUI[0],
459 wlp->dev_info->prim_dev_type.OUI[1],
460 wlp->dev_info->prim_dev_type.OUI[2]);
461out:
462 mutex_unlock(&wlp->mutex);
463 return result;
464}
465EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_show);
466
467ssize_t wlp_dev_prim_OUI_store(struct wlp *wlp, const char *buf, size_t size)
468{
469 ssize_t result;
470 u8 OUI[3];
471 mutex_lock(&wlp->mutex);
472 if (wlp->dev_info == NULL) {
473 result = __wlp_alloc_device_info(wlp);
474 if (result < 0)
475 goto out;
476 }
477 result = sscanf(buf, "%hhx:%hhx:%hhx",
478 &OUI[0], &OUI[1], &OUI[2]);
479 if (result != 3) {
480 result = -EINVAL;
481 goto out;
482 } else
483 memcpy(wlp->dev_info->prim_dev_type.OUI, OUI, sizeof(OUI));
484out:
485 mutex_unlock(&wlp->mutex);
486 return result < 0 ? result : size;
487}
488EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_store);
489
490
491ssize_t wlp_dev_prim_OUI_sub_show(struct wlp *wlp, char *buf)
492{
493 ssize_t result = 0;
494 mutex_lock(&wlp->mutex);
495 if (wlp->dev_info == NULL) {
496 result = __wlp_setup_device_info(wlp);
497 if (result < 0)
498 goto out;
499 }
500 result = scnprintf(buf, PAGE_SIZE, "%u\n",
501 wlp->dev_info->prim_dev_type.OUIsubdiv);
502out:
503 mutex_unlock(&wlp->mutex);
504 return result;
505}
506EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_sub_show);
507
508ssize_t wlp_dev_prim_OUI_sub_store(struct wlp *wlp, const char *buf,
509 size_t size)
510{
511 ssize_t result;
512 unsigned sub;
513 u8 max_sub = ~0;
514 mutex_lock(&wlp->mutex);
515 if (wlp->dev_info == NULL) {
516 result = __wlp_alloc_device_info(wlp);
517 if (result < 0)
518 goto out;
519 }
520 result = sscanf(buf, "%u", &sub);
521 if (sub <= max_sub)
522 wlp->dev_info->prim_dev_type.OUIsubdiv = sub;
523 else
524 result = -EINVAL;
525out:
526 mutex_unlock(&wlp->mutex);
527 return result < 0 ? result : size;
528}
529EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_sub_store);
530
531ssize_t wlp_dev_prim_subcat_show(struct wlp *wlp, char *buf)
532{
533 ssize_t result = 0;
534 mutex_lock(&wlp->mutex);
535 if (wlp->dev_info == NULL) {
536 result = __wlp_setup_device_info(wlp);
537 if (result < 0)
538 goto out;
539 }
540 result = scnprintf(buf, PAGE_SIZE, "%u\n",
541 wlp->dev_info->prim_dev_type.subID);
542out:
543 mutex_unlock(&wlp->mutex);
544 return result;
545}
546EXPORT_SYMBOL_GPL(wlp_dev_prim_subcat_show);
547
548ssize_t wlp_dev_prim_subcat_store(struct wlp *wlp, const char *buf,
549 size_t size)
550{
551 ssize_t result;
552 unsigned sub;
553 __le16 max_sub = ~0;
554 mutex_lock(&wlp->mutex);
555 if (wlp->dev_info == NULL) {
556 result = __wlp_alloc_device_info(wlp);
557 if (result < 0)
558 goto out;
559 }
560 result = sscanf(buf, "%u", &sub);
561 if (sub <= max_sub)
562 wlp->dev_info->prim_dev_type.subID = sub;
563 else
564 result = -EINVAL;
565out:
566 mutex_unlock(&wlp->mutex);
567 return result < 0 ? result : size;
568}
569EXPORT_SYMBOL_GPL(wlp_dev_prim_subcat_store);
570
571/**
572 * Subsystem implementation for interaction with individual WSS via sysfs
573 *
574 * Followed instructions for subsystem in Documentation/filesystems/sysfs.txt
575 */
576
577#define kobj_to_wlp_wss(obj) container_of(obj, struct wlp_wss, kobj)
578#define attr_to_wlp_wss_attr(_attr) \
579 container_of(_attr, struct wlp_wss_attribute, attr)
580
581/**
582 * Sysfs subsystem: forward read calls
583 *
584 * Sysfs operation for forwarding read call to the show method of the
585 * attribute owner
586 */
587static
588ssize_t wlp_wss_attr_show(struct kobject *kobj, struct attribute *attr,
589 char *buf)
590{
591 struct wlp_wss_attribute *wss_attr = attr_to_wlp_wss_attr(attr);
592 struct wlp_wss *wss = kobj_to_wlp_wss(kobj);
593 ssize_t ret = -EIO;
594
595 if (wss_attr->show)
596 ret = wss_attr->show(wss, buf);
597 return ret;
598}
599/**
600 * Sysfs subsystem: forward write calls
601 *
602 * Sysfs operation for forwarding write call to the store method of the
603 * attribute owner
604 */
605static
606ssize_t wlp_wss_attr_store(struct kobject *kobj, struct attribute *attr,
607 const char *buf, size_t count)
608{
609 struct wlp_wss_attribute *wss_attr = attr_to_wlp_wss_attr(attr);
610 struct wlp_wss *wss = kobj_to_wlp_wss(kobj);
611 ssize_t ret = -EIO;
612
613 if (wss_attr->store)
614 ret = wss_attr->store(wss, buf, count);
615 return ret;
616}
617
618static const struct sysfs_ops wss_sysfs_ops = {
619 .show = wlp_wss_attr_show,
620 .store = wlp_wss_attr_store,
621};
622
623struct kobj_type wss_ktype = {
624 .release = wlp_wss_release,
625 .sysfs_ops = &wss_sysfs_ops,
626};
627
628
629/**
630 * Sysfs files for individual WSS
631 */
632
633/**
634 * Print static properties of this WSS
635 *
636 * The name of a WSS may not be null teminated. It's max size is 64 bytes
637 * so we copy it to a larger array just to make sure we print sane data.
638 */
639static ssize_t wlp_wss_properties_show(struct wlp_wss *wss, char *buf)
640{
641 int result = 0;
642
643 if (mutex_lock_interruptible(&wss->mutex))
644 goto out;
645 result = __wlp_wss_properties_show(wss, buf, PAGE_SIZE);
646 mutex_unlock(&wss->mutex);
647out:
648 return result;
649}
650WSS_ATTR(properties, S_IRUGO, wlp_wss_properties_show, NULL);
651
652/**
653 * Print all connected members of this WSS
654 * The EDA cache contains all members of WSS neighborhood.
655 */
656static ssize_t wlp_wss_members_show(struct wlp_wss *wss, char *buf)
657{
658 struct wlp *wlp = container_of(wss, struct wlp, wss);
659 return wlp_eda_show(wlp, buf);
660}
661WSS_ATTR(members, S_IRUGO, wlp_wss_members_show, NULL);
662
663static
664const char *__wlp_strstate[] = {
665 "none",
666 "partially enrolled",
667 "enrolled",
668 "active",
669 "connected",
670};
671
672static const char *wlp_wss_strstate(unsigned state)
673{
674 if (state >= ARRAY_SIZE(__wlp_strstate))
675 return "unknown state";
676 return __wlp_strstate[state];
677}
678
679/*
680 * Print current state of this WSS
681 */
682static ssize_t wlp_wss_state_show(struct wlp_wss *wss, char *buf)
683{
684 int result = 0;
685
686 if (mutex_lock_interruptible(&wss->mutex))
687 goto out;
688 result = scnprintf(buf, PAGE_SIZE, "%s\n",
689 wlp_wss_strstate(wss->state));
690 mutex_unlock(&wss->mutex);
691out:
692 return result;
693}
694WSS_ATTR(state, S_IRUGO, wlp_wss_state_show, NULL);
695
696
697static
698struct attribute *wss_attrs[] = {
699 &wss_attr_properties.attr,
700 &wss_attr_members.attr,
701 &wss_attr_state.attr,
702 NULL,
703};
704
705struct attribute_group wss_attr_group = {
706 .name = NULL, /* we want them in the same directory */
707 .attrs = wss_attrs,
708};
diff --git a/drivers/uwb/wlp/txrx.c b/drivers/uwb/wlp/txrx.c
deleted file mode 100644
index 05dde44b3592..000000000000
--- a/drivers/uwb/wlp/txrx.c
+++ /dev/null
@@ -1,354 +0,0 @@
1/*
2 * WiMedia Logical Link Control Protocol (WLP)
3 * Message exchange infrastructure
4 *
5 * Copyright (C) 2007 Intel Corporation
6 * Reinette Chatre <reinette.chatre@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 */
26
27#include <linux/etherdevice.h>
28#include <linux/slab.h>
29#include <linux/wlp.h>
30
31#include "wlp-internal.h"
32
33/*
34 * Direct incoming association msg to correct parsing routine
35 *
36 * We only expect D1, E1, C1, C3 messages as new. All other incoming
37 * association messages should form part of an established session that is
38 * handled elsewhere.
39 * The handling of these messages often require calling sleeping functions
40 * - this cannot be done in interrupt context. We use the kernel's
41 * workqueue to handle these messages.
42 */
43static
44void wlp_direct_assoc_frame(struct wlp *wlp, struct sk_buff *skb,
45 struct uwb_dev_addr *src)
46{
47 struct device *dev = &wlp->rc->uwb_dev.dev;
48 struct wlp_frame_assoc *assoc = (void *) skb->data;
49 struct wlp_assoc_frame_ctx *frame_ctx;
50
51 frame_ctx = kmalloc(sizeof(*frame_ctx), GFP_ATOMIC);
52 if (frame_ctx == NULL) {
53 dev_err(dev, "WLP: Unable to allocate memory for association "
54 "frame handling.\n");
55 kfree_skb(skb);
56 return;
57 }
58 frame_ctx->wlp = wlp;
59 frame_ctx->skb = skb;
60 frame_ctx->src = *src;
61 switch (assoc->type) {
62 case WLP_ASSOC_D1:
63 INIT_WORK(&frame_ctx->ws, wlp_handle_d1_frame);
64 schedule_work(&frame_ctx->ws);
65 break;
66 case WLP_ASSOC_E1:
67 kfree_skb(skb); /* Temporary until we handle it */
68 kfree(frame_ctx); /* Temporary until we handle it */
69 break;
70 case WLP_ASSOC_C1:
71 INIT_WORK(&frame_ctx->ws, wlp_handle_c1_frame);
72 schedule_work(&frame_ctx->ws);
73 break;
74 case WLP_ASSOC_C3:
75 INIT_WORK(&frame_ctx->ws, wlp_handle_c3_frame);
76 schedule_work(&frame_ctx->ws);
77 break;
78 default:
79 dev_err(dev, "Received unexpected association frame. "
80 "Type = %d \n", assoc->type);
81 kfree_skb(skb);
82 kfree(frame_ctx);
83 break;
84 }
85}
86
87/*
88 * Process incoming association frame
89 *
90 * Although it could be possible to deal with some incoming association
91 * messages without creating a new session we are keeping things simple. We
92 * do not accept new association messages if there is a session in progress
93 * and the messages do not belong to that session.
94 *
95 * If an association message arrives that causes the creation of a session
96 * (WLP_ASSOC_E1) while we are in the process of creating a session then we
97 * rely on the neighbor mutex to protect the data. That is, the new session
98 * will not be started until the previous is completed.
99 */
100static
101void wlp_receive_assoc_frame(struct wlp *wlp, struct sk_buff *skb,
102 struct uwb_dev_addr *src)
103{
104 struct device *dev = &wlp->rc->uwb_dev.dev;
105 struct wlp_frame_assoc *assoc = (void *) skb->data;
106 struct wlp_session *session = wlp->session;
107 u8 version;
108
109 if (wlp_get_version(wlp, &assoc->version, &version,
110 sizeof(assoc->version)) < 0)
111 goto error;
112 if (version != WLP_VERSION) {
113 dev_err(dev, "Unsupported WLP version in association "
114 "message.\n");
115 goto error;
116 }
117 if (session != NULL) {
118 /* Function that created this session is still holding the
119 * &wlp->mutex to protect this session. */
120 if (assoc->type == session->exp_message ||
121 assoc->type == WLP_ASSOC_F0) {
122 if (!memcmp(&session->neighbor_addr, src,
123 sizeof(*src))) {
124 session->data = skb;
125 (session->cb)(wlp);
126 } else {
127 dev_err(dev, "Received expected message from "
128 "unexpected source. Expected message "
129 "%d or F0 from %02x:%02x, but received "
130 "it from %02x:%02x. Dropping.\n",
131 session->exp_message,
132 session->neighbor_addr.data[1],
133 session->neighbor_addr.data[0],
134 src->data[1], src->data[0]);
135 goto error;
136 }
137 } else {
138 dev_err(dev, "Association already in progress. "
139 "Dropping.\n");
140 goto error;
141 }
142 } else {
143 wlp_direct_assoc_frame(wlp, skb, src);
144 }
145 return;
146error:
147 kfree_skb(skb);
148}
149
150/*
151 * Verify incoming frame is from connected neighbor, prep to pass to WLP client
152 *
153 * Verification proceeds according to WLP 0.99 [7.3.1]. The source address
154 * is used to determine which neighbor is sending the frame and the WSS tag
155 * is used to know to which WSS the frame belongs (we only support one WSS
156 * so this test is straight forward).
157 * With the WSS found we need to ensure that we are connected before
158 * allowing the exchange of data frames.
159 */
160static
161int wlp_verify_prep_rx_frame(struct wlp *wlp, struct sk_buff *skb,
162 struct uwb_dev_addr *src)
163{
164 struct device *dev = &wlp->rc->uwb_dev.dev;
165 int result = -EINVAL;
166 struct wlp_eda_node eda_entry;
167 struct wlp_frame_std_abbrv_hdr *hdr = (void *) skb->data;
168
169 /*verify*/
170 result = wlp_copy_eda_node(&wlp->eda, src, &eda_entry);
171 if (result < 0) {
172 if (printk_ratelimit())
173 dev_err(dev, "WLP: Incoming frame is from unknown "
174 "neighbor %02x:%02x.\n", src->data[1],
175 src->data[0]);
176 goto out;
177 }
178 if (hdr->tag != eda_entry.tag) {
179 if (printk_ratelimit())
180 dev_err(dev, "WLP: Tag of incoming frame from "
181 "%02x:%02x does not match expected tag. "
182 "Received 0x%02x, expected 0x%02x. \n",
183 src->data[1], src->data[0], hdr->tag,
184 eda_entry.tag);
185 result = -EINVAL;
186 goto out;
187 }
188 if (eda_entry.state != WLP_WSS_CONNECTED) {
189 if (printk_ratelimit())
190 dev_err(dev, "WLP: Incoming frame from "
191 "%02x:%02x does is not from connected WSS.\n",
192 src->data[1], src->data[0]);
193 result = -EINVAL;
194 goto out;
195 }
196 /*prep*/
197 skb_pull(skb, sizeof(*hdr));
198out:
199 return result;
200}
201
202/*
203 * Receive a WLP frame from device
204 *
205 * @returns: 1 if calling function should free the skb
206 * 0 if it successfully handled skb and freed it
207 * 0 if error occured, will free skb in this case
208 */
209int wlp_receive_frame(struct device *dev, struct wlp *wlp, struct sk_buff *skb,
210 struct uwb_dev_addr *src)
211{
212 unsigned len = skb->len;
213 void *ptr = skb->data;
214 struct wlp_frame_hdr *hdr;
215 int result = 0;
216
217 if (len < sizeof(*hdr)) {
218 dev_err(dev, "Not enough data to parse WLP header.\n");
219 result = -EINVAL;
220 goto out;
221 }
222 hdr = ptr;
223 if (le16_to_cpu(hdr->mux_hdr) != WLP_PROTOCOL_ID) {
224 dev_err(dev, "Not a WLP frame type.\n");
225 result = -EINVAL;
226 goto out;
227 }
228 switch (hdr->type) {
229 case WLP_FRAME_STANDARD:
230 if (len < sizeof(struct wlp_frame_std_abbrv_hdr)) {
231 dev_err(dev, "Not enough data to parse Standard "
232 "WLP header.\n");
233 goto out;
234 }
235 result = wlp_verify_prep_rx_frame(wlp, skb, src);
236 if (result < 0) {
237 if (printk_ratelimit())
238 dev_err(dev, "WLP: Verification of frame "
239 "from neighbor %02x:%02x failed.\n",
240 src->data[1], src->data[0]);
241 goto out;
242 }
243 result = 1;
244 break;
245 case WLP_FRAME_ABBREVIATED:
246 dev_err(dev, "Abbreviated frame received. FIXME?\n");
247 kfree_skb(skb);
248 break;
249 case WLP_FRAME_CONTROL:
250 dev_err(dev, "Control frame received. FIXME?\n");
251 kfree_skb(skb);
252 break;
253 case WLP_FRAME_ASSOCIATION:
254 if (len < sizeof(struct wlp_frame_assoc)) {
255 dev_err(dev, "Not enough data to parse Association "
256 "WLP header.\n");
257 goto out;
258 }
259 wlp_receive_assoc_frame(wlp, skb, src);
260 break;
261 default:
262 dev_err(dev, "Invalid frame received.\n");
263 result = -EINVAL;
264 break;
265 }
266out:
267 if (result < 0) {
268 kfree_skb(skb);
269 result = 0;
270 }
271 return result;
272}
273EXPORT_SYMBOL_GPL(wlp_receive_frame);
274
275
276/*
277 * Verify frame from network stack, prepare for further transmission
278 *
279 * @skb: the socket buffer that needs to be prepared for transmission (it
280 * is in need of a WLP header). If this is a broadcast frame we take
281 * over the entire transmission.
282 * If it is a unicast the WSS connection should already be established
283 * and transmission will be done by the calling function.
284 * @dst: On return this will contain the device address to which the
285 * frame is destined.
286 * @returns: 0 on success no tx : WLP header successfully applied to skb buffer,
287 * calling function can proceed with tx
288 * 1 on success with tx : WLP will take over transmission of this
289 * frame
290 * <0 on error
291 *
292 * The network stack (WLP client) is attempting to transmit a frame. We can
293 * only transmit data if a local WSS is at least active (connection will be
294 * done here if this is a broadcast frame and neighbor also has the WSS
295 * active).
296 *
297 * The frame can be either broadcast or unicast. Broadcast in a WSS is
298 * supported via multicast, but we don't support multicast yet (until
299 * devices start to support MAB IEs). If a broadcast frame needs to be
300 * transmitted it is treated as a unicast frame to each neighbor. In this
301 * case the WLP takes over transmission of the skb and returns 1
302 * to the caller to indicate so. Also, in this case, if a neighbor has the
303 * same WSS activated but is not connected then the WSS connection will be
304 * done at this time. The neighbor's virtual address will be learned at
305 * this time.
306 *
307 * The destination address in a unicast frame is the virtual address of the
308 * neighbor. This address only becomes known when a WSS connection is
309 * established. We thus rely on a broadcast frame to trigger the setup of
310 * WSS connections to all neighbors before we are able to send unicast
311 * frames to them. This seems reasonable as IP would usually use ARP first
312 * before any unicast frames are sent.
313 *
314 * If we are already connected to the neighbor (neighbor's virtual address
315 * is known) we just prepare the WLP header and the caller will continue to
316 * send the frame.
317 *
318 * A failure in this function usually indicates something that cannot be
319 * fixed automatically. So, if this function fails (@return < 0) the calling
320 * function should not retry to send the frame as it will very likely keep
321 * failing.
322 *
323 */
324int wlp_prepare_tx_frame(struct device *dev, struct wlp *wlp,
325 struct sk_buff *skb, struct uwb_dev_addr *dst)
326{
327 int result = -EINVAL;
328 struct ethhdr *eth_hdr = (void *) skb->data;
329
330 if (is_multicast_ether_addr(eth_hdr->h_dest)) {
331 result = wlp_eda_for_each(&wlp->eda, wlp_wss_send_copy, skb);
332 if (result < 0) {
333 if (printk_ratelimit())
334 dev_err(dev, "Unable to handle broadcast "
335 "frame from WLP client.\n");
336 goto out;
337 }
338 dev_kfree_skb_irq(skb);
339 result = 1;
340 /* Frame will be transmitted by WLP. */
341 } else {
342 result = wlp_eda_for_virtual(&wlp->eda, eth_hdr->h_dest, dst,
343 wlp_wss_prep_hdr, skb);
344 if (unlikely(result < 0)) {
345 if (printk_ratelimit())
346 dev_err(dev, "Unable to prepare "
347 "skb for transmission. \n");
348 goto out;
349 }
350 }
351out:
352 return result;
353}
354EXPORT_SYMBOL_GPL(wlp_prepare_tx_frame);
diff --git a/drivers/uwb/wlp/wlp-internal.h b/drivers/uwb/wlp/wlp-internal.h
deleted file mode 100644
index 3e8d5de7c5b9..000000000000
--- a/drivers/uwb/wlp/wlp-internal.h
+++ /dev/null
@@ -1,224 +0,0 @@
1/*
2 * WiMedia Logical Link Control Protocol (WLP)
3 * Internal API
4 *
5 * Copyright (C) 2007 Intel Corporation
6 * Reinette Chatre <reinette.chatre@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
24#ifndef __WLP_INTERNAL_H__
25#define __WLP_INTERNAL_H__
26
27/**
28 * State of WSS connection
29 *
30 * A device needs to connect to a neighbor in an activated WSS before data
31 * can be transmitted. The spec also distinguishes between a new connection
32 * attempt and a connection attempt after previous connection attempts. The
33 * state WLP_WSS_CONNECT_FAILED is used for this scenario. See WLP 0.99
34 * [7.2.6]
35 */
36enum wlp_wss_connect {
37 WLP_WSS_UNCONNECTED = 0,
38 WLP_WSS_CONNECTED,
39 WLP_WSS_CONNECT_FAILED,
40};
41
42extern struct kobj_type wss_ktype;
43extern struct attribute_group wss_attr_group;
44
45/* This should be changed to a dynamic array where entries are sorted
46 * by eth_addr and search is done in a binary form
47 *
48 * Although thinking twice about it: this technologie's maximum reach
49 * is 10 meters...unless you want to pack too much stuff in around
50 * your radio controller/WLP device, the list will probably not be
51 * too big.
52 *
53 * In any case, there is probably some data structure in the kernel
54 * than we could reused for that already.
55 *
56 * The below structure is really just good while we support one WSS per
57 * host.
58 */
59struct wlp_eda_node {
60 struct list_head list_node;
61 unsigned char eth_addr[ETH_ALEN];
62 struct uwb_dev_addr dev_addr;
63 struct wlp_wss *wss;
64 unsigned char virt_addr[ETH_ALEN];
65 u8 tag;
66 enum wlp_wss_connect state;
67};
68
69typedef int (*wlp_eda_for_each_f)(struct wlp *, struct wlp_eda_node *, void *);
70
71extern void wlp_eda_init(struct wlp_eda *);
72extern void wlp_eda_release(struct wlp_eda *);
73extern int wlp_eda_create_node(struct wlp_eda *,
74 const unsigned char eth_addr[ETH_ALEN],
75 const struct uwb_dev_addr *);
76extern void wlp_eda_rm_node(struct wlp_eda *, const struct uwb_dev_addr *);
77extern int wlp_eda_update_node(struct wlp_eda *,
78 const struct uwb_dev_addr *,
79 struct wlp_wss *,
80 const unsigned char virt_addr[ETH_ALEN],
81 const u8, const enum wlp_wss_connect);
82extern int wlp_eda_update_node_state(struct wlp_eda *,
83 const struct uwb_dev_addr *,
84 const enum wlp_wss_connect);
85
86extern int wlp_copy_eda_node(struct wlp_eda *, struct uwb_dev_addr *,
87 struct wlp_eda_node *);
88extern int wlp_eda_for_each(struct wlp_eda *, wlp_eda_for_each_f , void *);
89extern int wlp_eda_for_virtual(struct wlp_eda *,
90 const unsigned char eth_addr[ETH_ALEN],
91 struct uwb_dev_addr *,
92 wlp_eda_for_each_f , void *);
93
94
95extern void wlp_remove_neighbor_tmp_info(struct wlp_neighbor_e *);
96
97extern size_t wlp_wss_key_print(char *, size_t, u8 *);
98
99/* Function called when no more references to WSS exists */
100extern void wlp_wss_release(struct kobject *);
101
102extern void wlp_wss_reset(struct wlp_wss *);
103extern int wlp_wss_create_activate(struct wlp_wss *, struct wlp_uuid *,
104 char *, unsigned, unsigned);
105extern int wlp_wss_enroll_activate(struct wlp_wss *, struct wlp_uuid *,
106 struct uwb_dev_addr *);
107extern ssize_t wlp_discover(struct wlp *);
108
109extern int wlp_enroll_neighbor(struct wlp *, struct wlp_neighbor_e *,
110 struct wlp_wss *, struct wlp_uuid *);
111extern int wlp_wss_is_active(struct wlp *, struct wlp_wss *,
112 struct uwb_dev_addr *);
113
114struct wlp_assoc_conn_ctx {
115 struct work_struct ws;
116 struct wlp *wlp;
117 struct sk_buff *skb;
118 struct wlp_eda_node eda_entry;
119};
120
121
122extern int wlp_wss_connect_prep(struct wlp *, struct wlp_eda_node *, void *);
123extern int wlp_wss_send_copy(struct wlp *, struct wlp_eda_node *, void *);
124
125
126/* Message handling */
127struct wlp_assoc_frame_ctx {
128 struct work_struct ws;
129 struct wlp *wlp;
130 struct sk_buff *skb;
131 struct uwb_dev_addr src;
132};
133
134extern int wlp_wss_prep_hdr(struct wlp *, struct wlp_eda_node *, void *);
135extern void wlp_handle_d1_frame(struct work_struct *);
136extern int wlp_parse_d2_frame_to_cache(struct wlp *, struct sk_buff *,
137 struct wlp_neighbor_e *);
138extern int wlp_parse_d2_frame_to_enroll(struct wlp_wss *, struct sk_buff *,
139 struct wlp_neighbor_e *,
140 struct wlp_uuid *);
141extern void wlp_handle_c1_frame(struct work_struct *);
142extern void wlp_handle_c3_frame(struct work_struct *);
143extern int wlp_parse_c3c4_frame(struct wlp *, struct sk_buff *,
144 struct wlp_uuid *, u8 *,
145 struct uwb_mac_addr *);
146extern int wlp_parse_f0(struct wlp *, struct sk_buff *);
147extern int wlp_send_assoc_frame(struct wlp *, struct wlp_wss *,
148 struct uwb_dev_addr *, enum wlp_assoc_type);
149extern ssize_t wlp_get_version(struct wlp *, struct wlp_attr_version *,
150 u8 *, ssize_t);
151extern ssize_t wlp_get_wssid(struct wlp *, struct wlp_attr_wssid *,
152 struct wlp_uuid *, ssize_t);
153extern int __wlp_alloc_device_info(struct wlp *);
154extern int __wlp_setup_device_info(struct wlp *);
155
156extern struct wlp_wss_attribute wss_attribute_properties;
157extern struct wlp_wss_attribute wss_attribute_members;
158extern struct wlp_wss_attribute wss_attribute_state;
159
160static inline
161size_t wlp_wss_uuid_print(char *buf, size_t bufsize, struct wlp_uuid *uuid)
162{
163 size_t result;
164
165 result = scnprintf(buf, bufsize,
166 "%02x:%02x:%02x:%02x:%02x:%02x:"
167 "%02x:%02x:%02x:%02x:%02x:%02x:"
168 "%02x:%02x:%02x:%02x",
169 uuid->data[0], uuid->data[1],
170 uuid->data[2], uuid->data[3],
171 uuid->data[4], uuid->data[5],
172 uuid->data[6], uuid->data[7],
173 uuid->data[8], uuid->data[9],
174 uuid->data[10], uuid->data[11],
175 uuid->data[12], uuid->data[13],
176 uuid->data[14], uuid->data[15]);
177 return result;
178}
179
180/**
181 * FIXME: How should a nonce be displayed?
182 */
183static inline
184size_t wlp_wss_nonce_print(char *buf, size_t bufsize, struct wlp_nonce *nonce)
185{
186 size_t result;
187
188 result = scnprintf(buf, bufsize,
189 "%02x %02x %02x %02x %02x %02x "
190 "%02x %02x %02x %02x %02x %02x "
191 "%02x %02x %02x %02x",
192 nonce->data[0], nonce->data[1],
193 nonce->data[2], nonce->data[3],
194 nonce->data[4], nonce->data[5],
195 nonce->data[6], nonce->data[7],
196 nonce->data[8], nonce->data[9],
197 nonce->data[10], nonce->data[11],
198 nonce->data[12], nonce->data[13],
199 nonce->data[14], nonce->data[15]);
200 return result;
201}
202
203
204static inline
205void wlp_session_cb(struct wlp *wlp)
206{
207 struct completion *completion = wlp->session->cb_priv;
208 complete(completion);
209}
210
211static inline
212int wlp_uuid_is_set(struct wlp_uuid *uuid)
213{
214 struct wlp_uuid zero_uuid = { .data = { 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00} };
218
219 if (!memcmp(uuid, &zero_uuid, sizeof(*uuid)))
220 return 0;
221 return 1;
222}
223
224#endif /* __WLP_INTERNAL_H__ */
diff --git a/drivers/uwb/wlp/wlp-lc.c b/drivers/uwb/wlp/wlp-lc.c
deleted file mode 100644
index 7f6a630bf26c..000000000000
--- a/drivers/uwb/wlp/wlp-lc.c
+++ /dev/null
@@ -1,560 +0,0 @@
1/*
2 * WiMedia Logical Link Control Protocol (WLP)
3 *
4 * Copyright (C) 2005-2006 Intel Corporation
5 * Reinette Chatre <reinette.chatre@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * FIXME: docs
23 */
24#include <linux/wlp.h>
25#include <linux/slab.h>
26
27#include "wlp-internal.h"
28
29static
30void wlp_neighbor_init(struct wlp_neighbor_e *neighbor)
31{
32 INIT_LIST_HEAD(&neighbor->wssid);
33}
34
35/**
36 * Create area for device information storage
37 *
38 * wlp->mutex must be held
39 */
40int __wlp_alloc_device_info(struct wlp *wlp)
41{
42 struct device *dev = &wlp->rc->uwb_dev.dev;
43 BUG_ON(wlp->dev_info != NULL);
44 wlp->dev_info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
45 if (wlp->dev_info == NULL) {
46 dev_err(dev, "WLP: Unable to allocate memory for "
47 "device information.\n");
48 return -ENOMEM;
49 }
50 return 0;
51}
52
53
54/**
55 * Fill in device information using function provided by driver
56 *
57 * wlp->mutex must be held
58 */
59static
60void __wlp_fill_device_info(struct wlp *wlp)
61{
62 wlp->fill_device_info(wlp, wlp->dev_info);
63}
64
65/**
66 * Setup device information
67 *
68 * Allocate area for device information and populate it.
69 *
70 * wlp->mutex must be held
71 */
72int __wlp_setup_device_info(struct wlp *wlp)
73{
74 int result;
75 struct device *dev = &wlp->rc->uwb_dev.dev;
76
77 result = __wlp_alloc_device_info(wlp);
78 if (result < 0) {
79 dev_err(dev, "WLP: Unable to allocate area for "
80 "device information.\n");
81 return result;
82 }
83 __wlp_fill_device_info(wlp);
84 return 0;
85}
86
87/**
88 * Remove information about neighbor stored temporarily
89 *
90 * Information learned during discovey should only be stored when the
91 * device enrolls in the neighbor's WSS. We do need to store this
92 * information temporarily in order to present it to the user.
93 *
94 * We are only interested in keeping neighbor WSS information if that
95 * neighbor is accepting enrollment.
96 *
97 * should be called with wlp->nbmutex held
98 */
99void wlp_remove_neighbor_tmp_info(struct wlp_neighbor_e *neighbor)
100{
101 struct wlp_wssid_e *wssid_e, *next;
102 u8 keep;
103 if (!list_empty(&neighbor->wssid)) {
104 list_for_each_entry_safe(wssid_e, next, &neighbor->wssid,
105 node) {
106 if (wssid_e->info != NULL) {
107 keep = wssid_e->info->accept_enroll;
108 kfree(wssid_e->info);
109 wssid_e->info = NULL;
110 if (!keep) {
111 list_del(&wssid_e->node);
112 kfree(wssid_e);
113 }
114 }
115 }
116 }
117 if (neighbor->info != NULL) {
118 kfree(neighbor->info);
119 neighbor->info = NULL;
120 }
121}
122
123/*
124 * Populate WLP neighborhood cache with neighbor information
125 *
126 * A new neighbor is found. If it is discoverable then we add it to the
127 * neighborhood cache.
128 *
129 */
130static
131int wlp_add_neighbor(struct wlp *wlp, struct uwb_dev *dev)
132{
133 int result = 0;
134 int discoverable;
135 struct wlp_neighbor_e *neighbor;
136
137 /*
138 * FIXME:
139 * Use contents of WLP IE found in beacon cache to determine if
140 * neighbor is discoverable.
141 * The device does not support WLP IE yet so this still needs to be
142 * done. Until then we assume all devices are discoverable.
143 */
144 discoverable = 1; /* will be changed when FIXME disappears */
145 if (discoverable) {
146 /* Add neighbor to cache for discovery */
147 neighbor = kzalloc(sizeof(*neighbor), GFP_KERNEL);
148 if (neighbor == NULL) {
149 dev_err(&dev->dev, "Unable to create memory for "
150 "new neighbor. \n");
151 result = -ENOMEM;
152 goto error_no_mem;
153 }
154 wlp_neighbor_init(neighbor);
155 uwb_dev_get(dev);
156 neighbor->uwb_dev = dev;
157 list_add(&neighbor->node, &wlp->neighbors);
158 }
159error_no_mem:
160 return result;
161}
162
163/**
164 * Remove one neighbor from cache
165 */
166static
167void __wlp_neighbor_release(struct wlp_neighbor_e *neighbor)
168{
169 struct wlp_wssid_e *wssid_e, *next_wssid_e;
170
171 list_for_each_entry_safe(wssid_e, next_wssid_e,
172 &neighbor->wssid, node) {
173 list_del(&wssid_e->node);
174 kfree(wssid_e);
175 }
176 uwb_dev_put(neighbor->uwb_dev);
177 list_del(&neighbor->node);
178 kfree(neighbor);
179}
180
181/**
182 * Clear entire neighborhood cache.
183 */
184static
185void __wlp_neighbors_release(struct wlp *wlp)
186{
187 struct wlp_neighbor_e *neighbor, *next;
188 if (list_empty(&wlp->neighbors))
189 return;
190 list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
191 __wlp_neighbor_release(neighbor);
192 }
193}
194
195static
196void wlp_neighbors_release(struct wlp *wlp)
197{
198 mutex_lock(&wlp->nbmutex);
199 __wlp_neighbors_release(wlp);
200 mutex_unlock(&wlp->nbmutex);
201}
202
203
204
205/**
206 * Send D1 message to neighbor, receive D2 message
207 *
208 * @neighbor: neighbor to which D1 message will be sent
209 * @wss: if not NULL, it is an enrollment request for this WSS
210 * @wssid: if wss not NULL, this is the wssid of the WSS in which we
211 * want to enroll
212 *
213 * A D1/D2 exchange is done for one of two reasons: discovery or
214 * enrollment. If done for discovery the D1 message is sent to the neighbor
215 * and the contents of the D2 response is stored in a temporary cache.
216 * If done for enrollment the @wss and @wssid are provided also. In this
217 * case the D1 message is sent to the neighbor, the D2 response is parsed
218 * for enrollment of the WSS with wssid.
219 *
220 * &wss->mutex is held
221 */
222static
223int wlp_d1d2_exchange(struct wlp *wlp, struct wlp_neighbor_e *neighbor,
224 struct wlp_wss *wss, struct wlp_uuid *wssid)
225{
226 int result;
227 struct device *dev = &wlp->rc->uwb_dev.dev;
228 DECLARE_COMPLETION_ONSTACK(completion);
229 struct wlp_session session;
230 struct sk_buff *skb;
231 struct wlp_frame_assoc *resp;
232 struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr;
233
234 mutex_lock(&wlp->mutex);
235 if (!wlp_uuid_is_set(&wlp->uuid)) {
236 dev_err(dev, "WLP: UUID is not set. Set via sysfs to "
237 "proceed.\n");
238 result = -ENXIO;
239 goto out;
240 }
241 /* Send D1 association frame */
242 result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_D1);
243 if (result < 0) {
244 dev_err(dev, "Unable to send D1 frame to neighbor "
245 "%02x:%02x (%d)\n", dev_addr->data[1],
246 dev_addr->data[0], result);
247 goto out;
248 }
249 /* Create session, wait for response */
250 session.exp_message = WLP_ASSOC_D2;
251 session.cb = wlp_session_cb;
252 session.cb_priv = &completion;
253 session.neighbor_addr = *dev_addr;
254 BUG_ON(wlp->session != NULL);
255 wlp->session = &session;
256 /* Wait for D2/F0 frame */
257 result = wait_for_completion_interruptible_timeout(&completion,
258 WLP_PER_MSG_TIMEOUT * HZ);
259 if (result == 0) {
260 result = -ETIMEDOUT;
261 dev_err(dev, "Timeout while sending D1 to neighbor "
262 "%02x:%02x.\n", dev_addr->data[1],
263 dev_addr->data[0]);
264 goto error_session;
265 }
266 if (result < 0) {
267 dev_err(dev, "Unable to discover/enroll neighbor %02x:%02x.\n",
268 dev_addr->data[1], dev_addr->data[0]);
269 goto error_session;
270 }
271 /* Parse message in session->data: it will be either D2 or F0 */
272 skb = session.data;
273 resp = (void *) skb->data;
274
275 if (resp->type == WLP_ASSOC_F0) {
276 result = wlp_parse_f0(wlp, skb);
277 if (result < 0)
278 dev_err(dev, "WLP: Unable to parse F0 from neighbor "
279 "%02x:%02x.\n", dev_addr->data[1],
280 dev_addr->data[0]);
281 result = -EINVAL;
282 goto error_resp_parse;
283 }
284 if (wss == NULL) {
285 /* Discovery */
286 result = wlp_parse_d2_frame_to_cache(wlp, skb, neighbor);
287 if (result < 0) {
288 dev_err(dev, "WLP: Unable to parse D2 message from "
289 "neighbor %02x:%02x for discovery.\n",
290 dev_addr->data[1], dev_addr->data[0]);
291 goto error_resp_parse;
292 }
293 } else {
294 /* Enrollment */
295 result = wlp_parse_d2_frame_to_enroll(wss, skb, neighbor,
296 wssid);
297 if (result < 0) {
298 dev_err(dev, "WLP: Unable to parse D2 message from "
299 "neighbor %02x:%02x for enrollment.\n",
300 dev_addr->data[1], dev_addr->data[0]);
301 goto error_resp_parse;
302 }
303 }
304error_resp_parse:
305 kfree_skb(skb);
306error_session:
307 wlp->session = NULL;
308out:
309 mutex_unlock(&wlp->mutex);
310 return result;
311}
312
313/**
314 * Enroll into WSS of provided WSSID by using neighbor as registrar
315 *
316 * &wss->mutex is held
317 */
318int wlp_enroll_neighbor(struct wlp *wlp, struct wlp_neighbor_e *neighbor,
319 struct wlp_wss *wss, struct wlp_uuid *wssid)
320{
321 int result = 0;
322 struct device *dev = &wlp->rc->uwb_dev.dev;
323 char buf[WLP_WSS_UUID_STRSIZE];
324 struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr;
325
326 wlp_wss_uuid_print(buf, sizeof(buf), wssid);
327
328 result = wlp_d1d2_exchange(wlp, neighbor, wss, wssid);
329 if (result < 0) {
330 dev_err(dev, "WLP: D1/D2 message exchange for enrollment "
331 "failed. result = %d \n", result);
332 goto out;
333 }
334 if (wss->state != WLP_WSS_STATE_PART_ENROLLED) {
335 dev_err(dev, "WLP: Unable to enroll into WSS %s using "
336 "neighbor %02x:%02x. \n", buf,
337 dev_addr->data[1], dev_addr->data[0]);
338 result = -EINVAL;
339 goto out;
340 }
341 if (wss->secure_status == WLP_WSS_SECURE) {
342 dev_err(dev, "FIXME: need to complete secure enrollment.\n");
343 result = -EINVAL;
344 goto error;
345 } else {
346 wss->state = WLP_WSS_STATE_ENROLLED;
347 dev_dbg(dev, "WLP: Success Enrollment into unsecure WSS "
348 "%s using neighbor %02x:%02x. \n",
349 buf, dev_addr->data[1], dev_addr->data[0]);
350 }
351out:
352 return result;
353error:
354 wlp_wss_reset(wss);
355 return result;
356}
357
358/**
359 * Discover WSS information of neighbor's active WSS
360 */
361static
362int wlp_discover_neighbor(struct wlp *wlp,
363 struct wlp_neighbor_e *neighbor)
364{
365 return wlp_d1d2_exchange(wlp, neighbor, NULL, NULL);
366}
367
368
369/**
370 * Each neighbor in the neighborhood cache is discoverable. Discover it.
371 *
372 * Discovery is done through sending of D1 association frame and parsing
373 * the D2 association frame response. Only wssid from D2 will be included
374 * in neighbor cache, rest is just displayed to user and forgotten.
375 *
376 * The discovery is not done in parallel. This is simple and enables us to
377 * maintain only one association context.
378 *
379 * The discovery of one neighbor does not affect the other, but if the
380 * discovery of a neighbor fails it is removed from the neighborhood cache.
381 */
382static
383int wlp_discover_all_neighbors(struct wlp *wlp)
384{
385 int result = 0;
386 struct device *dev = &wlp->rc->uwb_dev.dev;
387 struct wlp_neighbor_e *neighbor, *next;
388
389 list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
390 result = wlp_discover_neighbor(wlp, neighbor);
391 if (result < 0) {
392 dev_err(dev, "WLP: Unable to discover neighbor "
393 "%02x:%02x, removing from neighborhood. \n",
394 neighbor->uwb_dev->dev_addr.data[1],
395 neighbor->uwb_dev->dev_addr.data[0]);
396 __wlp_neighbor_release(neighbor);
397 }
398 }
399 return result;
400}
401
402static int wlp_add_neighbor_helper(struct device *dev, void *priv)
403{
404 struct wlp *wlp = priv;
405 struct uwb_dev *uwb_dev = to_uwb_dev(dev);
406
407 return wlp_add_neighbor(wlp, uwb_dev);
408}
409
410/**
411 * Discover WLP neighborhood
412 *
413 * Will send D1 association frame to all devices in beacon group that have
414 * discoverable bit set in WLP IE. D2 frames will be received, information
415 * displayed to user in @buf. Partial information (from D2 association
416 * frame) will be cached to assist with future association
417 * requests.
418 *
419 * The discovery of the WLP neighborhood is triggered by the user. This
420 * should occur infrequently and we thus free current cache and re-allocate
421 * memory if needed.
422 *
423 * If one neighbor fails during initial discovery (determining if it is a
424 * neighbor or not), we fail all - note that interaction with neighbor has
425 * not occured at this point so if a failure occurs we know something went wrong
426 * locally. We thus undo everything.
427 */
428ssize_t wlp_discover(struct wlp *wlp)
429{
430 int result = 0;
431 struct device *dev = &wlp->rc->uwb_dev.dev;
432
433 mutex_lock(&wlp->nbmutex);
434 /* Clear current neighborhood cache. */
435 __wlp_neighbors_release(wlp);
436 /* Determine which devices in neighborhood. Repopulate cache. */
437 result = uwb_dev_for_each(wlp->rc, wlp_add_neighbor_helper, wlp);
438 if (result < 0) {
439 /* May have partial neighbor information, release all. */
440 __wlp_neighbors_release(wlp);
441 goto error_dev_for_each;
442 }
443 /* Discover the properties of devices in neighborhood. */
444 result = wlp_discover_all_neighbors(wlp);
445 /* In case of failure we still print our partial results. */
446 if (result < 0) {
447 dev_err(dev, "Unable to fully discover neighborhood. \n");
448 result = 0;
449 }
450error_dev_for_each:
451 mutex_unlock(&wlp->nbmutex);
452 return result;
453}
454
455/**
456 * Handle events from UWB stack
457 *
458 * We handle events conservatively. If a neighbor goes off the air we
459 * remove it from the neighborhood. If an association process is in
460 * progress this function will block waiting for the nbmutex to become
461 * free. The association process will thus be allowed to complete before it
462 * is removed.
463 */
464static
465void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev,
466 enum uwb_notifs event)
467{
468 struct wlp *wlp = _wlp;
469 struct device *dev = &wlp->rc->uwb_dev.dev;
470 struct wlp_neighbor_e *neighbor, *next;
471 int result;
472 switch (event) {
473 case UWB_NOTIF_ONAIR:
474 result = wlp_eda_create_node(&wlp->eda,
475 uwb_dev->mac_addr.data,
476 &uwb_dev->dev_addr);
477 if (result < 0)
478 dev_err(dev, "WLP: Unable to add new neighbor "
479 "%02x:%02x to EDA cache.\n",
480 uwb_dev->dev_addr.data[1],
481 uwb_dev->dev_addr.data[0]);
482 break;
483 case UWB_NOTIF_OFFAIR:
484 wlp_eda_rm_node(&wlp->eda, &uwb_dev->dev_addr);
485 mutex_lock(&wlp->nbmutex);
486 list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
487 if (neighbor->uwb_dev == uwb_dev)
488 __wlp_neighbor_release(neighbor);
489 }
490 mutex_unlock(&wlp->nbmutex);
491 break;
492 default:
493 dev_err(dev, "don't know how to handle event %d from uwb\n",
494 event);
495 }
496}
497
498static void wlp_channel_changed(struct uwb_pal *pal, int channel)
499{
500 struct wlp *wlp = container_of(pal, struct wlp, pal);
501
502 if (channel < 0)
503 netif_carrier_off(wlp->ndev);
504 else
505 netif_carrier_on(wlp->ndev);
506}
507
508int wlp_setup(struct wlp *wlp, struct uwb_rc *rc, struct net_device *ndev)
509{
510 int result;
511
512 BUG_ON(wlp->fill_device_info == NULL);
513 BUG_ON(wlp->xmit_frame == NULL);
514 BUG_ON(wlp->stop_queue == NULL);
515 BUG_ON(wlp->start_queue == NULL);
516
517 wlp->rc = rc;
518 wlp->ndev = ndev;
519 wlp_eda_init(&wlp->eda);/* Set up address cache */
520 wlp->uwb_notifs_handler.cb = wlp_uwb_notifs_cb;
521 wlp->uwb_notifs_handler.data = wlp;
522 uwb_notifs_register(rc, &wlp->uwb_notifs_handler);
523
524 uwb_pal_init(&wlp->pal);
525 wlp->pal.rc = rc;
526 wlp->pal.channel_changed = wlp_channel_changed;
527 result = uwb_pal_register(&wlp->pal);
528 if (result < 0)
529 uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
530
531 return result;
532}
533EXPORT_SYMBOL_GPL(wlp_setup);
534
535void wlp_remove(struct wlp *wlp)
536{
537 wlp_neighbors_release(wlp);
538 uwb_pal_unregister(&wlp->pal);
539 uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
540 wlp_eda_release(&wlp->eda);
541 mutex_lock(&wlp->mutex);
542 if (wlp->dev_info != NULL)
543 kfree(wlp->dev_info);
544 mutex_unlock(&wlp->mutex);
545 wlp->rc = NULL;
546}
547EXPORT_SYMBOL_GPL(wlp_remove);
548
549/**
550 * wlp_reset_all - reset the WLP hardware
551 * @wlp: the WLP device to reset.
552 *
553 * This schedules a full hardware reset of the WLP device. The radio
554 * controller and any other PALs will also be reset.
555 */
556void wlp_reset_all(struct wlp *wlp)
557{
558 uwb_rc_reset_all(wlp->rc);
559}
560EXPORT_SYMBOL_GPL(wlp_reset_all);
diff --git a/drivers/uwb/wlp/wss-lc.c b/drivers/uwb/wlp/wss-lc.c
deleted file mode 100644
index 67872c83b679..000000000000
--- a/drivers/uwb/wlp/wss-lc.c
+++ /dev/null
@@ -1,959 +0,0 @@
1/*
2 * WiMedia Logical Link Control Protocol (WLP)
3 *
4 * Copyright (C) 2007 Intel Corporation
5 * Reinette Chatre <reinette.chatre@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * Implementation of the WLP association protocol.
23 *
24 * FIXME: Docs
25 *
26 * A UWB network interface will configure a WSS through wlp_wss_setup() after
27 * the interface has been assigned a MAC address, typically after
28 * "ifconfig" has been called. When the interface goes down it should call
29 * wlp_wss_remove().
30 *
31 * When the WSS is ready for use the user interacts via sysfs to create,
32 * discover, and activate WSS.
33 *
34 * wlp_wss_enroll_activate()
35 *
36 * wlp_wss_create_activate()
37 * wlp_wss_set_wssid_hash()
38 * wlp_wss_comp_wssid_hash()
39 * wlp_wss_sel_bcast_addr()
40 * wlp_wss_sysfs_add()
41 *
42 * Called when no more references to WSS exist:
43 * wlp_wss_release()
44 * wlp_wss_reset()
45 */
46#include <linux/etherdevice.h> /* for is_valid_ether_addr */
47#include <linux/skbuff.h>
48#include <linux/slab.h>
49#include <linux/wlp.h>
50
51#include "wlp-internal.h"
52
53size_t wlp_wss_key_print(char *buf, size_t bufsize, u8 *key)
54{
55 size_t result;
56
57 result = scnprintf(buf, bufsize,
58 "%02x %02x %02x %02x %02x %02x "
59 "%02x %02x %02x %02x %02x %02x "
60 "%02x %02x %02x %02x",
61 key[0], key[1], key[2], key[3],
62 key[4], key[5], key[6], key[7],
63 key[8], key[9], key[10], key[11],
64 key[12], key[13], key[14], key[15]);
65 return result;
66}
67
68/**
69 * Compute WSSID hash
70 * WLP Draft 0.99 [7.2.1]
71 *
72 * The WSSID hash for a WSSID is the result of an octet-wise exclusive-OR
73 * of all octets in the WSSID.
74 */
75static
76u8 wlp_wss_comp_wssid_hash(struct wlp_uuid *wssid)
77{
78 return wssid->data[0] ^ wssid->data[1] ^ wssid->data[2]
79 ^ wssid->data[3] ^ wssid->data[4] ^ wssid->data[5]
80 ^ wssid->data[6] ^ wssid->data[7] ^ wssid->data[8]
81 ^ wssid->data[9] ^ wssid->data[10] ^ wssid->data[11]
82 ^ wssid->data[12] ^ wssid->data[13] ^ wssid->data[14]
83 ^ wssid->data[15];
84}
85
86/**
87 * Select a multicast EUI-48 for the WSS broadcast address.
88 * WLP Draft 0.99 [7.2.1]
89 *
90 * Selected based on the WiMedia Alliance OUI, 00-13-88, within the WLP
91 * range, [01-13-88-00-01-00, 01-13-88-00-01-FF] inclusive.
92 *
93 * This address is currently hardcoded.
94 * FIXME?
95 */
96static
97struct uwb_mac_addr wlp_wss_sel_bcast_addr(struct wlp_wss *wss)
98{
99 struct uwb_mac_addr bcast = {
100 .data = { 0x01, 0x13, 0x88, 0x00, 0x01, 0x00 }
101 };
102 return bcast;
103}
104
105/**
106 * Clear the contents of the WSS structure - all except kobj, mutex, virtual
107 *
108 * We do not want to reinitialize - the internal kobj should not change as
109 * it still points to the parent received during setup. The mutex should
110 * remain also. We thus just reset values individually.
111 * The virutal address assigned to WSS will remain the same for the
112 * lifetime of the WSS. We only reset the fields that can change during its
113 * lifetime.
114 */
115void wlp_wss_reset(struct wlp_wss *wss)
116{
117 memset(&wss->wssid, 0, sizeof(wss->wssid));
118 wss->hash = 0;
119 memset(&wss->name[0], 0, sizeof(wss->name));
120 memset(&wss->bcast, 0, sizeof(wss->bcast));
121 wss->secure_status = WLP_WSS_UNSECURE;
122 memset(&wss->master_key[0], 0, sizeof(wss->master_key));
123 wss->tag = 0;
124 wss->state = WLP_WSS_STATE_NONE;
125}
126
127/**
128 * Create sysfs infrastructure for WSS
129 *
130 * The WSS is configured to have the interface as parent (see wlp_wss_setup())
131 * a new sysfs directory that includes wssid as its name is created in the
132 * interface's sysfs directory. The group of files interacting with WSS are
133 * created also.
134 */
135static
136int wlp_wss_sysfs_add(struct wlp_wss *wss, char *wssid_str)
137{
138 struct wlp *wlp = container_of(wss, struct wlp, wss);
139 struct device *dev = &wlp->rc->uwb_dev.dev;
140 int result;
141
142 result = kobject_set_name(&wss->kobj, "wss-%s", wssid_str);
143 if (result < 0)
144 return result;
145 wss->kobj.ktype = &wss_ktype;
146 result = kobject_init_and_add(&wss->kobj,
147 &wss_ktype, wss->kobj.parent, "wlp");
148 if (result < 0) {
149 dev_err(dev, "WLP: Cannot register WSS kobject.\n");
150 goto error_kobject_register;
151 }
152 result = sysfs_create_group(&wss->kobj, &wss_attr_group);
153 if (result < 0) {
154 dev_err(dev, "WLP: Cannot register WSS attributes: %d\n",
155 result);
156 goto error_sysfs_create_group;
157 }
158 return 0;
159error_sysfs_create_group:
160
161 kobject_put(&wss->kobj); /* will free name if needed */
162 return result;
163error_kobject_register:
164 kfree(wss->kobj.name);
165 wss->kobj.name = NULL;
166 wss->kobj.ktype = NULL;
167 return result;
168}
169
170
171/**
172 * Release WSS
173 *
174 * No more references exist to this WSS. We should undo everything that was
175 * done in wlp_wss_create_activate() except removing the group. The group
176 * is not removed because an object can be unregistered before the group is
177 * created. We also undo any additional operations on the WSS after this
178 * (addition of members).
179 *
180 * If memory was allocated for the kobject's name then it will
181 * be freed by the kobject system during this time.
182 *
183 * The EDA cache is removed and reinitialized when the WSS is removed. We
184 * thus loose knowledge of members of this WSS at that time and need not do
185 * it here.
186 */
187void wlp_wss_release(struct kobject *kobj)
188{
189 struct wlp_wss *wss = container_of(kobj, struct wlp_wss, kobj);
190
191 wlp_wss_reset(wss);
192}
193
194/**
195 * Enroll into a WSS using provided neighbor as registrar
196 *
197 * First search the neighborhood information to learn which neighbor is
198 * referred to, next proceed with enrollment.
199 *
200 * &wss->mutex is held
201 */
202static
203int wlp_wss_enroll_target(struct wlp_wss *wss, struct wlp_uuid *wssid,
204 struct uwb_dev_addr *dest)
205{
206 struct wlp *wlp = container_of(wss, struct wlp, wss);
207 struct device *dev = &wlp->rc->uwb_dev.dev;
208 struct wlp_neighbor_e *neighbor;
209 int result = -ENXIO;
210 struct uwb_dev_addr *dev_addr;
211
212 mutex_lock(&wlp->nbmutex);
213 list_for_each_entry(neighbor, &wlp->neighbors, node) {
214 dev_addr = &neighbor->uwb_dev->dev_addr;
215 if (!memcmp(dest, dev_addr, sizeof(*dest))) {
216 result = wlp_enroll_neighbor(wlp, neighbor, wss, wssid);
217 break;
218 }
219 }
220 if (result == -ENXIO)
221 dev_err(dev, "WLP: Cannot find neighbor %02x:%02x. \n",
222 dest->data[1], dest->data[0]);
223 mutex_unlock(&wlp->nbmutex);
224 return result;
225}
226
227/**
228 * Enroll into a WSS previously discovered
229 *
230 * User provides WSSID of WSS, search for neighbor that has this WSS
231 * activated and attempt to enroll.
232 *
233 * &wss->mutex is held
234 */
235static
236int wlp_wss_enroll_discovered(struct wlp_wss *wss, struct wlp_uuid *wssid)
237{
238 struct wlp *wlp = container_of(wss, struct wlp, wss);
239 struct device *dev = &wlp->rc->uwb_dev.dev;
240 struct wlp_neighbor_e *neighbor;
241 struct wlp_wssid_e *wssid_e;
242 char buf[WLP_WSS_UUID_STRSIZE];
243 int result = -ENXIO;
244
245
246 mutex_lock(&wlp->nbmutex);
247 list_for_each_entry(neighbor, &wlp->neighbors, node) {
248 list_for_each_entry(wssid_e, &neighbor->wssid, node) {
249 if (!memcmp(wssid, &wssid_e->wssid, sizeof(*wssid))) {
250 result = wlp_enroll_neighbor(wlp, neighbor,
251 wss, wssid);
252 if (result == 0) /* enrollment success */
253 goto out;
254 break;
255 }
256 }
257 }
258out:
259 if (result == -ENXIO) {
260 wlp_wss_uuid_print(buf, sizeof(buf), wssid);
261 dev_err(dev, "WLP: Cannot find WSSID %s in cache. \n", buf);
262 }
263 mutex_unlock(&wlp->nbmutex);
264 return result;
265}
266
267/**
268 * Enroll into WSS with provided WSSID, registrar may be provided
269 *
270 * @wss: out WSS that will be enrolled
271 * @wssid: wssid of neighboring WSS that we want to enroll in
272 * @devaddr: registrar can be specified, will be broadcast (ff:ff) if any
273 * neighbor can be used as registrar.
274 *
275 * &wss->mutex is held
276 */
277static
278int wlp_wss_enroll(struct wlp_wss *wss, struct wlp_uuid *wssid,
279 struct uwb_dev_addr *devaddr)
280{
281 int result;
282 struct wlp *wlp = container_of(wss, struct wlp, wss);
283 struct device *dev = &wlp->rc->uwb_dev.dev;
284 char buf[WLP_WSS_UUID_STRSIZE];
285 struct uwb_dev_addr bcast = {.data = {0xff, 0xff} };
286
287 wlp_wss_uuid_print(buf, sizeof(buf), wssid);
288
289 if (wss->state != WLP_WSS_STATE_NONE) {
290 dev_err(dev, "WLP: Already enrolled in WSS %s.\n", buf);
291 result = -EEXIST;
292 goto error;
293 }
294 if (!memcmp(&bcast, devaddr, sizeof(bcast)))
295 result = wlp_wss_enroll_discovered(wss, wssid);
296 else
297 result = wlp_wss_enroll_target(wss, wssid, devaddr);
298 if (result < 0) {
299 dev_err(dev, "WLP: Unable to enroll into WSS %s, result %d \n",
300 buf, result);
301 goto error;
302 }
303 dev_dbg(dev, "Successfully enrolled into WSS %s \n", buf);
304 result = wlp_wss_sysfs_add(wss, buf);
305 if (result < 0) {
306 dev_err(dev, "WLP: Unable to set up sysfs for WSS kobject.\n");
307 wlp_wss_reset(wss);
308 }
309error:
310 return result;
311
312}
313
314/**
315 * Activate given WSS
316 *
317 * Prior to activation a WSS must be enrolled. To activate a WSS a device
318 * includes the WSS hash in the WLP IE in its beacon in each superframe.
319 * WLP 0.99 [7.2.5].
320 *
321 * The WSS tag is also computed at this time. We only support one activated
322 * WSS so we can use the hash as a tag - there will never be a conflict.
323 *
324 * We currently only support one activated WSS so only one WSS hash is
325 * included in the WLP IE.
326 */
327static
328int wlp_wss_activate(struct wlp_wss *wss)
329{
330 struct wlp *wlp = container_of(wss, struct wlp, wss);
331 struct device *dev = &wlp->rc->uwb_dev.dev;
332 struct uwb_rc *uwb_rc = wlp->rc;
333 int result;
334 struct {
335 struct wlp_ie wlp_ie;
336 u8 hash; /* only include one hash */
337 } ie_data;
338
339 BUG_ON(wss->state != WLP_WSS_STATE_ENROLLED);
340 wss->hash = wlp_wss_comp_wssid_hash(&wss->wssid);
341 wss->tag = wss->hash;
342 memset(&ie_data, 0, sizeof(ie_data));
343 ie_data.wlp_ie.hdr.element_id = UWB_IE_WLP;
344 ie_data.wlp_ie.hdr.length = sizeof(ie_data) - sizeof(struct uwb_ie_hdr);
345 wlp_ie_set_hash_length(&ie_data.wlp_ie, sizeof(ie_data.hash));
346 ie_data.hash = wss->hash;
347 result = uwb_rc_ie_add(uwb_rc, &ie_data.wlp_ie.hdr,
348 sizeof(ie_data));
349 if (result < 0) {
350 dev_err(dev, "WLP: Unable to add WLP IE to beacon. "
351 "result = %d.\n", result);
352 goto error_wlp_ie;
353 }
354 wss->state = WLP_WSS_STATE_ACTIVE;
355 result = 0;
356error_wlp_ie:
357 return result;
358}
359
360/**
361 * Enroll in and activate WSS identified by provided WSSID
362 *
363 * The neighborhood cache should contain a list of all neighbors and the
364 * WSS they have activated. Based on that cache we search which neighbor we
365 * can perform the association process with. The user also has option to
366 * specify which neighbor it prefers as registrar.
367 * Successful enrollment is followed by activation.
368 * Successful activation will create the sysfs directory containing
369 * specific information regarding this WSS.
370 */
371int wlp_wss_enroll_activate(struct wlp_wss *wss, struct wlp_uuid *wssid,
372 struct uwb_dev_addr *devaddr)
373{
374 struct wlp *wlp = container_of(wss, struct wlp, wss);
375 struct device *dev = &wlp->rc->uwb_dev.dev;
376 int result = 0;
377 char buf[WLP_WSS_UUID_STRSIZE];
378
379 mutex_lock(&wss->mutex);
380 result = wlp_wss_enroll(wss, wssid, devaddr);
381 if (result < 0) {
382 wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid);
383 dev_err(dev, "WLP: Enrollment into WSS %s failed.\n", buf);
384 goto error_enroll;
385 }
386 result = wlp_wss_activate(wss);
387 if (result < 0) {
388 dev_err(dev, "WLP: Unable to activate WSS. Undoing enrollment "
389 "result = %d \n", result);
390 /* Undo enrollment */
391 wlp_wss_reset(wss);
392 goto error_activate;
393 }
394error_activate:
395error_enroll:
396 mutex_unlock(&wss->mutex);
397 return result;
398}
399
400/**
401 * Create, enroll, and activate a new WSS
402 *
403 * @wssid: new wssid provided by user
404 * @name: WSS name requested by used.
405 * @sec_status: security status requested by user
406 *
407 * A user requested the creation of a new WSS. All operations are done
408 * locally. The new WSS will be stored locally, the hash will be included
409 * in the WLP IE, and the sysfs infrastructure for this WSS will be
410 * created.
411 */
412int wlp_wss_create_activate(struct wlp_wss *wss, struct wlp_uuid *wssid,
413 char *name, unsigned sec_status, unsigned accept)
414{
415 struct wlp *wlp = container_of(wss, struct wlp, wss);
416 struct device *dev = &wlp->rc->uwb_dev.dev;
417 int result = 0;
418 char buf[WLP_WSS_UUID_STRSIZE];
419
420 result = wlp_wss_uuid_print(buf, sizeof(buf), wssid);
421
422 if (!mutex_trylock(&wss->mutex)) {
423 dev_err(dev, "WLP: WLP association session in progress.\n");
424 return -EBUSY;
425 }
426 if (wss->state != WLP_WSS_STATE_NONE) {
427 dev_err(dev, "WLP: WSS already exists. Not creating new.\n");
428 result = -EEXIST;
429 goto out;
430 }
431 if (wss->kobj.parent == NULL) {
432 dev_err(dev, "WLP: WSS parent not ready. Is network interface "
433 "up?\n");
434 result = -ENXIO;
435 goto out;
436 }
437 if (sec_status == WLP_WSS_SECURE) {
438 dev_err(dev, "WLP: FIXME Creation of secure WSS not "
439 "supported yet.\n");
440 result = -EINVAL;
441 goto out;
442 }
443 wss->wssid = *wssid;
444 memcpy(wss->name, name, sizeof(wss->name));
445 wss->bcast = wlp_wss_sel_bcast_addr(wss);
446 wss->secure_status = sec_status;
447 wss->accept_enroll = accept;
448 /*wss->virtual_addr is initialized in call to wlp_wss_setup*/
449 /* sysfs infrastructure */
450 result = wlp_wss_sysfs_add(wss, buf);
451 if (result < 0) {
452 dev_err(dev, "Cannot set up sysfs for WSS kobject.\n");
453 wlp_wss_reset(wss);
454 goto out;
455 } else
456 result = 0;
457 wss->state = WLP_WSS_STATE_ENROLLED;
458 result = wlp_wss_activate(wss);
459 if (result < 0) {
460 dev_err(dev, "WLP: Unable to activate WSS. Undoing "
461 "enrollment\n");
462 wlp_wss_reset(wss);
463 goto out;
464 }
465 result = 0;
466out:
467 mutex_unlock(&wss->mutex);
468 return result;
469}
470
471/**
472 * Determine if neighbor has WSS activated
473 *
474 * @returns: 1 if neighbor has WSS activated, zero otherwise
475 *
476 * This can be done in two ways:
477 * - send a C1 frame, parse C2/F0 response
478 * - examine the WLP IE sent by the neighbor
479 *
480 * The WLP IE is not fully supported in hardware so we use the C1/C2 frame
481 * exchange to determine if a WSS is activated. Using the WLP IE should be
482 * faster and should be used when it becomes possible.
483 */
484int wlp_wss_is_active(struct wlp *wlp, struct wlp_wss *wss,
485 struct uwb_dev_addr *dev_addr)
486{
487 int result = 0;
488 struct device *dev = &wlp->rc->uwb_dev.dev;
489 DECLARE_COMPLETION_ONSTACK(completion);
490 struct wlp_session session;
491 struct sk_buff *skb;
492 struct wlp_frame_assoc *resp;
493 struct wlp_uuid wssid;
494
495 mutex_lock(&wlp->mutex);
496 /* Send C1 association frame */
497 result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C1);
498 if (result < 0) {
499 dev_err(dev, "Unable to send C1 frame to neighbor "
500 "%02x:%02x (%d)\n", dev_addr->data[1],
501 dev_addr->data[0], result);
502 result = 0;
503 goto out;
504 }
505 /* Create session, wait for response */
506 session.exp_message = WLP_ASSOC_C2;
507 session.cb = wlp_session_cb;
508 session.cb_priv = &completion;
509 session.neighbor_addr = *dev_addr;
510 BUG_ON(wlp->session != NULL);
511 wlp->session = &session;
512 /* Wait for C2/F0 frame */
513 result = wait_for_completion_interruptible_timeout(&completion,
514 WLP_PER_MSG_TIMEOUT * HZ);
515 if (result == 0) {
516 dev_err(dev, "Timeout while sending C1 to neighbor "
517 "%02x:%02x.\n", dev_addr->data[1],
518 dev_addr->data[0]);
519 goto out;
520 }
521 if (result < 0) {
522 dev_err(dev, "Unable to send C1 to neighbor %02x:%02x.\n",
523 dev_addr->data[1], dev_addr->data[0]);
524 result = 0;
525 goto out;
526 }
527 /* Parse message in session->data: it will be either C2 or F0 */
528 skb = session.data;
529 resp = (void *) skb->data;
530 if (resp->type == WLP_ASSOC_F0) {
531 result = wlp_parse_f0(wlp, skb);
532 if (result < 0)
533 dev_err(dev, "WLP: unable to parse incoming F0 "
534 "frame from neighbor %02x:%02x.\n",
535 dev_addr->data[1], dev_addr->data[0]);
536 result = 0;
537 goto error_resp_parse;
538 }
539 /* WLP version and message type fields have already been parsed */
540 result = wlp_get_wssid(wlp, (void *)resp + sizeof(*resp), &wssid,
541 skb->len - sizeof(*resp));
542 if (result < 0) {
543 dev_err(dev, "WLP: unable to obtain WSSID from C2 frame.\n");
544 result = 0;
545 goto error_resp_parse;
546 }
547 if (!memcmp(&wssid, &wss->wssid, sizeof(wssid)))
548 result = 1;
549 else {
550 dev_err(dev, "WLP: Received a C2 frame without matching "
551 "WSSID.\n");
552 result = 0;
553 }
554error_resp_parse:
555 kfree_skb(skb);
556out:
557 wlp->session = NULL;
558 mutex_unlock(&wlp->mutex);
559 return result;
560}
561
562/**
563 * Activate connection with neighbor by updating EDA cache
564 *
565 * @wss: local WSS to which neighbor wants to connect
566 * @dev_addr: neighbor's address
567 * @wssid: neighbor's WSSID - must be same as our WSS's WSSID
568 * @tag: neighbor's WSS tag used to identify frames transmitted by it
569 * @virt_addr: neighbor's virtual EUI-48
570 */
571static
572int wlp_wss_activate_connection(struct wlp *wlp, struct wlp_wss *wss,
573 struct uwb_dev_addr *dev_addr,
574 struct wlp_uuid *wssid, u8 *tag,
575 struct uwb_mac_addr *virt_addr)
576{
577 struct device *dev = &wlp->rc->uwb_dev.dev;
578 int result = 0;
579
580 if (!memcmp(wssid, &wss->wssid, sizeof(*wssid))) {
581 /* Update EDA cache */
582 result = wlp_eda_update_node(&wlp->eda, dev_addr, wss,
583 (void *) virt_addr->data, *tag,
584 WLP_WSS_CONNECTED);
585 if (result < 0)
586 dev_err(dev, "WLP: Unable to update EDA cache "
587 "with new connected neighbor information.\n");
588 } else {
589 dev_err(dev, "WLP: Neighbor does not have matching WSSID.\n");
590 result = -EINVAL;
591 }
592 return result;
593}
594
595/**
596 * Connect to WSS neighbor
597 *
598 * Use C3/C4 exchange to determine if neighbor has WSS activated and
599 * retrieve the WSS tag and virtual EUI-48 of the neighbor.
600 */
601static
602int wlp_wss_connect_neighbor(struct wlp *wlp, struct wlp_wss *wss,
603 struct uwb_dev_addr *dev_addr)
604{
605 int result;
606 struct device *dev = &wlp->rc->uwb_dev.dev;
607 struct wlp_uuid wssid;
608 u8 tag;
609 struct uwb_mac_addr virt_addr;
610 DECLARE_COMPLETION_ONSTACK(completion);
611 struct wlp_session session;
612 struct wlp_frame_assoc *resp;
613 struct sk_buff *skb;
614
615 mutex_lock(&wlp->mutex);
616 /* Send C3 association frame */
617 result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C3);
618 if (result < 0) {
619 dev_err(dev, "Unable to send C3 frame to neighbor "
620 "%02x:%02x (%d)\n", dev_addr->data[1],
621 dev_addr->data[0], result);
622 goto out;
623 }
624 /* Create session, wait for response */
625 session.exp_message = WLP_ASSOC_C4;
626 session.cb = wlp_session_cb;
627 session.cb_priv = &completion;
628 session.neighbor_addr = *dev_addr;
629 BUG_ON(wlp->session != NULL);
630 wlp->session = &session;
631 /* Wait for C4/F0 frame */
632 result = wait_for_completion_interruptible_timeout(&completion,
633 WLP_PER_MSG_TIMEOUT * HZ);
634 if (result == 0) {
635 dev_err(dev, "Timeout while sending C3 to neighbor "
636 "%02x:%02x.\n", dev_addr->data[1],
637 dev_addr->data[0]);
638 result = -ETIMEDOUT;
639 goto out;
640 }
641 if (result < 0) {
642 dev_err(dev, "Unable to send C3 to neighbor %02x:%02x.\n",
643 dev_addr->data[1], dev_addr->data[0]);
644 goto out;
645 }
646 /* Parse message in session->data: it will be either C4 or F0 */
647 skb = session.data;
648 resp = (void *) skb->data;
649 if (resp->type == WLP_ASSOC_F0) {
650 result = wlp_parse_f0(wlp, skb);
651 if (result < 0)
652 dev_err(dev, "WLP: unable to parse incoming F0 "
653 "frame from neighbor %02x:%02x.\n",
654 dev_addr->data[1], dev_addr->data[0]);
655 result = -EINVAL;
656 goto error_resp_parse;
657 }
658 result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr);
659 if (result < 0) {
660 dev_err(dev, "WLP: Unable to parse C4 frame from neighbor.\n");
661 goto error_resp_parse;
662 }
663 result = wlp_wss_activate_connection(wlp, wss, dev_addr, &wssid, &tag,
664 &virt_addr);
665 if (result < 0) {
666 dev_err(dev, "WLP: Unable to activate connection to "
667 "neighbor %02x:%02x.\n", dev_addr->data[1],
668 dev_addr->data[0]);
669 goto error_resp_parse;
670 }
671error_resp_parse:
672 kfree_skb(skb);
673out:
674 /* Record that we unsuccessfully tried to connect to this neighbor */
675 if (result < 0)
676 wlp_eda_update_node_state(&wlp->eda, dev_addr,
677 WLP_WSS_CONNECT_FAILED);
678 wlp->session = NULL;
679 mutex_unlock(&wlp->mutex);
680 return result;
681}
682
683/**
684 * Connect to neighbor with common WSS, send pending frame
685 *
686 * This function is scheduled when a frame is destined to a neighbor with
687 * which we do not have a connection. A copy of the EDA cache entry is
688 * provided - not the actual cache entry (because it is protected by a
689 * spinlock).
690 *
691 * First determine if neighbor has the same WSS activated, connect if it
692 * does. The C3/C4 exchange is dual purpose to determine if neighbor has
693 * WSS activated and proceed with the connection.
694 *
695 * The frame that triggered the connection setup is sent after connection
696 * setup.
697 *
698 * network queue is stopped - we need to restart when done
699 *
700 */
701static
702void wlp_wss_connect_send(struct work_struct *ws)
703{
704 struct wlp_assoc_conn_ctx *conn_ctx = container_of(ws,
705 struct wlp_assoc_conn_ctx,
706 ws);
707 struct wlp *wlp = conn_ctx->wlp;
708 struct sk_buff *skb = conn_ctx->skb;
709 struct wlp_eda_node *eda_entry = &conn_ctx->eda_entry;
710 struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr;
711 struct wlp_wss *wss = &wlp->wss;
712 int result;
713 struct device *dev = &wlp->rc->uwb_dev.dev;
714
715 mutex_lock(&wss->mutex);
716 if (wss->state < WLP_WSS_STATE_ACTIVE) {
717 if (printk_ratelimit())
718 dev_err(dev, "WLP: Attempting to connect with "
719 "WSS that is not active or connected.\n");
720 dev_kfree_skb(skb);
721 goto out;
722 }
723 /* Establish connection - send C3 rcv C4 */
724 result = wlp_wss_connect_neighbor(wlp, wss, dev_addr);
725 if (result < 0) {
726 if (printk_ratelimit())
727 dev_err(dev, "WLP: Unable to establish connection "
728 "with neighbor %02x:%02x.\n",
729 dev_addr->data[1], dev_addr->data[0]);
730 dev_kfree_skb(skb);
731 goto out;
732 }
733 /* EDA entry changed, update the local copy being used */
734 result = wlp_copy_eda_node(&wlp->eda, dev_addr, eda_entry);
735 if (result < 0) {
736 if (printk_ratelimit())
737 dev_err(dev, "WLP: Cannot find EDA entry for "
738 "neighbor %02x:%02x \n",
739 dev_addr->data[1], dev_addr->data[0]);
740 }
741 result = wlp_wss_prep_hdr(wlp, eda_entry, skb);
742 if (result < 0) {
743 if (printk_ratelimit())
744 dev_err(dev, "WLP: Unable to prepare frame header for "
745 "transmission (neighbor %02x:%02x). \n",
746 dev_addr->data[1], dev_addr->data[0]);
747 dev_kfree_skb(skb);
748 goto out;
749 }
750 BUG_ON(wlp->xmit_frame == NULL);
751 result = wlp->xmit_frame(wlp, skb, dev_addr);
752 if (result < 0) {
753 if (printk_ratelimit())
754 dev_err(dev, "WLP: Unable to transmit frame: %d\n",
755 result);
756 if (result == -ENXIO)
757 dev_err(dev, "WLP: Is network interface up? \n");
758 /* We could try again ... */
759 dev_kfree_skb(skb);/*we need to free if tx fails */
760 }
761out:
762 kfree(conn_ctx);
763 BUG_ON(wlp->start_queue == NULL);
764 wlp->start_queue(wlp);
765 mutex_unlock(&wss->mutex);
766}
767
768/**
769 * Add WLP header to outgoing skb
770 *
771 * @eda_entry: pointer to neighbor's entry in the EDA cache
772 * @_skb: skb containing data destined to the neighbor
773 */
774int wlp_wss_prep_hdr(struct wlp *wlp, struct wlp_eda_node *eda_entry,
775 void *_skb)
776{
777 struct device *dev = &wlp->rc->uwb_dev.dev;
778 int result = 0;
779 unsigned char *eth_addr = eda_entry->eth_addr;
780 struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr;
781 struct sk_buff *skb = _skb;
782 struct wlp_frame_std_abbrv_hdr *std_hdr;
783
784 if (eda_entry->state == WLP_WSS_CONNECTED) {
785 /* Add WLP header */
786 BUG_ON(skb_headroom(skb) < sizeof(*std_hdr));
787 std_hdr = (void *) __skb_push(skb, sizeof(*std_hdr));
788 std_hdr->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
789 std_hdr->hdr.type = WLP_FRAME_STANDARD;
790 std_hdr->tag = eda_entry->wss->tag;
791 } else {
792 if (printk_ratelimit())
793 dev_err(dev, "WLP: Destination neighbor (Ethernet: "
794 "%pM, Dev: %02x:%02x) is not connected.\n",
795 eth_addr, dev_addr->data[1], dev_addr->data[0]);
796 result = -EINVAL;
797 }
798 return result;
799}
800
801
802/**
803 * Prepare skb for neighbor: connect if not already and prep WLP header
804 *
805 * This function is called in interrupt context, but it needs to sleep. We
806 * temporarily stop the net queue to establish the WLP connection.
807 * Setup of the WLP connection and restart of queue is scheduled
808 * on the default work queue.
809 *
810 * run with eda->lock held (spinlock)
811 */
812int wlp_wss_connect_prep(struct wlp *wlp, struct wlp_eda_node *eda_entry,
813 void *_skb)
814{
815 int result = 0;
816 struct device *dev = &wlp->rc->uwb_dev.dev;
817 struct sk_buff *skb = _skb;
818 struct wlp_assoc_conn_ctx *conn_ctx;
819
820 if (eda_entry->state == WLP_WSS_UNCONNECTED) {
821 /* We don't want any more packets while we set up connection */
822 BUG_ON(wlp->stop_queue == NULL);
823 wlp->stop_queue(wlp);
824 conn_ctx = kmalloc(sizeof(*conn_ctx), GFP_ATOMIC);
825 if (conn_ctx == NULL) {
826 if (printk_ratelimit())
827 dev_err(dev, "WLP: Unable to allocate memory "
828 "for connection handling.\n");
829 result = -ENOMEM;
830 goto out;
831 }
832 conn_ctx->wlp = wlp;
833 conn_ctx->skb = skb;
834 conn_ctx->eda_entry = *eda_entry;
835 INIT_WORK(&conn_ctx->ws, wlp_wss_connect_send);
836 schedule_work(&conn_ctx->ws);
837 result = 1;
838 } else if (eda_entry->state == WLP_WSS_CONNECT_FAILED) {
839 /* Previous connection attempts failed, don't retry - see
840 * conditions for connection in WLP 0.99 [7.6.2] */
841 if (printk_ratelimit())
842 dev_err(dev, "Could not connect to neighbor "
843 "previously. Not retrying. \n");
844 result = -ENONET;
845 goto out;
846 } else /* eda_entry->state == WLP_WSS_CONNECTED */
847 result = wlp_wss_prep_hdr(wlp, eda_entry, skb);
848out:
849 return result;
850}
851
852/**
853 * Emulate broadcast: copy skb, send copy to neighbor (connect if not already)
854 *
855 * We need to copy skbs in the case where we emulate broadcast through
856 * unicast. We copy instead of clone because we are modifying the data of
857 * the frame after copying ... clones share data so we cannot emulate
858 * broadcast using clones.
859 *
860 * run with eda->lock held (spinlock)
861 */
862int wlp_wss_send_copy(struct wlp *wlp, struct wlp_eda_node *eda_entry,
863 void *_skb)
864{
865 int result = -ENOMEM;
866 struct device *dev = &wlp->rc->uwb_dev.dev;
867 struct sk_buff *skb = _skb;
868 struct sk_buff *copy;
869 struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr;
870
871 copy = skb_copy(skb, GFP_ATOMIC);
872 if (copy == NULL) {
873 if (printk_ratelimit())
874 dev_err(dev, "WLP: Unable to copy skb for "
875 "transmission.\n");
876 goto out;
877 }
878 result = wlp_wss_connect_prep(wlp, eda_entry, copy);
879 if (result < 0) {
880 if (printk_ratelimit())
881 dev_err(dev, "WLP: Unable to connect/send skb "
882 "to neighbor.\n");
883 dev_kfree_skb_irq(copy);
884 goto out;
885 } else if (result == 1)
886 /* Frame will be transmitted separately */
887 goto out;
888 BUG_ON(wlp->xmit_frame == NULL);
889 result = wlp->xmit_frame(wlp, copy, dev_addr);
890 if (result < 0) {
891 if (printk_ratelimit())
892 dev_err(dev, "WLP: Unable to transmit frame: %d\n",
893 result);
894 if ((result == -ENXIO) && printk_ratelimit())
895 dev_err(dev, "WLP: Is network interface up? \n");
896 /* We could try again ... */
897 dev_kfree_skb_irq(copy);/*we need to free if tx fails */
898 }
899out:
900 return result;
901}
902
903
904/**
905 * Setup WSS
906 *
907 * Should be called by network driver after the interface has been given a
908 * MAC address.
909 */
910int wlp_wss_setup(struct net_device *net_dev, struct wlp_wss *wss)
911{
912 struct wlp *wlp = container_of(wss, struct wlp, wss);
913 struct device *dev = &wlp->rc->uwb_dev.dev;
914 int result = 0;
915
916 mutex_lock(&wss->mutex);
917 wss->kobj.parent = &net_dev->dev.kobj;
918 if (!is_valid_ether_addr(net_dev->dev_addr)) {
919 dev_err(dev, "WLP: Invalid MAC address. Cannot use for"
920 "virtual.\n");
921 result = -EINVAL;
922 goto out;
923 }
924 memcpy(wss->virtual_addr.data, net_dev->dev_addr,
925 sizeof(wss->virtual_addr.data));
926out:
927 mutex_unlock(&wss->mutex);
928 return result;
929}
930EXPORT_SYMBOL_GPL(wlp_wss_setup);
931
932/**
933 * Remove WSS
934 *
935 * Called by client that configured WSS through wlp_wss_setup(). This
936 * function is called when client no longer needs WSS, eg. client shuts
937 * down.
938 *
939 * We remove the WLP IE from the beacon before initiating local cleanup.
940 */
941void wlp_wss_remove(struct wlp_wss *wss)
942{
943 struct wlp *wlp = container_of(wss, struct wlp, wss);
944
945 mutex_lock(&wss->mutex);
946 if (wss->state == WLP_WSS_STATE_ACTIVE)
947 uwb_rc_ie_rm(wlp->rc, UWB_IE_WLP);
948 if (wss->state != WLP_WSS_STATE_NONE) {
949 sysfs_remove_group(&wss->kobj, &wss_attr_group);
950 kobject_put(&wss->kobj);
951 }
952 wss->kobj.parent = NULL;
953 memset(&wss->virtual_addr, 0, sizeof(wss->virtual_addr));
954 /* Cleanup EDA cache */
955 wlp_eda_release(&wlp->eda);
956 wlp_eda_init(&wlp->eda);
957 mutex_unlock(&wss->mutex);
958}
959EXPORT_SYMBOL_GPL(wlp_wss_remove);
diff --git a/include/linux/wlp.h b/include/linux/wlp.h
deleted file mode 100644
index c76fe2392506..000000000000
--- a/include/linux/wlp.h
+++ /dev/null
@@ -1,736 +0,0 @@
1/*
2 * WiMedia Logical Link Control Protocol (WLP)
3 *
4 * Copyright (C) 2005-2006 Intel Corporation
5 * Reinette Chatre <reinette.chatre@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 *
22 * FIXME: docs
23 *
24 * - Does not (yet) include support for WLP control frames
25 * WLP Draft 0.99 [6.5].
26 *
27 * A visual representation of the data structures.
28 *
29 * wssidB wssidB
30 * ^ ^
31 * | |
32 * wssidA wssidA
33 * wlp interface { ^ ^
34 * ... | |
35 * ... ... wssid wssid ...
36 * wlp --- ... | |
37 * }; neighbors --> neighbA --> neighbB
38 * ...
39 * wss
40 * ...
41 * eda cache --> neighborA --> neighborB --> neighborC ...
42 */
43
44#ifndef __LINUX__WLP_H_
45#define __LINUX__WLP_H_
46
47#include <linux/netdevice.h>
48#include <linux/skbuff.h>
49#include <linux/list.h>
50#include <linux/uwb.h>
51
52/**
53 * WLP Protocol ID
54 * WLP Draft 0.99 [6.2]
55 *
56 * The MUX header for all WLP frames
57 */
58#define WLP_PROTOCOL_ID 0x0100
59
60/**
61 * WLP Version
62 * WLP version placed in the association frames (WLP 0.99 [6.6])
63 */
64#define WLP_VERSION 0x10
65
66/**
67 * Bytes needed to print UUID as string
68 */
69#define WLP_WSS_UUID_STRSIZE 48
70
71/**
72 * Bytes needed to print nonce as string
73 */
74#define WLP_WSS_NONCE_STRSIZE 48
75
76
77/**
78 * Size used for WLP name size
79 *
80 * The WSS name is set to 65 bytes, 1 byte larger than the maximum
81 * allowed by the WLP spec. This is to have a null terminated string
82 * for display to the user. A maximum of 64 bytes will still be used
83 * when placing the WSS name field in association frames.
84 */
85#define WLP_WSS_NAME_SIZE 65
86
87/**
88 * Number of bytes added by WLP to data frame
89 *
90 * A data frame transmitted from a host will be placed in a Standard or
91 * Abbreviated WLP frame. These have an extra 4 bytes of header (struct
92 * wlp_frame_std_abbrv_hdr).
93 * When the stack sends this data frame for transmission it needs to ensure
94 * there is enough headroom for this header.
95 */
96#define WLP_DATA_HLEN 4
97
98/**
99 * State of device regarding WLP Service Set
100 *
101 * WLP_WSS_STATE_NONE: the host does not participate in any WSS
102 * WLP_WSS_STATE_PART_ENROLLED: used as part of the enrollment sequence
103 * ("Partial Enroll"). This state is used to
104 * indicate the first part of enrollment that is
105 * unsecure. If the WSS is unsecure then the
106 * state will promptly go to WLP_WSS_STATE_ENROLLED,
107 * if the WSS is not secure then the enrollment
108 * procedure is a few more steps before we are
109 * enrolled.
110 * WLP_WSS_STATE_ENROLLED: the host is enrolled in a WSS
111 * WLP_WSS_STATE_ACTIVE: WSS is activated
112 * WLP_WSS_STATE_CONNECTED: host is connected to neighbor in WSS
113 *
114 */
115enum wlp_wss_state {
116 WLP_WSS_STATE_NONE = 0,
117 WLP_WSS_STATE_PART_ENROLLED,
118 WLP_WSS_STATE_ENROLLED,
119 WLP_WSS_STATE_ACTIVE,
120 WLP_WSS_STATE_CONNECTED,
121};
122
123/**
124 * WSS Secure status
125 * WLP 0.99 Table 6
126 *
127 * Set to one if the WSS is secure, zero if it is not secure
128 */
129enum wlp_wss_sec_status {
130 WLP_WSS_UNSECURE = 0,
131 WLP_WSS_SECURE,
132};
133
134/**
135 * WLP frame type
136 * WLP Draft 0.99 [6.2 Table 1]
137 */
138enum wlp_frame_type {
139 WLP_FRAME_STANDARD = 0,
140 WLP_FRAME_ABBREVIATED,
141 WLP_FRAME_CONTROL,
142 WLP_FRAME_ASSOCIATION,
143};
144
145/**
146 * WLP Association Message Type
147 * WLP Draft 0.99 [6.6.1.2 Table 8]
148 */
149enum wlp_assoc_type {
150 WLP_ASSOC_D1 = 2,
151 WLP_ASSOC_D2 = 3,
152 WLP_ASSOC_M1 = 4,
153 WLP_ASSOC_M2 = 5,
154 WLP_ASSOC_M3 = 7,
155 WLP_ASSOC_M4 = 8,
156 WLP_ASSOC_M5 = 9,
157 WLP_ASSOC_M6 = 10,
158 WLP_ASSOC_M7 = 11,
159 WLP_ASSOC_M8 = 12,
160 WLP_ASSOC_F0 = 14,
161 WLP_ASSOC_E1 = 32,
162 WLP_ASSOC_E2 = 33,
163 WLP_ASSOC_C1 = 34,
164 WLP_ASSOC_C2 = 35,
165 WLP_ASSOC_C3 = 36,
166 WLP_ASSOC_C4 = 37,
167};
168
169/**
170 * WLP Attribute Type
171 * WLP Draft 0.99 [6.6.1 Table 6]
172 */
173enum wlp_attr_type {
174 WLP_ATTR_AUTH = 0x1005, /* Authenticator */
175 WLP_ATTR_DEV_NAME = 0x1011, /* Device Name */
176 WLP_ATTR_DEV_PWD_ID = 0x1012, /* Device Password ID */
177 WLP_ATTR_E_HASH1 = 0x1014, /* E-Hash1 */
178 WLP_ATTR_E_HASH2 = 0x1015, /* E-Hash2 */
179 WLP_ATTR_E_SNONCE1 = 0x1016, /* E-SNonce1 */
180 WLP_ATTR_E_SNONCE2 = 0x1017, /* E-SNonce2 */
181 WLP_ATTR_ENCR_SET = 0x1018, /* Encrypted Settings */
182 WLP_ATTR_ENRL_NONCE = 0x101A, /* Enrollee Nonce */
183 WLP_ATTR_KEYWRAP_AUTH = 0x101E, /* Key Wrap Authenticator */
184 WLP_ATTR_MANUF = 0x1021, /* Manufacturer */
185 WLP_ATTR_MSG_TYPE = 0x1022, /* Message Type */
186 WLP_ATTR_MODEL_NAME = 0x1023, /* Model Name */
187 WLP_ATTR_MODEL_NR = 0x1024, /* Model Number */
188 WLP_ATTR_PUB_KEY = 0x1032, /* Public Key */
189 WLP_ATTR_REG_NONCE = 0x1039, /* Registrar Nonce */
190 WLP_ATTR_R_HASH1 = 0x103D, /* R-Hash1 */
191 WLP_ATTR_R_HASH2 = 0x103E, /* R-Hash2 */
192 WLP_ATTR_R_SNONCE1 = 0x103F, /* R-SNonce1 */
193 WLP_ATTR_R_SNONCE2 = 0x1040, /* R-SNonce2 */
194 WLP_ATTR_SERIAL = 0x1042, /* Serial number */
195 WLP_ATTR_UUID_E = 0x1047, /* UUID-E */
196 WLP_ATTR_UUID_R = 0x1048, /* UUID-R */
197 WLP_ATTR_PRI_DEV_TYPE = 0x1054, /* Primary Device Type */
198 WLP_ATTR_SEC_DEV_TYPE = 0x1055, /* Secondary Device Type */
199 WLP_ATTR_PORT_DEV = 0x1056, /* Portable Device */
200 WLP_ATTR_APP_EXT = 0x1058, /* Application Extension */
201 WLP_ATTR_WLP_VER = 0x2000, /* WLP Version */
202 WLP_ATTR_WSSID = 0x2001, /* WSSID */
203 WLP_ATTR_WSS_NAME = 0x2002, /* WSS Name */
204 WLP_ATTR_WSS_SEC_STAT = 0x2003, /* WSS Secure Status */
205 WLP_ATTR_WSS_BCAST = 0x2004, /* WSS Broadcast Address */
206 WLP_ATTR_WSS_M_KEY = 0x2005, /* WSS Master Key */
207 WLP_ATTR_ACC_ENRL = 0x2006, /* Accepting Enrollment */
208 WLP_ATTR_WSS_INFO = 0x2007, /* WSS Information */
209 WLP_ATTR_WSS_SEL_MTHD = 0x2008, /* WSS Selection Method */
210 WLP_ATTR_ASSC_MTHD_LIST = 0x2009, /* Association Methods List */
211 WLP_ATTR_SEL_ASSC_MTHD = 0x200A, /* Selected Association Method */
212 WLP_ATTR_ENRL_HASH_COMM = 0x200B, /* Enrollee Hash Commitment */
213 WLP_ATTR_WSS_TAG = 0x200C, /* WSS Tag */
214 WLP_ATTR_WSS_VIRT = 0x200D, /* WSS Virtual EUI-48 */
215 WLP_ATTR_WLP_ASSC_ERR = 0x200E, /* WLP Association Error */
216 WLP_ATTR_VNDR_EXT = 0x200F, /* Vendor Extension */
217};
218
219/**
220 * WLP Category ID of primary/secondary device
221 * WLP Draft 0.99 [6.6.1.8 Table 12]
222 */
223enum wlp_dev_category_id {
224 WLP_DEV_CAT_COMPUTER = 1,
225 WLP_DEV_CAT_INPUT,
226 WLP_DEV_CAT_PRINT_SCAN_FAX_COPIER,
227 WLP_DEV_CAT_CAMERA,
228 WLP_DEV_CAT_STORAGE,
229 WLP_DEV_CAT_INFRASTRUCTURE,
230 WLP_DEV_CAT_DISPLAY,
231 WLP_DEV_CAT_MULTIM,
232 WLP_DEV_CAT_GAMING,
233 WLP_DEV_CAT_TELEPHONE,
234 WLP_DEV_CAT_OTHER = 65535,
235};
236
237/**
238 * WLP WSS selection method
239 * WLP Draft 0.99 [6.6.1.6 Table 10]
240 */
241enum wlp_wss_sel_mthd {
242 WLP_WSS_ENRL_SELECT = 1, /* Enrollee selects */
243 WLP_WSS_REG_SELECT, /* Registrar selects */
244};
245
246/**
247 * WLP association error values
248 * WLP Draft 0.99 [6.6.1.5 Table 9]
249 */
250enum wlp_assc_error {
251 WLP_ASSOC_ERROR_NONE,
252 WLP_ASSOC_ERROR_AUTH, /* Authenticator Failure */
253 WLP_ASSOC_ERROR_ROGUE, /* Rogue activity suspected */
254 WLP_ASSOC_ERROR_BUSY, /* Device busy */
255 WLP_ASSOC_ERROR_LOCK, /* Setup Locked */
256 WLP_ASSOC_ERROR_NOT_READY, /* Registrar not ready */
257 WLP_ASSOC_ERROR_INV, /* Invalid WSS selection */
258 WLP_ASSOC_ERROR_MSG_TIME, /* Message timeout */
259 WLP_ASSOC_ERROR_ENR_TIME, /* Enrollment session timeout */
260 WLP_ASSOC_ERROR_PW, /* Device password invalid */
261 WLP_ASSOC_ERROR_VER, /* Unsupported version */
262 WLP_ASSOC_ERROR_INT, /* Internal error */
263 WLP_ASSOC_ERROR_UNDEF, /* Undefined error */
264 WLP_ASSOC_ERROR_NUM, /* Numeric comparison failure */
265 WLP_ASSOC_ERROR_WAIT, /* Waiting for user input */
266};
267
268/**
269 * WLP Parameters
270 * WLP 0.99 [7.7]
271 */
272enum wlp_parameters {
273 WLP_PER_MSG_TIMEOUT = 15, /* Seconds to wait for response to
274 association message. */
275};
276
277/**
278 * WLP IE
279 *
280 * The WLP IE should be included in beacons by all devices.
281 *
282 * The driver can set only a few of the fields in this information element,
283 * most fields are managed by the device self. When the driver needs to set
284 * a field it will only provide values for the fields of interest, the rest
285 * will be filled with zeroes. The fields of interest are:
286 *
287 * Element ID
288 * Length
289 * Capabilities (only to include WSSID Hash list length)
290 * WSSID Hash List fields
291 *
292 * WLP 0.99 [6.7]
293 *
294 * Only the fields that will be used are detailed in this structure, rest
295 * are not detailed or marked as "notused".
296 */
297struct wlp_ie {
298 struct uwb_ie_hdr hdr;
299 __le16 capabilities;
300 __le16 cycle_param;
301 __le16 acw_anchor_addr;
302 u8 wssid_hash_list[];
303} __packed;
304
305static inline int wlp_ie_hash_length(struct wlp_ie *ie)
306{
307 return (le16_to_cpu(ie->capabilities) >> 12) & 0xf;
308}
309
310static inline void wlp_ie_set_hash_length(struct wlp_ie *ie, int hash_length)
311{
312 u16 caps = le16_to_cpu(ie->capabilities);
313 caps = (caps & ~(0xf << 12)) | (hash_length << 12);
314 ie->capabilities = cpu_to_le16(caps);
315}
316
317/**
318 * WLP nonce
319 * WLP Draft 0.99 [6.6.1 Table 6]
320 *
321 * A 128-bit random number often used (E-SNonce1, E-SNonce2, Enrollee
322 * Nonce, Registrar Nonce, R-SNonce1, R-SNonce2). It is passed to HW so
323 * it is packed.
324 */
325struct wlp_nonce {
326 u8 data[16];
327} __packed;
328
329/**
330 * WLP UUID
331 * WLP Draft 0.99 [6.6.1 Table 6]
332 *
333 * Universally Unique Identifier (UUID) encoded as an octet string in the
334 * order the octets are shown in string representation in RFC4122. A UUID
335 * is often used (UUID-E, UUID-R, WSSID). It is passed to HW so it is packed.
336 */
337struct wlp_uuid {
338 u8 data[16];
339} __packed;
340
341
342/**
343 * Primary and secondary device type attributes
344 * WLP Draft 0.99 [6.6.1.8]
345 */
346struct wlp_dev_type {
347 enum wlp_dev_category_id category:16;
348 u8 OUI[3];
349 u8 OUIsubdiv;
350 __le16 subID;
351} __packed;
352
353/**
354 * WLP frame header
355 * WLP Draft 0.99 [6.2]
356 */
357struct wlp_frame_hdr {
358 __le16 mux_hdr; /* WLP_PROTOCOL_ID */
359 enum wlp_frame_type type:8;
360} __packed;
361
362/**
363 * WLP attribute field header
364 * WLP Draft 0.99 [6.6.1]
365 *
366 * Header of each attribute found in an association frame
367 */
368struct wlp_attr_hdr {
369 __le16 type;
370 __le16 length;
371} __packed;
372
373/**
374 * Device information commonly used together
375 *
376 * Each of these device information elements has a specified range in which it
377 * should fit (WLP 0.99 [Table 6]). This range provided in the spec does not
378 * include the termination null '\0' character (when used in the
379 * association protocol the attribute fields are accompanied
380 * with a "length" field so the full range from the spec can be used for
381 * the value). We thus allocate an extra byte to be able to store a string
382 * of max length with a terminating '\0'.
383 */
384struct wlp_device_info {
385 char name[33];
386 char model_name[33];
387 char manufacturer[65];
388 char model_nr[33];
389 char serial[33];
390 struct wlp_dev_type prim_dev_type;
391};
392
393/**
394 * Macros for the WLP attributes
395 *
396 * There are quite a few attributes (total is 43). The attribute layout can be
397 * in one of three categories: one value, an array, an enum forced to 8 bits.
398 * These macros help with their definitions.
399 */
400#define wlp_attr(type, name) \
401struct wlp_attr_##name { \
402 struct wlp_attr_hdr hdr; \
403 type name; \
404} __packed;
405
406#define wlp_attr_array(type, name) \
407struct wlp_attr_##name { \
408 struct wlp_attr_hdr hdr; \
409 type name[]; \
410} __packed;
411
412/**
413 * WLP association attribute fields
414 * WLP Draft 0.99 [6.6.1 Table 6]
415 *
416 * Attributes appear in same order as the Table in the spec
417 * FIXME Does not define all attributes yet
418 */
419
420/* Device name: Friendly name of sending device */
421wlp_attr_array(u8, dev_name)
422
423/* Enrollee Nonce: Random number generated by enrollee for an enrollment
424 * session */
425wlp_attr(struct wlp_nonce, enonce)
426
427/* Manufacturer name: Name of manufacturer of the sending device */
428wlp_attr_array(u8, manufacturer)
429
430/* WLP Message Type */
431wlp_attr(u8, msg_type)
432
433/* WLP Model name: Model name of sending device */
434wlp_attr_array(u8, model_name)
435
436/* WLP Model number: Model number of sending device */
437wlp_attr_array(u8, model_nr)
438
439/* Registrar Nonce: Random number generated by registrar for an enrollment
440 * session */
441wlp_attr(struct wlp_nonce, rnonce)
442
443/* Serial number of device */
444wlp_attr_array(u8, serial)
445
446/* UUID of enrollee */
447wlp_attr(struct wlp_uuid, uuid_e)
448
449/* UUID of registrar */
450wlp_attr(struct wlp_uuid, uuid_r)
451
452/* WLP Primary device type */
453wlp_attr(struct wlp_dev_type, prim_dev_type)
454
455/* WLP Secondary device type */
456wlp_attr(struct wlp_dev_type, sec_dev_type)
457
458/* WLP protocol version */
459wlp_attr(u8, version)
460
461/* WLP service set identifier */
462wlp_attr(struct wlp_uuid, wssid)
463
464/* WLP WSS name */
465wlp_attr_array(u8, wss_name)
466
467/* WLP WSS Secure Status */
468wlp_attr(u8, wss_sec_status)
469
470/* WSS Broadcast Address */
471wlp_attr(struct uwb_mac_addr, wss_bcast)
472
473/* WLP Accepting Enrollment */
474wlp_attr(u8, accept_enrl)
475
476/**
477 * WSS information attributes
478 * WLP Draft 0.99 [6.6.3 Table 15]
479 */
480struct wlp_wss_info {
481 struct wlp_attr_wssid wssid;
482 struct wlp_attr_wss_name name;
483 struct wlp_attr_accept_enrl accept;
484 struct wlp_attr_wss_sec_status sec_stat;
485 struct wlp_attr_wss_bcast bcast;
486} __packed;
487
488/* WLP WSS Information */
489wlp_attr_array(struct wlp_wss_info, wss_info)
490
491/* WLP WSS Selection method */
492wlp_attr(u8, wss_sel_mthd)
493
494/* WLP WSS tag */
495wlp_attr(u8, wss_tag)
496
497/* WSS Virtual Address */
498wlp_attr(struct uwb_mac_addr, wss_virt)
499
500/* WLP association error */
501wlp_attr(u8, wlp_assc_err)
502
503/**
504 * WLP standard and abbreviated frames
505 *
506 * WLP Draft 0.99 [6.3] and [6.4]
507 *
508 * The difference between the WLP standard frame and the WLP
509 * abbreviated frame is that the standard frame includes the src
510 * and dest addresses from the Ethernet header, the abbreviated frame does
511 * not.
512 * The src/dest (as well as the type/length and client data) are already
513 * defined as part of the Ethernet header, we do not do this here.
514 * From this perspective the standard and abbreviated frames appear the
515 * same - they will be treated differently though.
516 *
517 * The size of this header is also captured in WLP_DATA_HLEN to enable
518 * interfaces to prepare their headroom.
519 */
520struct wlp_frame_std_abbrv_hdr {
521 struct wlp_frame_hdr hdr;
522 u8 tag;
523} __packed;
524
525/**
526 * WLP association frames
527 *
528 * WLP Draft 0.99 [6.6]
529 */
530struct wlp_frame_assoc {
531 struct wlp_frame_hdr hdr;
532 enum wlp_assoc_type type:8;
533 struct wlp_attr_version version;
534 struct wlp_attr_msg_type msg_type;
535 u8 attr[];
536} __packed;
537
538/* Ethernet to dev address mapping */
539struct wlp_eda {
540 spinlock_t lock;
541 struct list_head cache; /* Eth<->Dev Addr cache */
542};
543
544/**
545 * WSS information temporary storage
546 *
547 * This information is only stored temporarily during discovery. It should
548 * not be stored unless the device is enrolled in the advertised WSS. This
549 * is done mainly because we follow the letter of the spec in this regard.
550 * See WLP 0.99 [7.2.3].
551 * When the device does become enrolled in a WSS the WSS information will
552 * be stored as part of the more comprehensive struct wlp_wss.
553 */
554struct wlp_wss_tmp_info {
555 char name[WLP_WSS_NAME_SIZE];
556 u8 accept_enroll;
557 u8 sec_status;
558 struct uwb_mac_addr bcast;
559};
560
561struct wlp_wssid_e {
562 struct list_head node;
563 struct wlp_uuid wssid;
564 struct wlp_wss_tmp_info *info;
565};
566
567/**
568 * A cache entry of WLP neighborhood
569 *
570 * @node: head of list is wlp->neighbors
571 * @wssid: list of wssids of this neighbor, element is wlp_wssid_e
572 * @info: temporary storage for information learned during discovery. This
573 * storage is used together with the wssid_e temporary storage
574 * during discovery.
575 */
576struct wlp_neighbor_e {
577 struct list_head node;
578 struct wlp_uuid uuid;
579 struct uwb_dev *uwb_dev;
580 struct list_head wssid; /* Elements are wlp_wssid_e */
581 struct wlp_device_info *info;
582};
583
584struct wlp;
585/**
586 * Information for an association session in progress.
587 *
588 * @exp_message: The type of the expected message. Both this message and a
589 * F0 message (which can be sent in response to any
590 * association frame) will be accepted as a valid message for
591 * this session.
592 * @cb: The function that will be called upon receipt of this
593 * message.
594 * @cb_priv: Private data of callback
595 * @data: Data used in association process (always a sk_buff?)
596 * @neighbor: Address of neighbor with which association session is in
597 * progress.
598 */
599struct wlp_session {
600 enum wlp_assoc_type exp_message;
601 void (*cb)(struct wlp *);
602 void *cb_priv;
603 void *data;
604 struct uwb_dev_addr neighbor_addr;
605};
606
607/**
608 * WLP Service Set
609 *
610 * @mutex: used to protect entire WSS structure.
611 *
612 * @name: The WSS name is set to 65 bytes, 1 byte larger than the maximum
613 * allowed by the WLP spec. This is to have a null terminated string
614 * for display to the user. A maximum of 64 bytes will still be used
615 * when placing the WSS name field in association frames.
616 *
617 * @accept_enroll: Accepting enrollment: Set to one if registrar is
618 * accepting enrollment in WSS, or zero otherwise.
619 *
620 * Global and local information for each WSS in which we are enrolled.
621 * WLP 0.99 Section 7.2.1 and Section 7.2.2
622 */
623struct wlp_wss {
624 struct mutex mutex;
625 struct kobject kobj;
626 /* Global properties. */
627 struct wlp_uuid wssid;
628 u8 hash;
629 char name[WLP_WSS_NAME_SIZE];
630 struct uwb_mac_addr bcast;
631 u8 secure_status:1;
632 u8 master_key[16];
633 /* Local properties. */
634 u8 tag;
635 struct uwb_mac_addr virtual_addr;
636 /* Extra */
637 u8 accept_enroll:1;
638 enum wlp_wss_state state;
639};
640
641/**
642 * WLP main structure
643 * @mutex: protect changes to WLP structure. We only allow changes to the
644 * uuid, so currently this mutex only protects this field.
645 */
646struct wlp {
647 struct mutex mutex;
648 struct uwb_rc *rc; /* UWB radio controller */
649 struct net_device *ndev;
650 struct uwb_pal pal;
651 struct wlp_eda eda;
652 struct wlp_uuid uuid;
653 struct wlp_session *session;
654 struct wlp_wss wss;
655 struct mutex nbmutex; /* Neighbor mutex protects neighbors list */
656 struct list_head neighbors; /* Elements are wlp_neighbor_e */
657 struct uwb_notifs_handler uwb_notifs_handler;
658 struct wlp_device_info *dev_info;
659 void (*fill_device_info)(struct wlp *wlp, struct wlp_device_info *info);
660 int (*xmit_frame)(struct wlp *, struct sk_buff *,
661 struct uwb_dev_addr *);
662 void (*stop_queue)(struct wlp *);
663 void (*start_queue)(struct wlp *);
664};
665
666/* sysfs */
667
668
669struct wlp_wss_attribute {
670 struct attribute attr;
671 ssize_t (*show)(struct wlp_wss *wss, char *buf);
672 ssize_t (*store)(struct wlp_wss *wss, const char *buf, size_t count);
673};
674
675#define WSS_ATTR(_name, _mode, _show, _store) \
676static struct wlp_wss_attribute wss_attr_##_name = __ATTR(_name, _mode, \
677 _show, _store)
678
679extern int wlp_setup(struct wlp *, struct uwb_rc *, struct net_device *ndev);
680extern void wlp_remove(struct wlp *);
681extern ssize_t wlp_neighborhood_show(struct wlp *, char *);
682extern int wlp_wss_setup(struct net_device *, struct wlp_wss *);
683extern void wlp_wss_remove(struct wlp_wss *);
684extern ssize_t wlp_wss_activate_show(struct wlp_wss *, char *);
685extern ssize_t wlp_wss_activate_store(struct wlp_wss *, const char *, size_t);
686extern ssize_t wlp_eda_show(struct wlp *, char *);
687extern ssize_t wlp_eda_store(struct wlp *, const char *, size_t);
688extern ssize_t wlp_uuid_show(struct wlp *, char *);
689extern ssize_t wlp_uuid_store(struct wlp *, const char *, size_t);
690extern ssize_t wlp_dev_name_show(struct wlp *, char *);
691extern ssize_t wlp_dev_name_store(struct wlp *, const char *, size_t);
692extern ssize_t wlp_dev_manufacturer_show(struct wlp *, char *);
693extern ssize_t wlp_dev_manufacturer_store(struct wlp *, const char *, size_t);
694extern ssize_t wlp_dev_model_name_show(struct wlp *, char *);
695extern ssize_t wlp_dev_model_name_store(struct wlp *, const char *, size_t);
696extern ssize_t wlp_dev_model_nr_show(struct wlp *, char *);
697extern ssize_t wlp_dev_model_nr_store(struct wlp *, const char *, size_t);
698extern ssize_t wlp_dev_serial_show(struct wlp *, char *);
699extern ssize_t wlp_dev_serial_store(struct wlp *, const char *, size_t);
700extern ssize_t wlp_dev_prim_category_show(struct wlp *, char *);
701extern ssize_t wlp_dev_prim_category_store(struct wlp *, const char *,
702 size_t);
703extern ssize_t wlp_dev_prim_OUI_show(struct wlp *, char *);
704extern ssize_t wlp_dev_prim_OUI_store(struct wlp *, const char *, size_t);
705extern ssize_t wlp_dev_prim_OUI_sub_show(struct wlp *, char *);
706extern ssize_t wlp_dev_prim_OUI_sub_store(struct wlp *, const char *,
707 size_t);
708extern ssize_t wlp_dev_prim_subcat_show(struct wlp *, char *);
709extern ssize_t wlp_dev_prim_subcat_store(struct wlp *, const char *,
710 size_t);
711extern int wlp_receive_frame(struct device *, struct wlp *, struct sk_buff *,
712 struct uwb_dev_addr *);
713extern int wlp_prepare_tx_frame(struct device *, struct wlp *,
714 struct sk_buff *, struct uwb_dev_addr *);
715void wlp_reset_all(struct wlp *wlp);
716
717/**
718 * Initialize WSS
719 */
720static inline
721void wlp_wss_init(struct wlp_wss *wss)
722{
723 mutex_init(&wss->mutex);
724}
725
726static inline
727void wlp_init(struct wlp *wlp)
728{
729 INIT_LIST_HEAD(&wlp->neighbors);
730 mutex_init(&wlp->mutex);
731 mutex_init(&wlp->nbmutex);
732 wlp_wss_init(&wlp->wss);
733}
734
735
736#endif /* #ifndef __LINUX__WLP_H_ */