11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: hysdn_procconf.c,v 1.8.6.4 2001/09/23 22:24:54 kai Exp $ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 1999 by Werner Cornelius (werner@titro.de) 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software may be used and distributed according to the terms 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the GNU General Public License, incorporated herein by reference. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14d43c36dc6b357fa1806800f18aa30123c747a6d1Alexey Dobriyan#include <linux/cred.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/poll.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 195a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 2076a64921dad9acd76270dc74249f0dfe11c84bb8Arnd Bergmann#include <linux/mutex.h> 21457c4cbc5a3dde259d2a1f15d5f9785290397267Eric W. Biederman#include <net/net_namespace.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hysdn_defs.h" 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2576a64921dad9acd76270dc74249f0dfe11c84bb8Arnd Bergmannstatic DEFINE_MUTEX(hysdn_conf_mutex); 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INFO_OUT_LEN 80 /* length of info line including lf */ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************/ 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* defines and data structure for conf write operations */ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************/ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONF_STATE_DETECT 0 /* waiting for detect */ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONF_STATE_CONF 1 /* writing config data */ 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONF_STATE_POF 2 /* writing pof data */ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONF_LINE_LEN 255 /* 255 chars max */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct conf_writedata { 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_card *card; /* card the device is connected to */ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int buf_size; /* actual number of bytes in the buffer */ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int needed_size; /* needed size when reading pof */ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int state; /* actual interface states from above constants */ 42c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char conf_line[CONF_LINE_LEN]; /* buffered conf line */ 43c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned short channel; /* active channel number */ 44c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char *pof_buffer; /* buffer when writing pof */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************************/ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* process_line parses one config line and transfers it to the card if */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* necessary. */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* if the return value is negative an error occurred. */ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************************/ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsprocess_line(struct conf_writedata *cnf) 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 55c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char *cp = cnf->conf_line; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_LINE) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "conf line: %s", cp); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*cp == '-') { /* option */ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp++; /* point to option char */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*cp++ != 'c') 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); /* option unknown or used */ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 0; /* start value for channel */ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((*cp <= '9') && (*cp >= '0')) 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = i * 10 + *cp++ - '0'; /* get decimal number */ 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i > 65535) { 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_MISC) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "conf channel invalid %d", i); 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ERR_INV_CHAN); /* invalid channel */ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->channel = i & 0xFFFF; /* set new channel number */ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); /* success */ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* option */ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*cp == '*') { /* line to send */ 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_DATA) 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "conf chan=%d %s", cnf->channel, cp); 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (hysdn_tx_cfgline(cnf->card, cnf->conf_line + 1, 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->channel)); /* send the line without * */ 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* line to send */ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* process_line */ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************/ 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* conf file operations and tables */ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************/ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************/ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* write conf file -> boot or send cfg line to card */ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************/ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 94475be4d85a274d0961593db41cf85689db1d583cJoe Percheshysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t *off) 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct conf_writedata *cnf; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 98c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char ch, *cp; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!count) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); /* nothing to handle */ 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(cnf = file->private_data)) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); /* should never happen */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->state == CONF_STATE_DETECT) { /* auto detect cnf or pof data */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&ch, buf, 1)) /* get first char for detect */ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ch == 0x1A) { 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we detected a pof file */ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cnf->needed_size = pof_write_open(cnf->card, &cnf->pof_buffer)) <= 0) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cnf->needed_size); /* an error occurred -> exit */ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size = 0; /* buffer is empty */ 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->state = CONF_STATE_POF; /* new state */ 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* conf data has been detected */ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size = 0; /* buffer is empty */ 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->state = CONF_STATE_CONF; /* requested conf data write */ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->state != CARD_STATE_RUN) 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ERR_NOT_BOOTED); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->conf_line[CONF_LINE_LEN - 1] = 0; /* limit string length */ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->channel = 4098; /* default channel for output */ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* state was auto detect */ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->state == CONF_STATE_POF) { /* pof write active */ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = cnf->needed_size - cnf->buf_size; /* bytes still missing for write */ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i <= 0) 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EINVAL); /* size error handling pof */ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i < count) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = i; /* limit requested number of bytes */ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(cnf->pof_buffer + cnf->buf_size, buf, count)) 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); /* error while copying */ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size += count; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->needed_size == cnf->buf_size) { 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->needed_size = pof_write_buffer(cnf->card, cnf->buf_size); /* write data */ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->needed_size <= 0) { 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->card->state = CARD_STATE_BOOTERR; /* show boot error */ 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cnf->needed_size); /* an error occurred */ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size = 0; /* buffer is empty again */ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pof write active */ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { /* conf write active */ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->state != CARD_STATE_RUN) { 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_MISC) 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "cnf write denied -> not booted"); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ERR_NOT_BOOTED); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = (CONF_LINE_LEN - 1) - cnf->buf_size; /* bytes available in buffer */ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i > 0) { 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* copy remaining bytes into buffer */ 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count > i) 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = i; /* limit transfer */ 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(cnf->conf_line + cnf->buf_size, buf, count)) 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); /* error while copying */ 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = count; /* number of chars in buffer */ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp = cnf->conf_line + cnf->buf_size; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (i) { 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* search for end of line */ 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((*cp < ' ') && (*cp != 9)) 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* end of line found */ 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp++; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i--; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* search for end of line */ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) { 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* delimiter found */ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp++ = 0; /* string termination */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count -= (i - 1); /* subtract remaining bytes from count */ 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((i) && (*cp < ' ') && (*cp != 9)) { 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i--; /* discard next char */ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count++; /* mark as read */ 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp++; /* next char */ 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size = 0; /* buffer is empty after transfer */ 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((i = process_line(cnf)) < 0) /* handle the line */ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = i; /* return the error */ 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* delimiter found */ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size += count; /* add chars to string */ 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->buf_size >= CONF_LINE_LEN - 1) { 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_MISC) 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "cnf line too long %d chars pos %d", cnf->buf_size, count); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ERR_CONF_LONG); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* not delimited */ 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* copy remaining bytes into buffer */ 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->card->debug_flags & LOG_CNF_MISC) 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(cnf->card, "cnf line too long"); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ERR_CONF_LONG); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* conf write active */ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (count); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* hysdn_conf_write */ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************/ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* read conf file -> output card info data */ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************/ 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 212ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mitahysdn_conf_read(struct file *file, char __user *buf, size_t count, loff_t *off) 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *cp; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 216ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita if (!(file->f_mode & FMODE_READ)) 217ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita return -EPERM; /* no permission to read */ 218ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita 219ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita if (!(cp = file->private_data)) 220ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita return -EFAULT; /* should never happen */ 221ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita 222ea23ec26727b4df97b4965715f0519b6ddc0aa4bAkinobu Mita return simple_read_from_buffer(buf, count, off, cp, strlen(cp)); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* hysdn_conf_read */ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************/ 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* open conf file */ 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************/ 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshysdn_conf_open(struct inode *ino, struct file *filep) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_card *card; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct conf_writedata *cnf; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *cp, *tmp; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* now search the addressed card */ 23676a64921dad9acd76270dc74249f0dfe11c84bb8Arnd Bergmann mutex_lock(&hysdn_conf_mutex); 237d9dda78bad879595d8c4220a067fc029d6484a16Al Viro card = PDE_DATA(ino); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x", 240d76b0d9b2d87cfc95686e148767cbf7d0e22bdc0David Howells filep->f_cred->fsuid, filep->f_cred->fsgid, 241d76b0d9b2d87cfc95686e148767cbf7d0e22bdc0David Howells filep->f_mode); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* write only access -> write boot file or conf line */ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) { 24776a64921dad9acd76270dc74249f0dfe11c84bb8Arnd Bergmann mutex_unlock(&hysdn_conf_mutex); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->card = card; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->buf_size = 0; /* nothing buffered */ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf->state = CONF_STATE_DETECT; /* start auto detect */ 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds filep->private_data = cnf; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* read access -> output card info data */ 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2585cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day if (!(tmp = kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) { 25976a64921dad9acd76270dc74249f0dfe11c84bb8Arnd Bergmann mutex_unlock(&hysdn_conf_mutex); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EFAULT); /* out of memory */ 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds filep->private_data = tmp; /* start of string */ 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* first output a headline */ 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(tmp, "id bus slot type irq iobase dp-mem b-chans fax-chans state device"); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp = tmp; /* start of string */ 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (*cp) 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp++; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp++ = ' '; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp++ = '\n'; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* and now the data */ 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(cp, "%d %3d %4d %4d %3d 0x%04x 0x%08lx %7d %9d %3d %s", 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->myid, 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->bus, 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_SLOT(card->devfn), 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->brdtype, 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->irq, 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->iobase, 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->membase, 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->bchans, 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->faxchans, 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->state, 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_net_getname(card)); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (*cp) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp++; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp++ = ' '; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp++ = '\n'; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *cp = 0; /* end of string */ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { /* simultaneous read/write access forbidden ! */ 29376a64921dad9acd76270dc74249f0dfe11c84bb8Arnd Bergmann mutex_unlock(&hysdn_conf_mutex); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-EPERM); /* no permission this time */ 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 29676a64921dad9acd76270dc74249f0dfe11c84bb8Arnd Bergmann mutex_unlock(&hysdn_conf_mutex); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return nonseekable_open(ino, filep); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* hysdn_conf_open */ 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************/ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* close a config file. */ 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************/ 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshysdn_conf_close(struct inode *ino, struct file *filep) 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_card *card; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct conf_writedata *cnf; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31076a64921dad9acd76270dc74249f0dfe11c84bb8Arnd Bergmann mutex_lock(&hysdn_conf_mutex); 311d9dda78bad879595d8c4220a067fc029d6484a16Al Viro card = PDE_DATA(ino); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x", 314d76b0d9b2d87cfc95686e148767cbf7d0e22bdc0David Howells filep->f_cred->fsuid, filep->f_cred->fsgid, 315d76b0d9b2d87cfc95686e148767cbf7d0e22bdc0David Howells filep->f_mode); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* write only access -> write boot file or conf line */ 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (filep->private_data) { 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cnf = filep->private_data; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cnf->state == CONF_STATE_POF) 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = pof_write_close(cnf->card); /* close the pof write */ 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(filep->private_data); /* free allocated memory for buffer */ 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } /* handle write private data */ 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* read access -> output card info data */ 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3303c7208f253571ee5f157b98f0e315b5172afe092Jesper Juhl kfree(filep->private_data); /* release memory */ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 33276a64921dad9acd76270dc74249f0dfe11c84bb8Arnd Bergmann mutex_unlock(&hysdn_conf_mutex); 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (retval); 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* hysdn_conf_close */ 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************/ 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* table for conf filesystem functions defined above. */ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************/ 3392b8693c0617e972fc0b2fd1ebf8de97e15b656c3Arjan van de Venstatic const struct file_operations conf_fops = 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 341ac41cfd19bf77424519b962f8205ede51fceaac6Denis V. Lunev .owner = THIS_MODULE, 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .llseek = no_llseek, 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read = hysdn_conf_read, 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = hysdn_conf_write, 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = hysdn_conf_open, 346475be4d85a274d0961593db41cf85689db1d583cJoe Perches .release = hysdn_conf_close, 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************/ 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* hysdn subdir in /proc/net */ 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************/ 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct proc_dir_entry *hysdn_proc_entry = NULL; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************/ 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* hysdn_procconf_init is called when the module is loaded and after the cards */ 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* have been detected. The needed proc dir and card config files are created. */ 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The log init is called at last. */ 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************/ 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshysdn_procconf_init(void) 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_card *card; 363c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char conf_name[20]; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 365457c4cbc5a3dde259d2a1f15d5f9785290397267Eric W. Biederman hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, init_net.proc_net); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!hysdn_proc_entry) { 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n"); 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-1); 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card_root; /* point to first card */ 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (card) { 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); 3744d8e8d21de89ff9d86b83182f723129533aacaa9Al Viro if ((card->procconf = (void *) proc_create_data(conf_name, 375475be4d85a274d0961593db41cf85689db1d583cJoe Perches S_IFREG | S_IRUGO | S_IWUSR, 376475be4d85a274d0961593db41cf85689db1d583cJoe Perches hysdn_proc_entry, 3774d8e8d21de89ff9d86b83182f723129533aacaa9Al Viro &conf_fops, 3784d8e8d21de89ff9d86b83182f723129533aacaa9Al Viro card)) != NULL) { 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_proclog_init(card); /* init the log file entry */ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card->next; /* next entry */ 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 384cd141eeea911029b248cecf2fc464a12fe575dcfDavid S. Miller printk(KERN_NOTICE "HYSDN: procfs initialised\n"); 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* hysdn_procconf_init */ 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*************************************************************************************/ 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* hysdn_procconf_release is called when the module is unloaded and before the cards */ 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* resources are released. The module counter is assumed to be 0 ! */ 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*************************************************************************************/ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshysdn_procconf_release(void) 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_card *card; 396c721bccece2b3abca4f7b0b95108e68b78445cecAndrew Morton unsigned char conf_name[20]; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card_root; /* start with first card */ 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (card) { 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (card->procconf) 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_proc_entry(conf_name, hysdn_proc_entry); 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hysdn_proclog_release(card); /* init the log file entry */ 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card = card->next; /* point to next card */ 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 410457c4cbc5a3dde259d2a1f15d5f9785290397267Eric W. Biederman remove_proc_entry(PROC_SUBDIR_NAME, init_net.proc_net); 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 412