Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dgrp_dpa_ops.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 1999 Digi International (www.digi.com)
4  * James Puzzo <jamesp at digi dot com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
13  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  * PURPOSE. See the GNU General Public License for more details.
15  *
16  */
17 
18 /*
19  *
20  * Filename:
21  *
22  * dgrp_dpa_ops.c
23  *
24  * Description:
25  *
26  * Handle the file operations required for the "dpa" devices.
27  * Includes those functions required to register the "dpa" devices
28  * in "/proc".
29  *
30  * Author:
31  *
32  * James A. Puzzo
33  *
34  */
35 
36 #include <linux/module.h>
37 #include <linux/proc_fs.h>
38 #include <linux/tty.h>
39 #include <linux/poll.h>
40 #include <linux/cred.h>
41 #include <linux/sched.h>
42 #include <linux/ratelimit.h>
43 #include <asm/unaligned.h>
44 
45 #include "dgrp_common.h"
46 
47 /* File operation declarations */
48 static int dgrp_dpa_open(struct inode *, struct file *);
49 static int dgrp_dpa_release(struct inode *, struct file *);
50 static ssize_t dgrp_dpa_read(struct file *, char __user *, size_t, loff_t *);
51 static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd,
52  unsigned long arg);
53 static unsigned int dgrp_dpa_select(struct file *, struct poll_table_struct *);
54 
55 static const struct file_operations dpa_ops = {
56  .owner = THIS_MODULE,
57  .read = dgrp_dpa_read,
58  .poll = dgrp_dpa_select,
59  .unlocked_ioctl = dgrp_dpa_ioctl,
60  .open = dgrp_dpa_open,
61  .release = dgrp_dpa_release,
62 };
63 
64 static struct inode_operations dpa_inode_ops = {
65  .permission = dgrp_inode_permission
66 };
67 
68 
69 
70 struct digi_node {
71  uint nd_state; /* Node state: 1 = up, 0 = down. */
72  uint nd_chan_count; /* Number of channels found */
73  uint nd_tx_byte; /* Tx data count */
74  uint nd_rx_byte; /* RX data count */
75  u8 nd_ps_desc[MAX_DESC_LEN]; /* Description from PS */
76 };
77 
78 #define DIGI_GETNODE (('d'<<8) | 249) /* get board info */
79 
80 
81 struct digi_chan {
82  uint ch_port; /* Port number to get info on */
83  uint ch_open; /* 1 if open, 0 if not */
84  uint ch_txcount; /* TX data count */
85  uint ch_rxcount; /* RX data count */
86  uint ch_s_brate; /* Realport BRATE */
87  uint ch_s_estat; /* Realport ELAST */
88  uint ch_s_cflag; /* Realport CFLAG */
89  uint ch_s_iflag; /* Realport IFLAG */
90  uint ch_s_oflag; /* Realport OFLAG */
91  uint ch_s_xflag; /* Realport XFLAG */
92  uint ch_s_mstat; /* Realport MLAST */
93 };
94 
95 #define DIGI_GETCHAN (('d'<<8) | 248) /* get channel info */
96 
97 
98 struct digi_vpd {
99  int vpd_len;
101 };
102 
103 #define DIGI_GETVPD (('d'<<8) | 246) /* get VPD info */
104 
105 
106 struct digi_debug {
107  int onoff;
108  int port;
109 };
110 
111 #define DIGI_SETDEBUG (('d'<<8) | 247) /* set debug info */
112 
113 
115 {
116  struct nd_struct *node = de->data;
117 
118  de->proc_iops = &dpa_inode_ops;
119  de->proc_fops = &dpa_ops;
120 
121  node->nd_dpa_de = de;
122  spin_lock_init(&node->nd_dpa_lock);
123 }
124 
125 /*
126  * dgrp_dpa_open -- open the DPA device for a particular PortServer
127  */
128 static int dgrp_dpa_open(struct inode *inode, struct file *file)
129 {
130  struct nd_struct *nd;
131  int rtn = 0;
132 
133  struct proc_dir_entry *de;
134 
135  rtn = try_module_get(THIS_MODULE);
136  if (!rtn)
137  return -ENXIO;
138 
139  rtn = 0;
140 
141  if (!capable(CAP_SYS_ADMIN)) {
142  rtn = -EPERM;
143  goto done;
144  }
145 
146  /*
147  * Make sure that the "private_data" field hasn't already been used.
148  */
149  if (file->private_data) {
150  rtn = -EINVAL;
151  goto done;
152  }
153 
154  /*
155  * Get the node pointer, and fail if it doesn't exist.
156  */
157  de = PDE(inode);
158  if (!de) {
159  rtn = -ENXIO;
160  goto done;
161  }
162  nd = (struct nd_struct *)de->data;
163  if (!nd) {
164  rtn = -ENXIO;
165  goto done;
166  }
167 
168  file->private_data = (void *) nd;
169 
170  /*
171  * Allocate the DPA buffer.
172  */
173 
174  if (nd->nd_dpa_buf) {
175  rtn = -EBUSY;
176  } else {
178 
179  if (!nd->nd_dpa_buf) {
180  rtn = -ENOMEM;
181  } else {
182  nd->nd_dpa_out = 0;
183  nd->nd_dpa_in = 0;
184  nd->nd_dpa_lbolt = jiffies;
185  }
186  }
187 
188 done:
189 
190  if (rtn)
191  module_put(THIS_MODULE);
192  return rtn;
193 }
194 
195 /*
196  * dgrp_dpa_release -- close the DPA device for a particular PortServer
197  */
198 static int dgrp_dpa_release(struct inode *inode, struct file *file)
199 {
200  struct nd_struct *nd;
201  u8 *buf;
202  unsigned long lock_flags;
203 
204  /*
205  * Get the node pointer, and quit if it doesn't exist.
206  */
207  nd = (struct nd_struct *)(file->private_data);
208  if (!nd)
209  goto done;
210 
211  /*
212  * Free the dpa buffer.
213  */
214 
215  spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
216 
217  buf = nd->nd_dpa_buf;
218 
219  nd->nd_dpa_buf = NULL;
220  nd->nd_dpa_out = nd->nd_dpa_in;
221 
222  /*
223  * Wakeup any thread waiting for buffer space.
224  */
225 
226  if (nd->nd_dpa_flag & DPA_WAIT_SPACE) {
227  nd->nd_dpa_flag &= ~DPA_WAIT_SPACE;
229  }
230 
231  spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
232 
233  kfree(buf);
234 
235 done:
236  module_put(THIS_MODULE);
237  file->private_data = NULL;
238  return 0;
239 }
240 
241 /*
242  * dgrp_dpa_read
243  *
244  * Copy data from the monitoring buffer to the user, freeing space
245  * in the monitoring buffer for more messages
246  */
247 static ssize_t dgrp_dpa_read(struct file *file, char __user *buf, size_t count,
248  loff_t *ppos)
249 {
250  struct nd_struct *nd;
251  int n;
252  int r;
253  int offset = 0;
254  int res = 0;
255  ssize_t rtn;
256  unsigned long lock_flags;
257 
258  /*
259  * Get the node pointer, and quit if it doesn't exist.
260  */
261  nd = (struct nd_struct *)(file->private_data);
262  if (!nd)
263  return -ENXIO;
264 
265  /*
266  * Wait for some data to appear in the buffer.
267  */
268 
269  spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
270 
271  for (;;) {
272  n = (nd->nd_dpa_in - nd->nd_dpa_out) & DPA_MASK;
273 
274  if (n != 0)
275  break;
276 
277  nd->nd_dpa_flag |= DPA_WAIT_DATA;
278 
279  spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
280 
281  /*
282  * Go to sleep waiting until the condition becomes true.
283  */
285  ((nd->nd_dpa_flag & DPA_WAIT_DATA) == 0));
286 
287  if (rtn)
288  return rtn;
289 
290  spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
291  }
292 
293  /*
294  * Read whatever is there.
295  */
296 
297  if (n > count)
298  n = count;
299 
300  res = n;
301 
302  r = DPA_MAX - nd->nd_dpa_out;
303 
304  if (r <= n) {
305 
306  spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
307  rtn = copy_to_user((void __user *)buf,
308  nd->nd_dpa_buf + nd->nd_dpa_out, r);
309  spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
310 
311  if (rtn) {
312  rtn = -EFAULT;
313  goto done;
314  }
315 
316  nd->nd_dpa_out = 0;
317  n -= r;
318  offset = r;
319  }
320 
321  spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
322  rtn = copy_to_user((void __user *)buf + offset,
323  nd->nd_dpa_buf + nd->nd_dpa_out, n);
324  spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
325 
326  if (rtn) {
327  rtn = -EFAULT;
328  goto done;
329  }
330 
331  nd->nd_dpa_out += n;
332 
333  *ppos += res;
334 
335  rtn = res;
336 
337  /*
338  * Wakeup any thread waiting for buffer space.
339  */
340 
341  n = (nd->nd_dpa_in - nd->nd_dpa_out) & DPA_MASK;
342 
343  if (nd->nd_dpa_flag & DPA_WAIT_SPACE &&
344  (DPA_MAX - n) > DPA_HIGH_WATER) {
345  nd->nd_dpa_flag &= ~DPA_WAIT_SPACE;
347  }
348 
349  done:
350  spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
351  return rtn;
352 }
353 
354 static unsigned int dgrp_dpa_select(struct file *file,
355  struct poll_table_struct *table)
356 {
357  unsigned int retval = 0;
358  struct nd_struct *nd = file->private_data;
359 
360  if (nd->nd_dpa_out != nd->nd_dpa_in)
361  retval |= POLLIN | POLLRDNORM; /* Conditionally readable */
362 
363  retval |= POLLOUT | POLLWRNORM; /* Always writeable */
364 
365  return retval;
366 }
367 
368 static long dgrp_dpa_ioctl(struct file *file, unsigned int cmd,
369  unsigned long arg)
370 {
371 
372  struct nd_struct *nd;
373  struct digi_chan getchan;
374  struct digi_node getnode;
375  struct ch_struct *ch;
376  struct digi_debug setdebug;
377  struct digi_vpd vpd;
378  unsigned int port;
379  void __user *uarg = (void __user *) arg;
380 
381  nd = file->private_data;
382 
383  switch (cmd) {
384  case DIGI_GETCHAN:
385  if (copy_from_user(&getchan, uarg, sizeof(struct digi_chan)))
386  return -EFAULT;
387 
388  port = getchan.ch_port;
389 
391  return -EINVAL;
392 
393  ch = nd->nd_chan + port;
394 
395  getchan.ch_open = (ch->ch_open_count > 0) ? 1 : 0;
396  getchan.ch_txcount = ch->ch_txcount;
397  getchan.ch_rxcount = ch->ch_rxcount;
398  getchan.ch_s_brate = ch->ch_s_brate;
399  getchan.ch_s_estat = ch->ch_s_elast;
400  getchan.ch_s_cflag = ch->ch_s_cflag;
401  getchan.ch_s_iflag = ch->ch_s_iflag;
402  getchan.ch_s_oflag = ch->ch_s_oflag;
403  getchan.ch_s_xflag = ch->ch_s_xflag;
404  getchan.ch_s_mstat = ch->ch_s_mlast;
405 
406  if (copy_to_user(uarg, &getchan, sizeof(struct digi_chan)))
407  return -EFAULT;
408  break;
409 
410 
411  case DIGI_GETNODE:
412  getnode.nd_state = (nd->nd_state & NS_READY) ? 1 : 0;
413  getnode.nd_chan_count = nd->nd_chan_count;
414  getnode.nd_tx_byte = nd->nd_tx_byte;
415  getnode.nd_rx_byte = nd->nd_rx_byte;
416 
417  memset(&getnode.nd_ps_desc, 0, MAX_DESC_LEN);
418  strncpy(getnode.nd_ps_desc, nd->nd_ps_desc, MAX_DESC_LEN);
419 
420  if (copy_to_user(uarg, &getnode, sizeof(struct digi_node)))
421  return -EFAULT;
422  break;
423 
424 
425  case DIGI_SETDEBUG:
426  if (copy_from_user(&setdebug, uarg, sizeof(struct digi_debug)))
427  return -EFAULT;
428 
429  nd->nd_dpa_debug = setdebug.onoff;
430  nd->nd_dpa_port = setdebug.port;
431  break;
432 
433 
434  case DIGI_GETVPD:
435  if (nd->nd_vpd_len > 0) {
436  vpd.vpd_len = nd->nd_vpd_len;
437  memcpy(&vpd.vpd_data, &nd->nd_vpd, nd->nd_vpd_len);
438  } else {
439  vpd.vpd_len = 0;
440  }
441 
442  if (copy_to_user(uarg, &vpd, sizeof(struct digi_vpd)))
443  return -EFAULT;
444  break;
445  }
446 
447  return 0;
448 }
449 
460 static void dgrp_dpa(struct nd_struct *nd, u8 *buf, int nbuf)
461 {
462  int n;
463  int r;
464  unsigned long lock_flags;
465 
466  /*
467  * Grab DPA lock.
468  */
469  spin_lock_irqsave(&nd->nd_dpa_lock, lock_flags);
470 
471  /*
472  * Loop while data remains.
473  */
474  while (nbuf > 0 && nd->nd_dpa_buf != NULL) {
475 
476  n = (nd->nd_dpa_out - nd->nd_dpa_in - 1) & DPA_MASK;
477 
478  /*
479  * Enforce flow control on the DPA device.
480  */
481  if (n < (DPA_MAX - DPA_HIGH_WATER))
483 
484  /*
485  * This should never happen, as the flow control above
486  * should have stopped things before they got to this point.
487  */
488  if (n == 0) {
489  spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
490  return;
491  }
492 
493  /*
494  * Copy as much data as will fit.
495  */
496 
497  if (n > nbuf)
498  n = nbuf;
499 
500  r = DPA_MAX - nd->nd_dpa_in;
501 
502  if (r <= n) {
503  memcpy(nd->nd_dpa_buf + nd->nd_dpa_in, buf, r);
504 
505  n -= r;
506 
507  nd->nd_dpa_in = 0;
508 
509  buf += r;
510  nbuf -= r;
511  }
512 
513  memcpy(nd->nd_dpa_buf + nd->nd_dpa_in, buf, n);
514 
515  nd->nd_dpa_in += n;
516 
517  buf += n;
518  nbuf -= n;
519 
520  if (nd->nd_dpa_in >= DPA_MAX)
521  pr_info_ratelimited("%s - nd->nd_dpa_in (%i) >= DPA_MAX\n",
522  __func__, nd->nd_dpa_in);
523 
524  /*
525  * Wakeup any thread waiting for data
526  */
527  if (nd->nd_dpa_flag & DPA_WAIT_DATA) {
528  nd->nd_dpa_flag &= ~DPA_WAIT_DATA;
530  }
531  }
532 
533  /*
534  * Release the DPA lock.
535  */
536  spin_unlock_irqrestore(&nd->nd_dpa_lock, lock_flags);
537 }
538 
546 void dgrp_dpa_data(struct nd_struct *nd, int type, u8 *buf, int size)
547 {
548  u8 header[5];
549 
550  header[0] = type;
551 
552  put_unaligned_be32(size, header + 1);
553 
554  dgrp_dpa(nd, header, sizeof(header));
555  dgrp_dpa(nd, buf, size);
556 }