Commit 9a58a80a701bdb2d220cdab4914218df5b48d781

Authored by Alexey Dobriyan
Committed by David S. Miller
1 parent 508e14b4a4

proc_fops: convert drivers/isdn/ to seq_file

Convert code away from ->read_proc/->write_proc interfaces.  Switch to
proc_create()/proc_create_data() which make addition of proc entries
reliable wrt NULL ->proc_fops, NULL ->data and so on.

Problem with ->read_proc et al is described here commit
786d7e1612f0b0adb6046f19b906609e4fe8b1ba "Fix rmmod/read/write races in
/proc entries"

[akpm@linux-foundation.org: CONFIG_PROC_FS=n build fix]
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 21 changed files with 411 additions and 458 deletions Side-by-side Diff

Documentation/isdn/INTERFACE.CAPI
... ... @@ -149,10 +149,11 @@
149 149 pointer to a callback function returning the entry for the device in
150 150 the CAPI controller info table, /proc/capi/controller
151 151  
152   -read_proc_t *ctr_read_proc
153   - pointer to the read_proc callback function for the device's proc file
154   - system entry, /proc/capi/controllers/<n>; will be called with a
155   - pointer to the device's capi_ctr structure as the last (data) argument
  152 +const struct file_operations *proc_fops
  153 + pointers to callback functions for the device's proc file
  154 + system entry, /proc/capi/controllers/<n>; pointer to the device's
  155 + capi_ctr structure is available from struct proc_dir_entry::data
  156 + which is available from struct inode.
156 157  
157 158 Note: Callback functions except send_message() are never called in interrupt
158 159 context.
drivers/isdn/capi/capi.c
... ... @@ -33,6 +33,7 @@
33 33 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
34 34 #include <linux/skbuff.h>
35 35 #include <linux/proc_fs.h>
  36 +#include <linux/seq_file.h>
36 37 #include <linux/poll.h>
37 38 #include <linux/capi.h>
38 39 #include <linux/kernelcapi.h>
39 40  
40 41  
41 42  
42 43  
43 44  
44 45  
45 46  
46 47  
47 48  
48 49  
49 50  
50 51  
51 52  
52 53  
53 54  
... ... @@ -1407,114 +1408,84 @@
1407 1408 * /proc/capi/capi20:
1408 1409 * minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
1409 1410 */
1410   -static int proc_capidev_read_proc(char *page, char **start, off_t off,
1411   - int count, int *eof, void *data)
  1411 +static int capi20_proc_show(struct seq_file *m, void *v)
