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__ */ 284