Commit | Line | Data |
---|---|---|
e5711071 PH |
1 | #ifndef _FIREWIRE_FWSERIAL_H |
2 | #define _FIREWIRE_FWSERIAL_H | |
3 | ||
4 | #include <linux/kernel.h> | |
5 | #include <linux/tty.h> | |
6 | #include <linux/tty_driver.h> | |
7 | #include <linux/tty_flip.h> | |
8 | #include <linux/list.h> | |
9 | #include <linux/firewire.h> | |
10 | #include <linux/firewire-constants.h> | |
11 | #include <linux/spinlock.h> | |
12 | #include <linux/rcupdate.h> | |
13 | #include <linux/mutex.h> | |
14 | #include <linux/serial.h> | |
15 | #include <linux/serial_reg.h> | |
16 | #include <linux/module.h> | |
17 | #include <linux/seq_file.h> | |
4df5bb04 | 18 | #include <linux/debugfs.h> |
e5711071 PH |
19 | |
20 | #include "dma_fifo.h" | |
21 | ||
22 | #ifdef FWTTY_PROFILING | |
23 | #define DISTRIBUTION_MAX_SIZE 8192 | |
24 | #define DISTRIBUTION_MAX_INDEX (ilog2(DISTRIBUTION_MAX_SIZE) + 1) | |
eeb6f1ba | 25 | static inline void fwtty_profile_data(unsigned int stat[], unsigned int val) |
e5711071 PH |
26 | { |
27 | int n = (val) ? min(ilog2(val) + 1, DISTRIBUTION_MAX_INDEX) : 0; | |
28 | ++stat[n]; | |
29 | } | |
30 | #else | |
31 | #define DISTRIBUTION_MAX_INDEX 0 | |
49bb8405 | 32 | #define fwtty_profile_data(st, n) |
e5711071 PH |
33 | #endif |
34 | ||
35 | /* Parameters for both VIRT_CABLE_PLUG & VIRT_CABLE_PLUG_RSP mgmt codes */ | |
36 | struct virt_plug_params { | |
37 | __be32 status_hi; | |
38 | __be32 status_lo; | |
39 | __be32 fifo_hi; | |
40 | __be32 fifo_lo; | |
41 | __be32 fifo_len; | |
42 | }; | |
43 | ||
44 | struct peer_work_params { | |
45 | union { | |
46 | struct virt_plug_params plug_req; | |
47 | }; | |
48 | }; | |
49 | ||
50 | /** | |
51 | * fwtty_peer: structure representing local & remote unit devices | |
52 | * @unit: unit child device of fw_device node | |
53 | * @serial: back pointer to associated fw_serial aggregate | |
54 | * @guid: unique 64-bit guid for this unit device | |
55 | * @generation: most recent bus generation | |
56 | * @node_id: most recent node_id | |
57 | * @speed: link speed of peer (0 = S100, 2 = S400, ... 5 = S3200) | |
58 | * @mgmt_addr: bus addr region to write mgmt packets to | |
59 | * @status_addr: bus addr register to write line status to | |
60 | * @fifo_addr: bus addr region to write serial output to | |
61 | * @fifo_len: max length for single write to fifo_addr | |
62 | * @list: link for insertion into fw_serial's peer_list | |
63 | * @rcu: for deferring peer reclamation | |
64 | * @lock: spinlock to synchonize changes to state & port fields | |
65 | * @work: only one work item can be queued at any one time | |
66 | * Note: pending work is canceled prior to removal, so this | |
67 | * peer is valid for at least the lifetime of the work function | |
68 | * @work_params: parameter block for work functions | |
69 | * @timer: timer for resetting peer state if remote request times out | |
70 | * @state: current state | |
71 | * @connect: work item for auto-connecting | |
72 | * @connect_retries: # of connections already attempted | |
73 | * @port: associated tty_port (usable if state == FWSC_ATTACHED) | |
74 | */ | |
75 | struct fwtty_peer { | |
76 | struct fw_unit *unit; | |
77 | struct fw_serial *serial; | |
78 | u64 guid; | |
79 | int generation; | |
80 | int node_id; | |
eeb6f1ba | 81 | unsigned int speed; |
e5711071 PH |
82 | int max_payload; |
83 | u64 mgmt_addr; | |
84 | ||
85 | /* these are usable only if state == FWSC_ATTACHED */ | |
86 | u64 status_addr; | |
87 | u64 fifo_addr; | |
88 | int fifo_len; | |
89 | ||
90 | struct list_head list; | |
91 | struct rcu_head rcu; | |
92 | ||
93 | spinlock_t lock; | |
6c256cb6 | 94 | work_func_t workfn; |
e5711071 PH |
95 | struct work_struct work; |
96 | struct peer_work_params work_params; | |
97 | struct timer_list timer; | |
98 | int state; | |
99 | struct delayed_work connect; | |
100 | int connect_retries; | |
101 | ||
102 | struct fwtty_port *port; | |
103 | }; | |
104 | ||
105 | #define to_peer(ptr, field) (container_of(ptr, struct fwtty_peer, field)) | |
106 | ||
107 | /* state values for fwtty_peer.state field */ | |
108 | enum fwtty_peer_state { | |
109 | FWPS_GONE, | |
110 | FWPS_NOT_ATTACHED, | |
111 | FWPS_ATTACHED, | |
112 | FWPS_PLUG_PENDING, | |
113 | FWPS_PLUG_RESPONDING, | |
114 | FWPS_UNPLUG_PENDING, | |
115 | FWPS_UNPLUG_RESPONDING, | |
116 | ||
117 | FWPS_NO_MGMT_ADDR = -1, | |
118 | }; | |
119 | ||
120 | #define CONNECT_RETRY_DELAY HZ | |
121 | #define MAX_CONNECT_RETRIES 10 | |
122 | ||
123 | /* must be holding peer lock for these state funclets */ | |
124 | static inline void peer_set_state(struct fwtty_peer *peer, int new) | |
125 | { | |
126 | peer->state = new; | |
127 | } | |
128 | ||
129 | static inline struct fwtty_port *peer_revert_state(struct fwtty_peer *peer) | |
130 | { | |
131 | struct fwtty_port *port = peer->port; | |
132 | ||
133 | peer->port = NULL; | |
134 | peer_set_state(peer, FWPS_NOT_ATTACHED); | |
135 | return port; | |
136 | } | |
137 | ||
138 | struct fwserial_mgmt_pkt { | |
139 | struct { | |
140 | __be16 len; | |
141 | __be16 code; | |
142 | } hdr; | |
143 | union { | |
144 | struct virt_plug_params plug_req; | |
145 | struct virt_plug_params plug_rsp; | |
146 | }; | |
147 | } __packed; | |
148 | ||
149 | /* fwserial_mgmt_packet codes */ | |
150 | #define FWSC_RSP_OK 0x0000 | |
151 | #define FWSC_RSP_NACK 0x8000 | |
152 | #define FWSC_CODE_MASK 0x0fff | |
153 | ||
154 | #define FWSC_VIRT_CABLE_PLUG 1 | |
155 | #define FWSC_VIRT_CABLE_UNPLUG 2 | |
156 | #define FWSC_VIRT_CABLE_PLUG_RSP 3 | |
157 | #define FWSC_VIRT_CABLE_UNPLUG_RSP 4 | |
158 | ||
159 | /* 1 min. plug timeout -- suitable for userland authorization */ | |
160 | #define VIRT_CABLE_PLUG_TIMEOUT (60 * HZ) | |
161 | ||
162 | struct stats { | |
eeb6f1ba DB |
163 | unsigned int xchars; |
164 | unsigned int dropped; | |
165 | unsigned int tx_stall; | |
166 | unsigned int fifo_errs; | |
167 | unsigned int sent; | |
168 | unsigned int lost; | |
169 | unsigned int throttled; | |
170 | unsigned int reads[DISTRIBUTION_MAX_INDEX + 1]; | |
171 | unsigned int writes[DISTRIBUTION_MAX_INDEX + 1]; | |
172 | unsigned int txns[DISTRIBUTION_MAX_INDEX + 1]; | |
173 | unsigned int unthrottle[DISTRIBUTION_MAX_INDEX + 1]; | |
e5711071 PH |
174 | }; |
175 | ||
176 | struct fwconsole_ops { | |
177 | void (*notify)(int code, void *data); | |
178 | void (*stats)(struct stats *stats, void *data); | |
179 | void (*proc_show)(struct seq_file *m, void *data); | |
180 | }; | |
181 | ||
182 | /* codes for console ops notify */ | |
183 | #define FWCON_NOTIFY_ATTACH 1 | |
184 | #define FWCON_NOTIFY_DETACH 2 | |
185 | ||
e5711071 PH |
186 | /** |
187 | * fwtty_port: structure used to track/represent underlying tty_port | |
188 | * @port: underlying tty_port | |
189 | * @device: tty device | |
190 | * @index: index into port_table for this particular port | |
2257d122 | 191 | * note: minor = index + minor_start assigned by tty_alloc_driver() |
e5711071 PH |
192 | * @serial: back pointer to the containing fw_serial |
193 | * @rx_handler: bus address handler for unique addr region used by remotes | |
194 | * to communicate with this port. Every port uses | |
195 | * fwtty_port_handler() for per port transactions. | |
196 | * @fwcon_ops: ops for attached fw_console (if any) | |
197 | * @con_data: private data for fw_console | |
198 | * @wait_tx: waitqueue for sleeping until writer/drain completes tx | |
199 | * @emit_breaks: delayed work responsible for generating breaks when the | |
200 | * break line status is active | |
201 | * @cps : characters per second computed from the termios settings | |
202 | * @break_last: timestamp in jiffies from last emit_breaks | |
203 | * @hangup: work responsible for HUPing when carrier is dropped/lost | |
204 | * @mstatus: loose virtualization of LSR/MSR | |
205 | * bits 15..0 correspond to TIOCM_* bits | |
206 | * bits 19..16 reserved for mctrl | |
207 | * bit 20 OOB_TX_THROTTLE | |
208 | * bits 23..21 reserved | |
209 | * bits 31..24 correspond to UART_LSR_* bits | |
210 | * @lock: spinlock for protecting concurrent access to fields below it | |
211 | * @mctrl: loose virtualization of MCR | |
212 | * bits 15..0 correspond to TIOCM_* bits | |
213 | * bit 16 OOB_RX_THROTTLE | |
214 | * bits 19..17 reserved | |
215 | * bits 31..20 reserved for mstatus | |
216 | * @drain: delayed work scheduled to ensure that writes are flushed. | |
217 | * The work can race with the writer but concurrent sending is | |
218 | * prevented with the IN_TX flag. Scheduled under lock to | |
219 | * limit scheduling when fifo has just been drained. | |
e5711071 | 220 | * @tx_fifo: fifo used to store & block-up writes for dma to remote |
69e98df7 | 221 | * @max_payload: max bytes transmissible per dma (based on peer's max_payload) |
e5711071 PH |
222 | * @status_mask: UART_LSR_* bitmask significant to rx (based on termios) |
223 | * @ignore_mask: UART_LSR_* bitmask of states to ignore (also based on termios) | |
224 | * @break_ctl: if set, port is 'sending break' to remote | |
225 | * @write_only: self-explanatory | |
226 | * @overrun: previous rx was lost (partially or completely) | |
227 | * @loopback: if set, port is in loopback mode | |
228 | * @flags: atomic bit flags | |
229 | * bit 0: IN_TX - gate to allow only one cpu to send from the dma fifo | |
230 | * at a time. | |
231 | * bit 1: STOP_TX - force tx to exit while sending | |
232 | * @peer: rcu-pointer to associated fwtty_peer (if attached) | |
233 | * NULL if no peer attached | |
234 | * @icount: predefined statistics reported by the TIOCGICOUNT ioctl | |
235 | * @stats: additional statistics reported in /proc/tty/driver/firewire_serial | |
236 | */ | |
237 | struct fwtty_port { | |
238 | struct tty_port port; | |
239 | struct device *device; | |
eeb6f1ba | 240 | unsigned int index; |
e5711071 PH |
241 | struct fw_serial *serial; |
242 | struct fw_address_handler rx_handler; | |
243 | ||
244 | struct fwconsole_ops *fwcon_ops; | |
245 | void *con_data; | |
246 | ||
247 | wait_queue_head_t wait_tx; | |
248 | struct delayed_work emit_breaks; | |
eeb6f1ba | 249 | unsigned int cps; |
e5711071 PH |
250 | unsigned long break_last; |
251 | ||
252 | struct work_struct hangup; | |
253 | ||
eeb6f1ba | 254 | unsigned int mstatus; |
e5711071 PH |
255 | |
256 | spinlock_t lock; | |
eeb6f1ba | 257 | unsigned int mctrl; |
e5711071 | 258 | struct delayed_work drain; |
e5711071 PH |
259 | struct dma_fifo tx_fifo; |
260 | int max_payload; | |
eeb6f1ba DB |
261 | unsigned int status_mask; |
262 | unsigned int ignore_mask; | |
263 | unsigned int break_ctl:1, | |
e5711071 PH |
264 | write_only:1, |
265 | overrun:1, | |
266 | loopback:1; | |
267 | unsigned long flags; | |
268 | ||
1aedfa8f | 269 | struct fwtty_peer __rcu *peer; |
e5711071 PH |
270 | |
271 | struct async_icount icount; | |
272 | struct stats stats; | |
273 | }; | |
274 | ||
275 | #define to_port(ptr, field) (container_of(ptr, struct fwtty_port, field)) | |
276 | ||
277 | /* bit #s for flags field */ | |
278 | #define IN_TX 0 | |
279 | #define STOP_TX 1 | |
e5711071 PH |
280 | |
281 | /* bitmasks for special mctrl/mstatus bits */ | |
282 | #define OOB_RX_THROTTLE 0x00010000 | |
283 | #define MCTRL_RSRVD 0x000e0000 | |
284 | #define OOB_TX_THROTTLE 0x00100000 | |
285 | #define MSTATUS_RSRVD 0x00e00000 | |
286 | ||
287 | #define MCTRL_MASK (TIOCM_DTR | TIOCM_RTS | TIOCM_OUT1 | TIOCM_OUT2 | \ | |
288 | TIOCM_LOOP | OOB_RX_THROTTLE | MCTRL_RSRVD) | |
289 | ||
290 | /* XXX even every 1/50th secs. may be unnecessarily accurate */ | |
291 | /* delay in jiffies between brk emits */ | |
292 | #define FREQ_BREAKS (HZ / 50) | |
293 | ||
294 | /* Ports are allocated in blocks of num_ports for each fw_card */ | |
87a5a037 PH |
295 | #define MAX_CARD_PORTS CONFIG_FWTTY_MAX_CARD_PORTS |
296 | #define MAX_TOTAL_PORTS CONFIG_FWTTY_MAX_TOTAL_PORTS | |
e5711071 PH |
297 | |
298 | /* tuning parameters */ | |
299 | #define FWTTY_PORT_TXFIFO_LEN 4096 | |
300 | #define FWTTY_PORT_MAX_PEND_DMA 8 /* costs a cache line per pend */ | |
301 | #define DRAIN_THRESHOLD 1024 | |
302 | #define MAX_ASYNC_PAYLOAD 4096 /* ohci-defined limit */ | |
303 | #define WRITER_MINIMUM 128 | |
304 | /* TODO: how to set watermark to AR context size? see fwtty_rx() */ | |
305 | #define HIGH_WATERMARK 32768 /* AR context is 32K */ | |
306 | ||
307 | /* | |
308 | * Size of bus addr region above 4GB used per port as the recv addr | |
309 | * - must be at least as big as the MAX_ASYNC_PAYLOAD | |
310 | */ | |
311 | #define FWTTY_PORT_RXFIFO_LEN MAX_ASYNC_PAYLOAD | |
312 | ||
313 | /** | |
314 | * fw_serial: aggregate used to associate tty ports with specific fw_card | |
315 | * @card: fw_card associated with this fw_serial device (1:1 association) | |
316 | * @kref: reference-counted multi-port management allows delayed destroy | |
317 | * @self: local unit device as 'peer'. Not valid until local unit device | |
318 | * is enumerated. | |
319 | * @list: link for insertion into fwserial_list | |
320 | * @peer_list: list of local & remote unit devices attached to this card | |
321 | * @ports: fixed array of tty_ports provided by this serial device | |
322 | */ | |
323 | struct fw_serial { | |
324 | struct fw_card *card; | |
325 | struct kref kref; | |
326 | ||
4df5bb04 | 327 | struct dentry *debugfs; |
e5711071 PH |
328 | struct fwtty_peer *self; |
329 | ||
330 | struct list_head list; | |
331 | struct list_head peer_list; | |
332 | ||
333 | struct fwtty_port *ports[MAX_CARD_PORTS]; | |
334 | }; | |
335 | ||
336 | #define to_serial(ptr, field) (container_of(ptr, struct fw_serial, field)) | |
337 | ||
338 | #define TTY_DEV_NAME "fwtty" /* ttyFW was taken */ | |
339 | static const char tty_dev_name[] = TTY_DEV_NAME; | |
340 | static const char loop_dev_name[] = "fwloop"; | |
e5711071 | 341 | |
a3d9ad47 | 342 | extern struct tty_driver *fwtty_driver; |
e5711071 | 343 | |
e5711071 PH |
344 | /* |
345 | * Returns the max send async payload size in bytes based on the unit device | |
06b8f14d PH |
346 | * link speed. Self-limiting asynchronous bandwidth (via reducing the payload) |
347 | * is not necessary and does not work, because | |
348 | * 1) asynchronous traffic will absorb all available bandwidth (less that | |
349 | * being used for isochronous traffic) | |
350 | * 2) isochronous arbitration always wins. | |
e5711071 | 351 | */ |
eeb6f1ba | 352 | static inline int link_speed_to_max_payload(unsigned int speed) |
e5711071 | 353 | { |
d8356189 PH |
354 | /* Max async payload is 4096 - see IEEE 1394-2008 tables 6-4, 16-18 */ |
355 | return min(512 << speed, 4096); | |
e5711071 PH |
356 | } |
357 | ||
358 | #endif /* _FIREWIRE_FWSERIAL_H */ |