1412 1412 {
1413 1413 struct capidev *cdev;
1414 1414 struct list_head *l;
1415   - int len = 0;
1416 1415  
1417 1416 read_lock(&capidev_list_lock);
1418 1417 list_for_each(l, &capidev_list) {
1419 1418 cdev = list_entry(l, struct capidev, list);
1420   - len += sprintf(page+len, "0 %d %lu %lu %lu %lu\n",
  1419 + seq_printf(m, "0 %d %lu %lu %lu %lu\n",
1421 1420 cdev->ap.applid,
1422 1421 cdev->ap.nrecvctlpkt,
1423 1422 cdev->ap.nrecvdatapkt,
1424 1423 cdev->ap.nsentctlpkt,
1425 1424 cdev->ap.nsentdatapkt);
1426   - if (len <= off) {
1427   - off -= len;
1428   - len = 0;
1429   - } else {
1430   - if (len-off > count)
1431   - goto endloop;
1432   - }
1433 1425 }
1434   -
1435   -endloop:
1436 1426 read_unlock(&capidev_list_lock);
1437   - if (len < count)
1438   - *eof = 1;
1439   - if (len > count) len = count;
1440   - if (len < 0) len = 0;
1441   - return len;
  1427 + return 0;
1442 1428 }
1443 1429  
  1430 +static int capi20_proc_open(struct inode *inode, struct file *file)
  1431 +{
  1432 + return single_open(file, capi20_proc_show, NULL);
  1433 +}
  1434 +
  1435 +static const struct file_operations capi20_proc_fops = {
  1436 + .owner = THIS_MODULE,
  1437 + .open = capi20_proc_open,
  1438 + .read = seq_read,
  1439 + .llseek = seq_lseek,
  1440 + .release = single_release,
  1441 +};
  1442 +
1444 1443 /*
1445 1444 * /proc/capi/capi20ncci:
1446 1445 * applid ncci
1447 1446 */
1448   -static int proc_capincci_read_proc(char *page, char **start, off_t off,
1449   - int count, int *eof, void *data)
  1447 +static int capi20ncci_proc_show(struct seq_file *m, void *v)
1450 1448 {
1451 1449 struct capidev *cdev;
1452 1450 struct capincci *np;
1453 1451 struct list_head *l;
1454   - int len = 0;
1455 1452  
1456 1453 read_lock(&capidev_list_lock);
1457 1454 list_for_each(l, &capidev_list) {
1458 1455 cdev = list_entry(l, struct capidev, list);
1459 1456 for (np=cdev->nccis; np; np = np->next) {
1460   - len += sprintf(page+len, "%d 0x%x\n",
  1457 + seq_printf(m, "%d 0x%x\n",
1461 1458 cdev->ap.applid,
1462 1459 np->ncci);
1463   - if (len <= off) {
1464   - off -= len;
1465   - len = 0;
1466   - } else {
1467   - if (len-off > count)
1468   - goto endloop;
1469   - }
1470 1460 }
1471 1461 }
1472   -endloop:
1473 1462 read_unlock(&capidev_list_lock);
1474   - *start = page+off;
1475   - if (len < count)
1476   - *eof = 1;
1477   - if (len>count) len = count;
1478   - if (len<0) len = 0;
1479   - return len;
  1463 + return 0;
1480 1464 }
1481 1465  
1482   -static struct procfsentries {
1483   - char *name;
1484   - mode_t mode;
1485   - int (*read_proc)(char *page, char **start, off_t off,
1486   - int count, int *eof, void *data);
1487   - struct proc_dir_entry *procent;
1488   -} procfsentries[] = {
1489   - /* { "capi", S_IFDIR, 0 }, */
1490   - { "capi/capi20", 0 , proc_capidev_read_proc },
1491   - { "capi/capi20ncci", 0 , proc_capincci_read_proc },
  1466 +static int capi20ncci_proc_open(struct inode *inode, struct file *file)
  1467 +{
  1468 + return single_open(file, capi20ncci_proc_show, NULL);
  1469 +}
  1470 +
  1471 +static const struct file_operations capi20ncci_proc_fops = {
  1472 + .owner = THIS_MODULE,
  1473 + .open = capi20ncci_proc_open,
  1474 + .read = seq_read,
  1475 + .llseek = seq_lseek,
  1476 + .release = single_release,
1492 1477 };
1493 1478  
1494 1479 static void __init proc_init(void)
1495 1480 {
1496   - int nelem = ARRAY_SIZE(procfsentries);
1497   - int i;
1498   -
1499   - for (i=0; i < nelem; i++) {
1500   - struct procfsentries *p = procfsentries + i;
1501   - p->procent = create_proc_entry(p->name, p->mode, NULL);
1502   - if (p->procent) p->procent->read_proc = p->read_proc;
1503   - }
  1481 + proc_create("capi/capi20", 0, NULL, &capi20_proc_fops);
  1482 + proc_create("capi/capi20ncci", 0, NULL, &capi20ncci_proc_fops);
1504 1483 }
1505 1484  
1506 1485 static void __exit proc_exit(void)
1507 1486 {
1508   - int nelem = ARRAY_SIZE(procfsentries);
1509   - int i;
1510   -
1511   - for (i=nelem-1; i >= 0; i--) {
1512   - struct procfsentries *p = procfsentries + i;
1513   - if (p->procent) {
1514   - remove_proc_entry(p->name, NULL);
1515   - p->procent = NULL;
1516   - }
1517   - }
  1487 + remove_proc_entry("capi/capi20", NULL);
  1488 + remove_proc_entry("capi/capi20ncci", NULL);
1518 1489 }
1519 1490  
1520 1491 /* -------- init function and module interface ---------------------- */
drivers/isdn/capi/capidrv.c
... ... @@ -24,6 +24,7 @@
24 24 #include <linux/isdn.h>
25 25 #include <linux/isdnif.h>
26 26 #include <linux/proc_fs.h>
  27 +#include <linux/seq_file.h>
27 28 #include <linux/capi.h>
28 29 #include <linux/kernelcapi.h>
29 30 #include <linux/ctype.h>
30 31  
31 32  
32 33  
33 34  
34 35  
... ... @@ -2229,59 +2230,37 @@
2229 2230 * /proc/capi/capidrv:
2230 2231 * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
2231 2232 */
2232   -static int proc_capidrv_read_proc(char *page, char **start, off_t off,
2233   - int count, int *eof, void *data)
  2233 +static int capidrv_proc_show(struct seq_file *m, void *v)
2234 2234 {
2235   - int len = 0;
2236   -
2237   - len += sprintf(page+len, "%lu %lu %lu %lu\n",
  2235 + seq_printf(m, "%lu %lu %lu %lu\n",
2238 2236 global.ap.nrecvctlpkt,
2239 2237 global.ap.nrecvdatapkt,
2240 2238 global.ap.nsentctlpkt,
2241 2239 global.ap.nsentdatapkt);
2242   - if (off+count >= len)
2243   - *eof = 1;
2244   - if (len < off)
2245   - return 0;
2246   - *start = page + off;
2247   - return ((count < len-off) ? count : len-off);
  2240 + return 0;
2248 2241 }
2249 2242  
2250   -static struct procfsentries {
2251   - char *name;
2252   - mode_t mode;
2253   - int (*read_proc)(char *page, char **start, off_t off,
2254   - int count, int *eof, void *data);
2255   - struct proc_dir_entry *procent;
2256   -} procfsentries[] = {
2257   - /* { "capi", S_IFDIR, 0 }, */
2258   - { "capi/capidrv", 0 , proc_capidrv_read_proc },
  2243 +static int capidrv_proc_open(struct inode *inode, struct file *file)
  2244 +{
  2245 + return single_open(file, capidrv_proc_show, NULL);
  2246 +}
  2247 +
  2248 +static const struct file_operations capidrv_proc_fops = {
  2249 + .owner = THIS_MODULE,
  2250 + .open = capidrv_proc_open,
  2251 + .read = seq_read,
  2252 + .llseek = seq_lseek,
  2253 + .release = single_release,
2259 2254 };
2260 2255  
2261 2256 static void __init proc_init(void)
2262 2257 {
2263   - int nelem = ARRAY_SIZE(procfsentries);
2264   - int i;
2265   -
2266   - for (i=0; i < nelem; i++) {
2267   - struct procfsentries *p = procfsentries + i;
2268   - p->procent = create_proc_entry(p->name, p->mode, NULL);
2269   - if (p->procent) p->procent->read_proc = p->read_proc;
2270   - }
  2258 + proc_create("capi/capidrv", 0, NULL, &capidrv_proc_fops);
2271 2259 }
2272 2260  
2273 2261 static void __exit proc_exit(void)
2274 2262 {
2275   - int nelem = ARRAY_SIZE(procfsentries);
2276   - int i;
2277   -
2278   - for (i=nelem-1; i >= 0; i--) {
2279   - struct procfsentries *p = procfsentries + i;
2280   - if (p->procent) {
2281   - remove_proc_entry(p->name, NULL);
2282   - p->procent = NULL;
2283   - }
2284   - }
  2263 + remove_proc_entry("capi/capidrv", NULL);
2285 2264 }
2286 2265  
2287 2266 static int __init capidrv_init(void)
drivers/isdn/capi/kcapi.c
... ... @@ -490,13 +490,7 @@
490 490 card->traceflag = showcapimsgs;
491 491  
492 492 sprintf(card->procfn, "capi/controllers/%d", card->cnr);
493   - card->procent = create_proc_entry(card->procfn, 0, NULL);
494   - if (card->procent) {
495   - card->procent->read_proc =
496   - (int (*)(char *,char **,off_t,int,int *,void *))
497   - card->ctr_read_proc;
498   - card->procent->data = card;
499   - }
  493 + card->procent = proc_create_data(card->procfn, 0, NULL, card->proc_fops, card);
500 494  
501 495 ncards++;
502 496 printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n",
drivers/isdn/gigaset/capi.c
... ... @@ -13,6 +13,8 @@
13 13  
14 14 #include "gigaset.h"
15 15 #include <linux/ctype.h>
  16 +#include <linux/proc_fs.h>
  17 +#include <linux/seq_file.h>
16 18 #include <linux/isdn/capilli.h>
17 19 #include <linux/isdn/capicmd.h>
18 20 #include <linux/isdn/capiutil.h>
19 21  
20 22  
21 23  
22 24  
23 25  
... ... @@ -2106,35 +2108,22 @@
2106 2108 return ctr->name; /* ToDo: more? */
2107 2109 }
2108 2110  
2109   -/**
2110   - * gigaset_ctr_read_proc() - build controller proc file entry
2111   - * @page: buffer of PAGE_SIZE bytes for receiving the entry.
2112   - * @start: unused.
2113   - * @off: unused.
2114   - * @count: unused.
2115   - * @eof: unused.
2116   - * @ctr: controller descriptor structure.
2117   - *
2118   - * Return value: length of generated entry
2119   - */
2120   -static int gigaset_ctr_read_proc(char *page, char **start, off_t off,
2121   - int count, int *eof, struct capi_ctr *ctr)
  2111 +static int gigaset_proc_show(struct seq_file *m, void *v)
2122 2112 {
  2113 + struct capi_ctr *ctr = m->private;
2123 2114 struct cardstate *cs = ctr->driverdata;
2124 2115 char *s;
2125 2116 int i;
2126   - int len = 0;
2127   - len += sprintf(page+len, "%-16s %s\n", "name", ctr->name);
2128   - len += sprintf(page+len, "%-16s %s %s\n", "dev",
  2117 +
  2118 + seq_printf(m, "%-16s %s\n", "name", ctr->name);
  2119 + seq_printf(m, "%-16s %s %s\n", "dev",
2129 2120 dev_driver_string(cs->dev), dev_name(cs->dev));
2130   - len += sprintf(page+len, "%-16s %d\n", "id", cs->myid);
  2121 + seq_printf(m, "%-16s %d\n", "id", cs->myid);
2131 2122 if (cs->gotfwver)
2132   - len += sprintf(page+len, "%-16s %d.%d.%d.%d\n", "firmware",
  2123 + seq_printf(m, "%-16s %d.%d.%d.%d\n", "firmware",
2133 2124 cs->fwver[0], cs->fwver[1], cs->fwver[2], cs->fwver[3]);
2134   - len += sprintf(page+len, "%-16s %d\n", "channels",
2135   - cs->channels);
2136   - len += sprintf(page+len, "%-16s %s\n", "onechannel",
2137   - cs->onechannel ? "yes" : "no");
  2125 + seq_printf(m, "%-16s %d\n", "channels", cs->channels);
  2126 + seq_printf(m, "%-16s %s\n", "onechannel", cs->onechannel ? "yes" : "no");
2138 2127  
2139 2128 switch (cs->mode) {
2140 2129 case M_UNKNOWN:
... ... @@ -2152,7 +2141,7 @@
2152 2141 default:
2153 2142 s = "??";
2154 2143 }
2155   - len += sprintf(page+len, "%-16s %s\n", "mode", s);
  2144 + seq_printf(m, "%-16s %s\n", "mode", s);
2156 2145  
2157 2146 switch (cs->mstate) {
2158 2147 case MS_UNINITIALIZED:
2159 2148  
2160 2149  
2161 2150  
2162 2151  
2163 2152  
... ... @@ -2176,25 +2165,21 @@
2176 2165 default:
2177 2166 s = "??";
2178 2167 }
2179   - len += sprintf(page+len, "%-16s %s\n", "mstate", s);
  2168 + seq_printf(m, "%-16s %s\n", "mstate", s);
2180 2169  
2181   - len += sprintf(page+len, "%-16s %s\n", "running",
2182   - cs->running ? "yes" : "no");
2183   - len += sprintf(page+len, "%-16s %s\n", "connected",
2184   - cs->connected ? "yes" : "no");
2185   - len += sprintf(page+len, "%-16s %s\n", "isdn_up",
2186   - cs->isdn_up ? "yes" : "no");
2187   - len += sprintf(page+len, "%-16s %s\n", "cidmode",
2188   - cs->cidmode ? "yes" : "no");
  2170 + seq_printf(m, "%-16s %s\n", "running", cs->running ? "yes" : "no");
  2171 + seq_printf(m, "%-16s %s\n", "connected", cs->connected ? "yes" : "no");
  2172 + seq_printf(m, "%-16s %s\n", "isdn_up", cs->isdn_up ? "yes" : "no");
  2173 + seq_printf(m, "%-16s %s\n", "cidmode", cs->cidmode ? "yes" : "no");
2189 2174  
2190 2175 for (i = 0; i < cs->channels; i++) {
2191   - len += sprintf(page+len, "[%d]%-13s %d\n", i, "corrupted",
  2176 + seq_printf(m, "[%d]%-13s %d\n", i, "corrupted",
2192 2177 cs->bcs[i].corrupted);
2193   - len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_down",
  2178 + seq_printf(m, "[%d]%-13s %d\n", i, "trans_down",
2194 2179 cs->bcs[i].trans_down);
2195   - len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_up",
  2180 + seq_printf(m, "[%d]%-13s %d\n", i, "trans_up",
2196 2181 cs->bcs[i].trans_up);
2197   - len += sprintf(page+len, "[%d]%-13s %d\n", i, "chstate",
  2182 + seq_printf(m, "[%d]%-13s %d\n", i, "chstate",
2198 2183 cs->bcs[i].chstate);
2199 2184 switch (cs->bcs[i].proto2) {
2200 2185 case L2_BITSYNC:
2201 2186  
2202 2187  
2203 2188  
... ... @@ -2209,12 +2194,24 @@
2209 2194 default:
2210 2195 s = "??";
2211 2196 }
2212   - len += sprintf(page+len, "[%d]%-13s %s\n", i, "proto2", s);
  2197 + seq_printf(m, "[%d]%-13s %s\n", i, "proto2", s);
2213 2198 }
2214   - return len;
  2199 + return 0;
2215 2200 }
2216 2201  
  2202 +static int gigaset_proc_open(struct inode *inode, struct file *file)
  2203 +{
  2204 + return single_open(file, gigaset_proc_show, PDE(inode)->data);
  2205 +}
2217 2206  
  2207 +static const struct file_operations gigaset_proc_fops = {
  2208 + .owner = THIS_MODULE,
  2209 + .open = gigaset_proc_open,
  2210 + .read = seq_read,
  2211 + .llseek = seq_lseek,
  2212 + .release = single_release,
  2213 +};
  2214 +
2218 2215 static struct capi_driver capi_driver_gigaset = {
2219 2216 .name = "gigaset",
2220 2217 .revision = "1.0",
... ... @@ -2256,7 +2253,7 @@
2256 2253 iif->ctr.release_appl = gigaset_release_appl;
2257 2254 iif->ctr.send_message = gigaset_send_message;
2258 2255 iif->ctr.procinfo = gigaset_procinfo;
2259   - iif->ctr.ctr_read_proc = gigaset_ctr_read_proc;
  2256 + iif->ctr.proc_fops = &gigaset_proc_fops;
2260 2257 INIT_LIST_HEAD(&iif->appls);
2261 2258 skb_queue_head_init(&iif->sendqueue);
2262 2259 atomic_set(&iif->sendqlen, 0);
drivers/isdn/hardware/avm/avmcard.h
... ... @@ -556,8 +556,7 @@
556 556 void b1_parse_version(avmctrl_info *card);
557 557 irqreturn_t b1_interrupt(int interrupt, void *devptr);
558 558  
559   -int b1ctl_read_proc(char *page, char **start, off_t off,
560   - int count, int *eof, struct capi_ctr *ctrl);
  559 +extern const struct file_operations b1ctl_proc_fops;
561 560  
562 561 avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *,
563 562 long rsize, long ssize);
... ... @@ -577,8 +576,7 @@
577 576 capi_register_params *rp);
578 577 void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl);
579 578 u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
580   -int b1dmactl_read_proc(char *page, char **start, off_t off,
581   - int count, int *eof, struct capi_ctr *ctrl);
  579 +extern const struct file_operations b1dmactl_proc_fops;
582 580  
583 581 #endif /* _AVMCARD_H_ */
drivers/isdn/hardware/avm/b1.c
... ... @@ -12,6 +12,8 @@
12 12 #include <linux/module.h>
13 13 #include <linux/kernel.h>
14 14 #include <linux/pci.h>
  15 +#include <linux/proc_fs.h>
  16 +#include <linux/seq_file.h>
15 17 #include <linux/skbuff.h>
16 18 #include <linux/delay.h>
17 19 #include <linux/mm.h>
18 20  
19 21  
20 22  
... ... @@ -634,18 +636,17 @@
634 636 }
635 637  
636 638 /* ------------------------------------------------------------- */
637   -int b1ctl_read_proc(char *page, char **start, off_t off,
638   - int count, int *eof, struct capi_ctr *ctrl)
  639 +static int b1ctl_proc_show(struct seq_file *m, void *v)
639 640 {
  641 + struct capi_ctr *ctrl = m->private;
640 642 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
641 643 avmcard *card = cinfo->card;
642 644 u8 flag;
643   - int len = 0;
644 645 char *s;
645 646  
646   - len += sprintf(page+len, "%-16s %s\n", "name", card->name);
647   - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
648   - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
  647 + seq_printf(m, "%-16s %s\n", "name", card->name);
  648 + seq_printf(m, "%-16s 0x%x\n", "io", card->port);
  649 + seq_printf(m, "%-16s %d\n", "irq", card->irq);
649 650 switch (card->cardtype) {
650 651 case avm_b1isa: s = "B1 ISA"; break;
651 652 case avm_b1pci: s = "B1 PCI"; break;
652 653  
653 654  
654 655  
655 656  
656 657  
... ... @@ -658,20 +659,20 @@
658 659 case avm_c2: s = "C2"; break;
659 660 default: s = "???"; break;
660 661 }
661   - len += sprintf(page+len, "%-16s %s\n", "type", s);
  662 + seq_printf(m, "%-16s %s\n", "type", s);
662 663 if (card->cardtype == avm_t1isa)
663   - len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr);
  664 + seq_printf(m, "%-16s %d\n", "cardnr", card->cardnr);
664 665 if ((s = cinfo->version[VER_DRIVER]) != NULL)
665   - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
  666 + seq_printf(m, "%-16s %s\n", "ver_driver", s);
666 667 if ((s = cinfo->version[VER_CARDTYPE]) != NULL)
667   - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
  668 + seq_printf(m, "%-16s %s\n", "ver_cardtype", s);
668 669 if ((s = cinfo->version[VER_SERIAL]) != NULL)
669   - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
  670 + seq_printf(m, "%-16s %s\n", "ver_serial", s);
670 671  
671 672 if (card->cardtype != avm_m1) {
672 673 flag = ((u8 *)(ctrl->profile.manu))[3];
673 674 if (flag)
674   - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
  675 + seq_printf(m, "%-16s%s%s%s%s%s%s%s\n",
675 676 "protocol",
676 677 (flag & 0x01) ? " DSS1" : "",
677 678 (flag & 0x02) ? " CT1" : "",
... ... @@ -685,7 +686,7 @@
685 686 if (card->cardtype != avm_m1) {
686 687 flag = ((u8 *)(ctrl->profile.manu))[5];
687 688 if (flag)
688   - len += sprintf(page+len, "%-16s%s%s%s%s\n",
  689 + seq_printf(m, "%-16s%s%s%s%s\n",
689 690 "linetype",
690 691 (flag & 0x01) ? " point to point" : "",
691 692 (flag & 0x02) ? " point to multipoint" : "",
692 693  
693 694  
... ... @@ -693,16 +694,25 @@
693 694 (flag & 0x04) ? " leased line with D-channel" : ""
694 695 );
695 696 }
696   - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
  697 + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname);
697 698  
698   - if (off+count >= len)
699   - *eof = 1;
700   - if (len < off)
701   - return 0;
702   - *start = page + off;
703   - return ((count < len-off) ? count : len-off);
  699 + return 0;
704 700 }
705 701  
  702 +static int b1ctl_proc_open(struct inode *inode, struct file *file)
  703 +{
  704 + return single_open(file, b1ctl_proc_show, PDE(inode)->data);
  705 +}
  706 +
  707 +const struct file_operations b1ctl_proc_fops = {
  708 + .owner = THIS_MODULE,
  709 + .open = b1ctl_proc_open,
  710 + .read = seq_read,
  711 + .llseek = seq_lseek,
  712 + .release = single_release,
  713 +};
  714 +EXPORT_SYMBOL(b1ctl_proc_fops);
  715 +
706 716 /* ------------------------------------------------------------- */
707 717  
708 718 #ifdef CONFIG_PCI
... ... @@ -780,8 +790,6 @@
780 790  
781 791 EXPORT_SYMBOL(b1_parse_version);
782 792 EXPORT_SYMBOL(b1_interrupt);
783   -
784   -EXPORT_SYMBOL(b1ctl_read_proc);
785 793  
786 794 static int __init b1_init(void)
787 795 {
drivers/isdn/hardware/avm/b1dma.c
... ... @@ -11,6 +11,8 @@
11 11  
12 12 #include <linux/module.h>
13 13 #include <linux/kernel.h>
  14 +#include <linux/proc_fs.h>
  15 +#include <linux/seq_file.h>
14 16 #include <linux/skbuff.h>
15 17 #include <linux/delay.h>
16 18 #include <linux/mm.h>
17 19  
18 20  
19 21  
... ... @@ -855,21 +857,20 @@
855 857  
856 858 /* ------------------------------------------------------------- */
857 859  
858   -int b1dmactl_read_proc(char *page, char **start, off_t off,
859   - int count, int *eof, struct capi_ctr *ctrl)
  860 +static int b1dmactl_proc_show(struct seq_file *m, void *v)
860 861 {
  862 + struct capi_ctr *ctrl = m->private;
861 863 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
862 864 avmcard *card = cinfo->card;
863 865 u8 flag;
864   - int len = 0;
865 866 char *s;
866 867 u32 txoff, txlen, rxoff, rxlen, csr;
867 868 unsigned long flags;
868 869  
869   - len += sprintf(page+len, "%-16s %s\n", "name", card->name);
870   - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
871   - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
872   - len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase);
  870 + seq_printf(m, "%-16s %s\n", "name", card->name);
  871 + seq_printf(m, "%-16s 0x%x\n", "io", card->port);
  872 + seq_printf(m, "%-16s %d\n", "irq", card->irq);
  873 + seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase);
873 874 switch (card->cardtype) {
874 875 case avm_b1isa: s = "B1 ISA"; break;
875 876 case avm_b1pci: s = "B1 PCI"; break;
876 877  
877 878  
878 879  
879 880  
... ... @@ -882,18 +883,18 @@
882 883 case avm_c2: s = "C2"; break;
883 884 default: s = "???"; break;
884 885 }
885   - len += sprintf(page+len, "%-16s %s\n", "type", s);
  886 + seq_printf(m, "%-16s %s\n", "type", s);
886 887 if ((s = cinfo->version[VER_DRIVER]) != NULL)
887   - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
  888 + seq_printf(m, "%-16s %s\n", "ver_driver", s);
888 889 if ((s = cinfo->version[VER_CARDTYPE]) != NULL)
889   - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
  890 + seq_printf(m, "%-16s %s\n", "ver_cardtype", s);
890 891 if ((s = cinfo->version[VER_SERIAL]) != NULL)
891   - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
  892 + seq_printf(m, "%-16s %s\n", "ver_serial", s);
892 893  
893 894 if (card->cardtype != avm_m1) {
894 895 flag = ((u8 *)(ctrl->profile.manu))[3];
895 896 if (flag)
896   - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
  897 + seq_printf(m, "%-16s%s%s%s%s%s%s%s\n",
897 898 "protocol",
898 899 (flag & 0x01) ? " DSS1" : "",
899 900 (flag & 0x02) ? " CT1" : "",
... ... @@ -907,7 +908,7 @@
907 908 if (card->cardtype != avm_m1) {
908 909 flag = ((u8 *)(ctrl->profile.manu))[5];
909 910 if (flag)
910   - len += sprintf(page+len, "%-16s%s%s%s%s\n",
  911 + seq_printf(m, "%-16s%s%s%s%s\n",
911 912 "linetype",
912 913 (flag & 0x01) ? " point to point" : "",
913 914 (flag & 0x02) ? " point to multipoint" : "",
... ... @@ -915,7 +916,7 @@
915 916 (flag & 0x04) ? " leased line with D-channel" : ""
916 917 );
917 918 }
918   - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
  919 + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname);
919 920  
920 921  
921 922 spin_lock_irqsave(&card->lock, flags);
922 923  
923 924  
... ... @@ -930,27 +931,30 @@
930 931  
931 932 spin_unlock_irqrestore(&card->lock, flags);
932 933  
933   - len += sprintf(page+len, "%-16s 0x%lx\n",
934   - "csr (cached)", (unsigned long)card->csr);
935   - len += sprintf(page+len, "%-16s 0x%lx\n",
936   - "csr", (unsigned long)csr);
937   - len += sprintf(page+len, "%-16s %lu\n",
938   - "txoff", (unsigned long)txoff);
939   - len += sprintf(page+len, "%-16s %lu\n",
940   - "txlen", (unsigned long)txlen);
941   - len += sprintf(page+len, "%-16s %lu\n",
942   - "rxoff", (unsigned long)rxoff);
943   - len += sprintf(page+len, "%-16s %lu\n",
944   - "rxlen", (unsigned long)rxlen);
  934 + seq_printf(m, "%-16s 0x%lx\n", "csr (cached)", (unsigned long)card->csr);
  935 + seq_printf(m, "%-16s 0x%lx\n", "csr", (unsigned long)csr);
  936 + seq_printf(m, "%-16s %lu\n", "txoff", (unsigned long)txoff);
  937 + seq_printf(m, "%-16s %lu\n", "txlen", (unsigned long)txlen);
  938 + seq_printf(m, "%-16s %lu\n", "rxoff", (unsigned long)rxoff);
  939 + seq_printf(m, "%-16s %lu\n", "rxlen", (unsigned long)rxlen);
945 940  
946   - if (off+count >= len)
947   - *eof = 1;
948   - if (len < off)
949   - return 0;
950   - *start = page + off;
951   - return ((count < len-off) ? count : len-off);
  941 + return 0;
952 942 }
953 943  
  944 +static int b1dmactl_proc_open(struct inode *inode, struct file *file)
  945 +{
  946 + return single_open(file, b1dmactl_proc_show, PDE(inode)->data);
  947 +}
  948 +
  949 +const struct file_operations b1dmactl_proc_fops = {
  950 + .owner = THIS_MODULE,
  951 + .open = b1dmactl_proc_open,
  952 + .read = seq_read,
  953 + .llseek = seq_lseek,
  954 + .release = single_release,
  955 +};
  956 +EXPORT_SYMBOL(b1dmactl_proc_fops);
  957 +
954 958 /* ------------------------------------------------------------- */
955 959  
956 960 EXPORT_SYMBOL(b1dma_reset);
... ... @@ -963,7 +967,6 @@
963 967 EXPORT_SYMBOL(b1dma_register_appl);
964 968 EXPORT_SYMBOL(b1dma_release_appl);
965 969 EXPORT_SYMBOL(b1dma_send_message);
966   -EXPORT_SYMBOL(b1dmactl_read_proc);
967 970  
968 971 static int __init b1dma_init(void)
969 972 {
drivers/isdn/hardware/avm/b1isa.c
... ... @@ -121,7 +121,7 @@
121 121 cinfo->capi_ctrl.load_firmware = b1_load_firmware;
122 122 cinfo->capi_ctrl.reset_ctr = b1_reset_ctr;
123 123 cinfo->capi_ctrl.procinfo = b1isa_procinfo;
124   - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
  124 + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops;
125 125 strcpy(cinfo->capi_ctrl.name, card->name);
126 126  
127 127 retval = attach_capi_ctr(&cinfo->capi_ctrl);
drivers/isdn/hardware/avm/b1pci.c
... ... @@ -112,7 +112,7 @@
112 112 cinfo->capi_ctrl.load_firmware = b1_load_firmware;
113 113 cinfo->capi_ctrl.reset_ctr = b1_reset_ctr;
114 114 cinfo->capi_ctrl.procinfo = b1pci_procinfo;
115   - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
  115 + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops;
116 116 strcpy(cinfo->capi_ctrl.name, card->name);
117 117 cinfo->capi_ctrl.owner = THIS_MODULE;
118 118  
... ... @@ -251,7 +251,7 @@
251 251 cinfo->capi_ctrl.load_firmware = b1dma_load_firmware;
252 252 cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr;
253 253 cinfo->capi_ctrl.procinfo = b1pciv4_procinfo;
254   - cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc;
  254 + cinfo->capi_ctrl.proc_fops = &b1dmactl_proc_fops;
255 255 strcpy(cinfo->capi_ctrl.name, card->name);
256 256  
257 257 retval = attach_capi_ctr(&cinfo->capi_ctrl);
drivers/isdn/hardware/avm/b1pcmcia.c
... ... @@ -108,7 +108,7 @@
108 108 cinfo->capi_ctrl.load_firmware = b1_load_firmware;
109 109 cinfo->capi_ctrl.reset_ctr = b1_reset_ctr;
110 110 cinfo->capi_ctrl.procinfo = b1pcmcia_procinfo;
111   - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
  111 + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops;
112 112 strcpy(cinfo->capi_ctrl.name, card->name);
113 113  
114 114 retval = attach_capi_ctr(&cinfo->capi_ctrl);
drivers/isdn/hardware/avm/c4.c
... ... @@ -11,6 +11,8 @@
11 11  
12 12 #include <linux/module.h>
13 13 #include <linux/kernel.h>
  14 +#include <linux/proc_fs.h>
  15 +#include <linux/seq_file.h>
14 16 #include <linux/skbuff.h>
15 17 #include <linux/delay.h>
16 18 #include <linux/mm.h>
17 19  
18 20  
19 21  
... ... @@ -1062,19 +1064,18 @@
1062 1064 return cinfo->infobuf;
1063 1065 }
1064 1066  
1065   -static int c4_read_proc(char *page, char **start, off_t off,
1066   - int count, int *eof, struct capi_ctr *ctrl)
  1067 +static int c4_proc_show(struct seq_file *m, void *v)
1067 1068 {
  1069 + struct capi_ctr *ctrl = m->private;
1068 1070 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
1069 1071 avmcard *card = cinfo->card;
1070 1072 u8 flag;
1071   - int len = 0;
1072 1073 char *s;
1073 1074  
1074   - len += sprintf(page+len, "%-16s %s\n", "name", card->name);
1075   - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
1076   - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
1077   - len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase);
  1075 + seq_printf(m, "%-16s %s\n", "name", card->name);
  1076 + seq_printf(m, "%-16s 0x%x\n", "io", card->port);
  1077 + seq_printf(m, "%-16s %d\n", "irq", card->irq);
  1078 + seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase);
1078 1079 switch (card->cardtype) {
1079 1080 case avm_b1isa: s = "B1 ISA"; break;
1080 1081 case avm_b1pci: s = "B1 PCI"; break;
1081 1082  
1082 1083  
1083 1084  
1084 1085  
... ... @@ -1087,18 +1088,18 @@
1087 1088 case avm_c2: s = "C2"; break;
1088 1089 default: s = "???"; break;
1089 1090 }
1090   - len += sprintf(page+len, "%-16s %s\n", "type", s);
  1091 + seq_printf(m, "%-16s %s\n", "type", s);
1091 1092 if ((s = cinfo->version[VER_DRIVER]) != NULL)
1092   - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
  1093 + seq_printf(m, "%-16s %s\n", "ver_driver", s);
1093 1094 if ((s = cinfo->version[VER_CARDTYPE]) != NULL)
1094   - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
  1095 + seq_printf(m, "%-16s %s\n", "ver_cardtype", s);
1095 1096 if ((s = cinfo->version[VER_SERIAL]) != NULL)
1096   - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
  1097 + seq_printf(m, "%-16s %s\n", "ver_serial", s);
1097 1098  
1098 1099 if (card->cardtype != avm_m1) {
1099 1100 flag = ((u8 *)(ctrl->profile.manu))[3];
1100 1101 if (flag)
1101   - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
  1102 + seq_printf(m, "%-16s%s%s%s%s%s%s%s\n",
1102 1103 "protocol",
1103 1104 (flag & 0x01) ? " DSS1" : "",
1104 1105 (flag & 0x02) ? " CT1" : "",
... ... @@ -1112,7 +1113,7 @@
1112 1113 if (card->cardtype != avm_m1) {
1113 1114 flag = ((u8 *)(ctrl->profile.manu))[5];
1114 1115 if (flag)
1115   - len += sprintf(page+len, "%-16s%s%s%s%s\n",
  1116 + seq_printf(m, "%-16s%s%s%s%s\n",
1116 1117 "linetype",
1117 1118 (flag & 0x01) ? " point to point" : "",
1118 1119 (flag & 0x02) ? " point to multipoint" : "",
1119 1120  
1120 1121  
... ... @@ -1120,16 +1121,24 @@
1120 1121 (flag & 0x04) ? " leased line with D-channel" : ""
1121 1122 );
1122 1123 }
1123   - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
  1124 + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname);
1124 1125  
1125   - if (off+count >= len)
1126   - *eof = 1;
1127   - if (len < off)
1128   - return 0;
1129   - *start = page + off;
1130   - return ((count < len-off) ? count : len-off);
  1126 + return 0;
1131 1127 }
1132 1128  
  1129 +static int c4_proc_open(struct inode *inode, struct file *file)
  1130 +{
  1131 + return single_open(file, c4_proc_show, PDE(inode)->data);
  1132 +}
  1133 +
  1134 +static const struct file_operations c4_proc_fops = {
  1135 + .owner = THIS_MODULE,
  1136 + .open = c4_proc_open,
  1137 + .read = seq_read,
  1138 + .llseek = seq_lseek,
  1139 + .release = single_release,
  1140 +};
  1141 +
1133 1142 /* ------------------------------------------------------------- */
1134 1143  
1135 1144 static int c4_add_card(struct capicardparams *p, struct pci_dev *dev,
... ... @@ -1201,7 +1210,7 @@
1201 1210 cinfo->capi_ctrl.load_firmware = c4_load_firmware;
1202 1211 cinfo->capi_ctrl.reset_ctr = c4_reset_ctr;
1203 1212 cinfo->capi_ctrl.procinfo = c4_procinfo;
1204   - cinfo->capi_ctrl.ctr_read_proc = c4_read_proc;
  1213 + cinfo->capi_ctrl.proc_fops = &c4_proc_fops;
1205 1214 strcpy(cinfo->capi_ctrl.name, card->name);
1206 1215  
1207 1216 retval = attach_capi_ctr(&cinfo->capi_ctrl);
drivers/isdn/hardware/avm/t1isa.c
... ... @@ -429,7 +429,7 @@
429 429 cinfo->capi_ctrl.load_firmware = t1isa_load_firmware;
430 430 cinfo->capi_ctrl.reset_ctr = t1isa_reset_ctr;
431 431 cinfo->capi_ctrl.procinfo = t1isa_procinfo;
432   - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
  432 + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops;
433 433 strcpy(cinfo->capi_ctrl.name, card->name);
434 434  
435 435 retval = attach_capi_ctr(&cinfo->capi_ctrl);
drivers/isdn/hardware/avm/t1pci.c
... ... @@ -119,7 +119,7 @@
119 119 cinfo->capi_ctrl.load_firmware = b1dma_load_firmware;
120 120 cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr;
121 121 cinfo->capi_ctrl.procinfo = t1pci_procinfo;
122   - cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc;
  122 + cinfo->capi_ctrl.proc_fops = &b1dmactl_proc_fops;
123 123 strcpy(cinfo->capi_ctrl.name, card->name);
124 124  
125 125 retval = attach_capi_ctr(&cinfo->capi_ctrl);
drivers/isdn/hardware/eicon/capimain.c
... ... @@ -13,6 +13,7 @@
13 13 #include <linux/module.h>
14 14 #include <linux/init.h>
15 15 #include <asm/uaccess.h>
  16 +#include <linux/seq_file.h>
16 17 #include <linux/skbuff.h>
17 18  
18 19 #include "os_capi.h"
19 20  
20 21  
21 22  
22 23  
23 24  
... ... @@ -75,25 +76,32 @@
75 76 /*
76 77 * proc function for controller info
77 78 */
78   -static int diva_ctl_read_proc(char *page, char **start, off_t off,
79   - int count, int *eof, struct capi_ctr *ctrl)
  79 +static int diva_ctl_proc_show(struct seq_file *m, void *v)
80 80 {
  81 + struct capi_ctr *ctrl = m->private;
81 82 diva_card *card = (diva_card *) ctrl->driverdata;
82   - int len = 0;
83 83  
84   - len += sprintf(page + len, "%s\n", ctrl->name);
85   - len += sprintf(page + len, "Serial No. : %s\n", ctrl->serial);
86   - len += sprintf(page + len, "Id : %d\n", card->Id);
87   - len += sprintf(page + len, "Channels : %d\n", card->d.channels);
  84 + seq_printf(m, "%s\n", ctrl->name);
  85 + seq_printf(m, "Serial No. : %s\n", ctrl->serial);
  86 + seq_printf(m, "Id : %d\n", card->Id);
  87 + seq_printf(m, "Channels : %d\n", card->d.channels);
88 88  
89   - if (off + count >= len)
90   - *eof = 1;
91   - if (len < off)
92   - return 0;
93   - *start = page + off;
94   - return ((count < len - off) ? count : len - off);
  89 + return 0;
95 90 }
96 91  
  92 +static int diva_ctl_proc_open(struct inode *inode, struct file *file)
  93 +{
  94 + return single_open(file, diva_ctl_proc_show, NULL);
  95 +}
  96 +
  97 +static const struct file_operations diva_ctl_proc_fops = {
  98 + .owner = THIS_MODULE,
  99 + .open = diva_ctl_proc_open,
  100 + .read = seq_read,
  101 + .llseek = seq_lseek,
  102 + .release = single_release,
  103 +};
  104 +
97 105 /*
98 106 * set additional os settings in capi_ctr struct
99 107 */
... ... @@ -102,7 +110,7 @@
102 110 ctrl->driver_name = DRIVERLNAME;
103 111 ctrl->load_firmware = NULL;
104 112 ctrl->reset_ctr = NULL;
105   - ctrl->ctr_read_proc = diva_ctl_read_proc;
  113 + ctrl->proc_fops = &diva_ctl_proc_fops;
106 114 ctrl->owner = THIS_MODULE;
107 115 }
108 116  
drivers/isdn/hardware/eicon/diva_didd.c
... ... @@ -15,6 +15,7 @@
15 15 #include <linux/init.h>
16 16 #include <linux/kernel.h>
17 17 #include <linux/proc_fs.h>
  18 +#include <linux/seq_file.h>
18 19 #include <net/net_namespace.h>
19 20  
20 21 #include "platform.h"
21 22  
22 23  
23 24  
24 25  
25 26  
26 27  
... ... @@ -62,39 +63,41 @@
62 63 return rev;
63 64 }
64 65  
65   -static int
66   -proc_read(char *page, char **start, off_t off, int count, int *eof,
67   - void *data)
  66 +static int divadidd_proc_show(struct seq_file *m, void *v)
68 67 {
69   - int len = 0;
70 68 char tmprev[32];
71 69  
72 70 strcpy(tmprev, main_revision);
73   - len += sprintf(page + len, "%s\n", DRIVERNAME);
74   - len += sprintf(page + len, "name : %s\n", DRIVERLNAME);
75   - len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_DIDD);
76   - len += sprintf(page + len, "build : %s(%s)\n",
  71 + seq_printf(m, "%s\n", DRIVERNAME);
  72 + seq_printf(m, "name : %s\n", DRIVERLNAME);
  73 + seq_printf(m, "release : %s\n", DRIVERRELEASE_DIDD);
  74 + seq_printf(m, "build : %s(%s)\n",
77 75 diva_didd_common_code_build, DIVA_BUILD);
78   - len += sprintf(page + len, "revision : %s\n", getrev(tmprev));
  76 + seq_printf(m, "revision : %s\n", getrev(tmprev));
79 77  
80   - if (off + count >= len)
81   - *eof = 1;
82   - if (len < off)
83   - return 0;
84   - *start = page + off;
85   - return ((count < len - off) ? count : len - off);
  78 + return 0;
86 79 }
87 80  
  81 +static int divadidd_proc_open(struct inode *inode, struct file *file)
  82 +{
  83 + return single_open(file, divadidd_proc_show, NULL);
  84 +}
  85 +
  86 +static const struct file_operations divadidd_proc_fops = {
  87 + .owner = THIS_MODULE,
  88 + .open = divadidd_proc_open,
  89 + .read = seq_read,
  90 + .llseek = seq_lseek,
  91 + .release = single_release,
  92 +};
  93 +
88 94 static int DIVA_INIT_FUNCTION create_proc(void)
89 95 {
90 96 proc_net_eicon = proc_mkdir("eicon", init_net.proc_net);
91 97  
92 98 if (proc_net_eicon) {
93   - if ((proc_didd =
94   - create_proc_entry(DRIVERLNAME, S_IFREG | S_IRUGO,
95   - proc_net_eicon))) {
96   - proc_didd->read_proc = proc_read;
97   - }
  99 + proc_didd = proc_create(DRIVERLNAME, S_IRUGO, proc_net_eicon,
  100 + &divadidd_proc_fops);
98 101 return (1);
99 102 }
100 103 return (0);
drivers/isdn/hardware/eicon/divasi.c
... ... @@ -17,6 +17,7 @@
17 17 #include <linux/poll.h>
18 18 #include <linux/proc_fs.h>
19 19 #include <linux/skbuff.h>
  20 +#include <linux/seq_file.h>
20 21 #include <linux/smp_lock.h>
21 22 #include <asm/uaccess.h>
22 23  
23 24  
24 25  
25 26  
26 27  
27 28  
28 29  
29 30  
... ... @@ -86,39 +87,40 @@
86 87 extern struct proc_dir_entry *proc_net_eicon;
87 88 static struct proc_dir_entry *um_idi_proc_entry = NULL;
88 89  
89   -static int
90   -um_idi_proc_read(char *page, char **start, off_t off, int count, int *eof,
91   - void *data)
  90 +static int um_idi_proc_show(struct seq_file *m, void *v)
92 91 {
93   - int len = 0;
94 92 char tmprev[32];
95 93  
96   - len += sprintf(page + len, "%s\n", DRIVERNAME);
97   - len += sprintf(page + len, "name : %s\n", DRIVERLNAME);
98   - len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_IDI);
  94 + seq_printf(m, "%s\n", DRIVERNAME);
  95 + seq_printf(m, "name : %s\n", DRIVERLNAME);
  96 + seq_printf(m, "release : %s\n", DRIVERRELEASE_IDI);
99 97 strcpy(tmprev, main_revision);
100   - len += sprintf(page + len, "revision : %s\n", getrev(tmprev));
101   - len += sprintf(page + len, "build : %s\n", DIVA_BUILD);
102   - len += sprintf(page + len, "major : %d\n", major);
  98 + seq_printf(m, "revision : %s\n", getrev(tmprev));
  99 + seq_printf(m, "build : %s\n", DIVA_BUILD);
  100 + seq_printf(m, "major : %d\n", major);
103 101  
104   - if (off + count >= len)
105   - *eof = 1;
106   - if (len < off)
107   - return 0;
108   - *start = page + off;
109   - return ((count < len - off) ? count : len - off);
  102 + return 0;
110 103 }
111 104  
  105 +static int um_idi_proc_open(struct inode *inode, struct file *file)
  106 +{
  107 + return single_open(file, um_idi_proc_show, NULL);
  108 +}
  109 +
  110 +static const struct file_operations um_idi_proc_fops = {
  111 + .owner = THIS_MODULE,
  112 + .open = um_idi_proc_open,
  113 + .read = seq_read,
  114 + .llseek = seq_lseek,
  115 + .release = single_release,
  116 +};
  117 +
112 118 static int DIVA_INIT_FUNCTION create_um_idi_proc(void)
113 119 {
114   - um_idi_proc_entry = create_proc_entry(DRIVERLNAME,
115   - S_IFREG | S_IRUGO | S_IWUSR,
116   - proc_net_eicon);
  120 + um_idi_proc_entry = proc_create(DRIVERLNAME, S_IRUGO, proc_net_eicon,
  121 + &um_idi_proc_fops);
117 122 if (!um_idi_proc_entry)
118 123 return (0);
119   -
120   - um_idi_proc_entry->read_proc = um_idi_proc_read;
121   -
122 124 return (1);
123 125 }
124 126  
drivers/isdn/hardware/eicon/divasproc.c
... ... @@ -14,6 +14,7 @@
14 14 #include <linux/kernel.h>
15 15 #include <linux/poll.h>
16 16 #include <linux/proc_fs.h>
  17 +#include <linux/seq_file.h>
17 18 #include <linux/list.h>
18 19 #include <asm/uaccess.h>
19 20  
20 21  
... ... @@ -141,14 +142,10 @@
141 142 }
142 143 }
143 144  
144   -/*
145   -** write group_optimization
146   -*/
147   -static int
148   -write_grp_opt(struct file *file, const char __user *buffer, unsigned long count,
149   - void *data)
  145 +static ssize_t grp_opt_proc_write(struct file *file, const char __user *buffer,
  146 + size_t count, loff_t *pos)
150 147 {
151   - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
  148 + diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data;
152 149 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
153 150  
154 151 if ((count == 1) || (count == 2)) {
155 152  
... ... @@ -172,14 +169,10 @@
172 169 return (-EINVAL);
173 170 }
174 171  
175   -/*
176   -** write dynamic_l1_down
177   -*/
178   -static int
179   -write_d_l1_down(struct file *file, const char __user *buffer, unsigned long count,
180   - void *data)
  172 +static ssize_t d_l1_down_proc_write(struct file *file, const char __user *buffer,
  173 + size_t count, loff_t *pos)
181 174 {
182   - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
  175 + diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data;
183 176 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
184 177  
185 178 if ((count == 1) || (count == 2)) {
186 179  
187 180  
188 181  
189 182  
190 183  
191 184  
192 185  
193 186  
194 187  
195 188  
196 189  
... ... @@ -203,63 +196,62 @@
203 196 return (-EINVAL);
204 197 }
205 198  
206   -
207   -/*
208   -** read dynamic_l1_down
209   -*/
210   -static int
211   -read_d_l1_down(char *page, char **start, off_t off, int count, int *eof,
212   - void *data)
  199 +static int d_l1_down_proc_show(struct seq_file *m, void *v)
213 200 {
214   - int len = 0;
215   - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
  201 + diva_os_xdi_adapter_t *a = m->private;
216 202 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
217 203  
218   - len += sprintf(page + len, "%s\n",
  204 + seq_printf(m, "%s\n",
219 205 (IoAdapter->capi_cfg.
220 206 cfg_1 & DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? "1" :
221 207 "0");
  208 + return 0;
  209 +}
222 210  
223   - if (off + count >= len)
224   - *eof = 1;
225   - if (len < off)
226   - return 0;
227   - *start = page + off;
228   - return ((count < len - off) ? count : len - off);
  211 +static int d_l1_down_proc_open(struct inode *inode, struct file *file)
  212 +{
  213 + return single_open(file, d_l1_down_proc_show, PDE(inode)->data);
229 214 }
230 215  
231   -/*
232   -** read group_optimization
233   -*/
234   -static int
235   -read_grp_opt(char *page, char **start, off_t off, int count, int *eof,
236   - void *data)
  216 +static const struct file_operations d_l1_down_proc_fops = {
  217 + .owner = THIS_MODULE,
  218 + .open = d_l1_down_proc_open,
  219 + .read = seq_read,
  220 + .llseek = seq_lseek,
  221 + .release = single_release,
  222 + .write = d_l1_down_proc_write,
  223 +};
  224 +
  225 +static int grp_opt_proc_show(struct seq_file *m, void *v)
237 226 {
238   - int len = 0;
239   - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
  227 + diva_os_xdi_adapter_t *a = m->private;
240 228 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
241 229  
242   - len += sprintf(page + len, "%s\n",
  230 + seq_printf(m, "%s\n",
243 231 (IoAdapter->capi_cfg.
244 232 cfg_1 & DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON)
245 233 ? "1" : "0");
  234 + return 0;
  235 +}
246 236  
247   - if (off + count >= len)
248   - *eof = 1;
249   - if (len < off)
250   - return 0;
251   - *start = page + off;
252   - return ((count < len - off) ? count : len - off);
  237 +static int grp_opt_proc_open(struct inode *inode, struct file *file)
  238 +{
  239 + return single_open(file, grp_opt_proc_show, PDE(inode)->data);
253 240 }
254 241  
255   -/*
256   -** info write
257   -*/
258   -static int
259   -info_write(struct file *file, const char __user *buffer, unsigned long count,
260   - void *data)
  242 +static const struct file_operations grp_opt_proc_fops = {
  243 + .owner = THIS_MODULE,
  244 + .open = grp_opt_proc_open,
  245 + .read = seq_read,
  246 + .llseek = seq_lseek,
  247 + .release = single_release,
  248 + .write = grp_opt_proc_write,
  249 +};
  250 +
  251 +static ssize_t info_proc_write(struct file *file, const char __user *buffer,
  252 + size_t count, loff_t *pos)
261 253 {
262   - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
  254 + diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data;
263 255 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
264 256 char c[4];
265 257  
266 258  
267 259  
268 260  
269 261  
270 262  
271 263  
272 264  
273 265  
274 266  
... ... @@ -277,63 +269,46 @@
277 269 return (-EINVAL);
278 270 }
279 271  
280   -/*
281   -** info read
282   -*/
283   -static int
284   -info_read(char *page, char **start, off_t off, int count, int *eof,
285   - void *data)
  272 +static int info_proc_show(struct seq_file *m, void *v)
286 273 {
287 274 int i = 0;
288   - int len = 0;
289 275 char *p;
290 276 char tmpser[16];
291   - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data;
  277 + diva_os_xdi_adapter_t *a = m->private;
292 278 PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1];
293 279  
294   - len +=
295   - sprintf(page + len, "Name : %s\n",
296   - IoAdapter->Properties.Name);
297   - len += sprintf(page + len, "DSP state : %08x\n", a->dsp_mask);
298   - len += sprintf(page + len, "Channels : %02d\n",
299   - IoAdapter->Properties.Channels);
300   - len += sprintf(page + len, "E. max/used : %03d/%03d\n",
  280 + seq_printf(m, "Name : %s\n", IoAdapter->Properties.Name);
  281 + seq_printf(m, "DSP state : %08x\n", a->dsp_mask);
  282 + seq_printf(m, "Channels : %02d\n", IoAdapter->Properties.Channels);
  283 + seq_printf(m, "E. max/used : %03d/%03d\n",
301 284 IoAdapter->e_max, IoAdapter->e_count);
302 285 diva_get_vserial_number(IoAdapter, tmpser);
303   - len += sprintf(page + len, "Serial : %s\n", tmpser);
304   - len +=
305   - sprintf(page + len, "IRQ : %d\n",
306   - IoAdapter->irq_info.irq_nr);
307   - len += sprintf(page + len, "CardIndex : %d\n", a->CardIndex);
308   - len += sprintf(page + len, "CardOrdinal : %d\n", a->CardOrdinal);
309   - len += sprintf(page + len, "Controller : %d\n", a->controller);
310   - len += sprintf(page + len, "Bus-Type : %s\n",
  286 + seq_printf(m, "Serial : %s\n", tmpser);
  287 + seq_printf(m, "IRQ : %d\n", IoAdapter->irq_info.irq_nr);
  288 + seq_printf(m, "CardIndex : %d\n", a->CardIndex);
  289 + seq_printf(m, "CardOrdinal : %d\n", a->CardOrdinal);
  290 + seq_printf(m, "Controller : %d\n", a->controller);
  291 + seq_printf(m, "Bus-Type : %s\n",
311 292 (a->Bus ==
312 293 DIVAS_XDI_ADAPTER_BUS_ISA) ? "ISA" : "PCI");
313   - len += sprintf(page + len, "Port-Name : %s\n", a->port_name);
  294 + seq_printf(m, "Port-Name : %s\n", a->port_name);
314 295 if (a->Bus == DIVAS_XDI_ADAPTER_BUS_PCI) {
315   - len +=
316   - sprintf(page + len, "PCI-bus : %d\n",
317   - a->resources.pci.bus);
318   - len +=
319   - sprintf(page + len, "PCI-func : %d\n",
320   - a->resources.pci.func);
  296 + seq_printf(m, "PCI-bus : %d\n", a->resources.pci.bus);
  297 + seq_printf(m, "PCI-func : %d\n", a->resources.pci.func);
321 298 for (i = 0; i < 8; i++) {
322 299 if (a->resources.pci.bar[i]) {
323   - len +=
324   - sprintf(page + len,
  300 + seq_printf(m,
325 301 "Mem / I/O %d : 0x%x / mapped : 0x%lx",
326 302 i, a->resources.pci.bar[i],
327 303 (unsigned long) a->resources.
328 304 pci.addr[i]);
329 305 if (a->resources.pci.length[i]) {
330   - len +=
331   - sprintf(page + len,
  306 + seq_printf(m,
332 307 " / length : %d",
333 308 a->resources.pci.
334 309 length[i]);
335 310 }
336   - len += sprintf(page + len, "\n");
  311 + seq_putc(m, '\n');
337 312 }
338 313 }
339 314 }
340 315  
341 316  
... ... @@ -353,16 +328,25 @@
353 328 } else {
354 329 p = "ready";
355 330 }
356   - len += sprintf(page + len, "State : %s\n", p);
  331 + seq_printf(m, "State : %s\n", p);
357 332  
358   - if (off + count >= len)
359   - *eof = 1;
360   - if (len < off)
361   - return 0;
362   - *start = page + off;
363   - return ((count < len - off) ? count : len - off);
  333 + return 0;
364 334 }
365 335  
  336 +static int info_proc_open(struct inode *inode, struct file *file)
  337 +{
  338 + return single_open(file, info_proc_show, PDE(inode)->data);
  339 +}
  340 +
  341 +static const struct file_operations info_proc_fops = {
  342 + .owner = THIS_MODULE,
  343 + .open = info_proc_open,
  344 + .read = seq_read,
  345 + .llseek = seq_lseek,
  346 + .release = single_release,
  347 + .write = info_proc_write,
  348 +};
  349 +
366 350 /*
367 351 ** adapter proc init/de-init
368 352 */
369 353  
370 354  
371 355  
372 356  
... ... @@ -380,28 +364,20 @@
380 364 return (0);
381 365 a->proc_adapter_dir = (void *) de;
382 366  
383   - if (!(pe =
384   - create_proc_entry(info_proc_name, S_IFREG | S_IRUGO | S_IWUSR, de)))
  367 + pe = proc_create_data(info_proc_name, S_IRUGO | S_IWUSR, de,
  368 + &info_proc_fops, a);
  369 + if (!pe)
385 370 return (0);
386 371 a->proc_info = (void *) pe;
387   - pe->write_proc = info_write;
388   - pe->read_proc = info_read;
389   - pe->data = a;
390 372  
391   - if ((pe = create_proc_entry(grp_opt_proc_name,
392   - S_IFREG | S_IRUGO | S_IWUSR, de))) {
  373 + pe = proc_create_data(grp_opt_proc_name, S_IRUGO | S_IWUSR, de,
  374 + &grp_opt_proc_fops, a);
  375 + if (pe)
393 376 a->proc_grp_opt = (void *) pe;
394   - pe->write_proc = write_grp_opt;
395   - pe->read_proc = read_grp_opt;
396   - pe->data = a;
397   - }
398   - if ((pe = create_proc_entry(d_l1_down_proc_name,
399   - S_IFREG | S_IRUGO | S_IWUSR, de))) {
  377 + pe = proc_create_data(d_l1_down_proc_name, S_IRUGO | S_IWUSR, de,
  378 + &d_l1_down_proc_fops, a);
  379 + if (pe)
400 380 a->proc_d_l1_down = (void *) pe;
401   - pe->write_proc = write_d_l1_down;
402   - pe->read_proc = read_d_l1_down;
403   - pe->data = a;
404   - }
405 381  
406 382 DBG_TRC(("proc entry %s created", tmp));
407 383  
drivers/isdn/hysdn/hycapi.c
... ... @@ -11,6 +11,8 @@
11 11 */
12 12  
13 13 #include <linux/module.h>
  14 +#include <linux/proc_fs.h>
  15 +#include <linux/seq_file.h>
14 16 #include <linux/signal.h>
15 17 #include <linux/kernel.h>
16 18 #include <linux/skbuff.h>
17 19  
18 20  
19 21  
... ... @@ -432,26 +434,16 @@
432 434 return retval;
433 435 }
434 436  
435   -/*********************************************************************
436   -hycapi_read_proc
437   -
438   -Informations provided in the /proc/capi-entries.
439   -
440   -*********************************************************************/
441   -
442   -static int hycapi_read_proc(char *page, char **start, off_t off,
443   - int count, int *eof, struct capi_ctr *ctrl)
  437 +static int hycapi_proc_show(struct seq_file *m, void *v)
444 438 {
  439 + struct capi_ctr *ctrl = m->private;
445 440 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
446 441 hysdn_card *card = cinfo->card;
447   - int len = 0;
448 442 char *s;
449   -#ifdef HYCAPI_PRINTFNAMES
450   - printk(KERN_NOTICE "hycapi_read_proc\n");
451   -#endif
452   - len += sprintf(page+len, "%-16s %s\n", "name", cinfo->cardname);
453   - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->iobase);
454   - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
  443 +
  444 + seq_printf(m, "%-16s %s\n", "name", cinfo->cardname);
  445 + seq_printf(m, "%-16s 0x%x\n", "io", card->iobase);
  446 + seq_printf(m, "%-16s %d\n", "irq", card->irq);
455 447  
456 448 switch (card->brdtype) {
457 449 case BD_PCCARD: s = "HYSDN Hycard"; break;
458 450  
459 451  
460 452  
461 453  
462 454  
463 455  
... ... @@ -461,24 +453,32 @@
461 453 case BD_PLEXUS: s = "HYSDN Plexus30"; break;
462 454 default: s = "???"; break;
463 455 }
464   - len += sprintf(page+len, "%-16s %s\n", "type", s);
  456 + seq_printf(m, "%-16s %s\n", "type", s);
465 457 if ((s = cinfo->version[VER_DRIVER]) != NULL)
466   - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
  458 + seq_printf(m, "%-16s %s\n", "ver_driver", s);
467 459 if ((s = cinfo->version[VER_CARDTYPE]) != NULL)
468   - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
  460 + seq_printf(m, "%-16s %s\n", "ver_cardtype", s);
469 461 if ((s = cinfo->version[VER_SERIAL]) != NULL)
470   - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
  462 + seq_printf(m, "%-16s %s\n", "ver_serial", s);
471 463  
472   - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
  464 + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname);
473 465  
474   - if (off+count >= len)
475   - *eof = 1;
476   - if (len < off)
477   - return 0;
478   - *start = page + off;
479   - return ((count < len-off) ? count : len-off);
  466 + return 0;
480 467 }
481 468  
  469 +static int hycapi_proc_open(struct inode *inode, struct file *file)
  470 +{
  471 + return single_open(file, hycapi_proc_show, PDE(inode)->data);
  472 +}
  473 +
  474 +static const struct file_operations hycapi_proc_fops = {
  475 + .owner = THIS_MODULE,
  476 + .open = hycapi_proc_open,
  477 + .read = seq_read,
  478 + .llseek = seq_lseek,
  479 + .release = single_release,
  480 +};
  481 +
482 482 /**************************************************************
483 483 hycapi_load_firmware
484 484  
... ... @@ -774,7 +774,7 @@
774 774 ctrl->load_firmware = hycapi_load_firmware;
775 775 ctrl->reset_ctr = hycapi_reset_ctr;
776 776 ctrl->procinfo = hycapi_procinfo;
777   - ctrl->ctr_read_proc = hycapi_read_proc;
  777 + ctrl->proc_fops = &hycapi_proc_fops;
778 778 strcpy(ctrl->name, cinfo->cardname);
779 779 ctrl->owner = THIS_MODULE;
780 780  
include/linux/isdn/capilli.h
... ... @@ -50,8 +50,7 @@
50 50 u16 (*send_message)(struct capi_ctr *, struct sk_buff *skb);
51 51  
52 52 char *(*procinfo)(struct capi_ctr *);
53   - int (*ctr_read_proc)(char *page, char **start, off_t off,
54   - int count, int *eof, struct capi_ctr *card);
  53 + const struct file_operations *proc_fops;
55 54  
56 55 /* filled in before calling ready callback */
57 56 u8 manu[CAPI_MANUFACTURER_LEN]; /* CAPI_GET_MANUFACTURER */
net/bluetooth/cmtp/capi.c
... ... @@ -21,7 +21,8 @@
21 21 */
22 22  
23 23 #include <linux/module.h>
24   -
  24 +#include <linux/proc_fs.h>
  25 +#include <linux/seq_file.h>
25 26 #include <linux/types.h>
26 27 #include <linux/errno.h>
27 28 #include <linux/kernel.h>
28 29  
29 30  
30 31  
31 32  
32 33  
33 34  
34 35  
... ... @@ -516,33 +517,37 @@
516 517 return "CAPI Message Transport Protocol";
517 518 }
518 519  
519   -static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
  520 +static int cmtp_proc_show(struct seq_file *m, void *v)
520 521 {
  522 + struct capi_ctr *ctrl = m->private;
521 523 struct cmtp_session *session = ctrl->driverdata;
522 524 struct cmtp_application *app;
523 525 struct list_head *p, *n;
524   - int len = 0;
525 526  
526   - len += sprintf(page + len, "%s\n\n", cmtp_procinfo(ctrl));
527   - len += sprintf(page + len, "addr %s\n", session->name);
528   - len += sprintf(page + len, "ctrl %d\n", session->num);
  527 + seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl));
  528 + seq_printf(m, "addr %s\n", session->name);
  529 + seq_printf(m, "ctrl %d\n", session->num);
529 530  
530 531 list_for_each_safe(p, n, &session->applications) {
531 532 app = list_entry(p, struct cmtp_application, list);
532   - len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping);
  533 + seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping);
533 534 }
534 535  
535   - if (off + count >= len)
536   - *eof = 1;
  536 + return 0;
  537 +}
537 538  
538   - if (len < off)
539   - return 0;
540   -
541   - *start = page + off;
542   -
543   - return ((count < len - off) ? count : len - off);
  539 +static int cmtp_proc_open(struct inode *inode, struct file *file)
  540 +{
  541 + return single_open(file, cmtp_proc_show, PDE(inode)->data);
544 542 }
545 543  
  544 +static const struct file_operations cmtp_proc_fops = {
  545 + .owner = THIS_MODULE,
  546 + .open = cmtp_proc_open,
  547 + .read = seq_read,
  548 + .llseek = seq_lseek,
  549 + .release = single_release,
  550 +};
546 551  
547 552 int cmtp_attach_device(struct cmtp_session *session)
548 553 {
... ... @@ -582,7 +587,7 @@
582 587 session->ctrl.send_message = cmtp_send_message;
583 588  
584 589 session->ctrl.procinfo = cmtp_procinfo;
585   - session->ctrl.ctr_read_proc = cmtp_ctr_read_proc;
  590 + session->ctrl.proc_fops = &cmtp_proc_fops;
586 591  
587 592 if (attach_capi_ctr(&session->ctrl) < 0) {
588 593 BT_ERR("Can't attach new controller");