Merge branch 'core-printk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / s390 / cio / chsc_sch.c
1 /*
2  * Driver for s390 chsc subchannels
3  *
4  * Copyright IBM Corp. 2008, 2011
5  *
6  * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
7  *
8  */
9
10 #include <linux/slab.h>
11 #include <linux/compat.h>
12 #include <linux/device.h>
13 #include <linux/module.h>
14 #include <linux/uaccess.h>
15 #include <linux/miscdevice.h>
16 #include <linux/kernel_stat.h>
17
18 #include <asm/compat.h>
19 #include <asm/cio.h>
20 #include <asm/chsc.h>
21 #include <asm/isc.h>
22
23 #include "cio.h"
24 #include "cio_debug.h"
25 #include "css.h"
26 #include "chsc_sch.h"
27 #include "ioasm.h"
28
29 static debug_info_t *chsc_debug_msg_id;
30 static debug_info_t *chsc_debug_log_id;
31
32 static struct chsc_request *on_close_request;
33 static struct chsc_async_area *on_close_chsc_area;
34 static DEFINE_MUTEX(on_close_mutex);
35
36 #define CHSC_MSG(imp, args...) do {                                     \
37                 debug_sprintf_event(chsc_debug_msg_id, imp , ##args);   \
38         } while (0)
39
40 #define CHSC_LOG(imp, txt) do {                                 \
41                 debug_text_event(chsc_debug_log_id, imp , txt); \
42         } while (0)
43
44 static void CHSC_LOG_HEX(int level, void *data, int length)
45 {
46         while (length > 0) {
47                 debug_event(chsc_debug_log_id, level, data, length);
48                 length -= chsc_debug_log_id->buf_size;
49                 data += chsc_debug_log_id->buf_size;
50         }
51 }
52
53 MODULE_AUTHOR("IBM Corporation");
54 MODULE_DESCRIPTION("driver for s390 chsc subchannels");
55 MODULE_LICENSE("GPL");
56
57 static void chsc_subchannel_irq(struct subchannel *sch)
58 {
59         struct chsc_private *private = dev_get_drvdata(&sch->dev);
60         struct chsc_request *request = private->request;
61         struct irb *irb = (struct irb *)&S390_lowcore.irb;
62
63         CHSC_LOG(4, "irb");
64         CHSC_LOG_HEX(4, irb, sizeof(*irb));
65         inc_irq_stat(IRQIO_CSC);
66
67         /* Copy irb to provided request and set done. */
68         if (!request) {
69                 CHSC_MSG(0, "Interrupt on sch 0.%x.%04x with no request\n",
70                          sch->schid.ssid, sch->schid.sch_no);
71                 return;
72         }
73         private->request = NULL;
74         memcpy(&request->irb, irb, sizeof(*irb));
75         cio_update_schib(sch);
76         complete(&request->completion);
77         put_device(&sch->dev);
78 }
79
80 static int chsc_subchannel_probe(struct subchannel *sch)
81 {
82         struct chsc_private *private;
83         int ret;
84
85         CHSC_MSG(6, "Detected chsc subchannel 0.%x.%04x\n",
86                  sch->schid.ssid, sch->schid.sch_no);
87         sch->isc = CHSC_SCH_ISC;
88         private = kzalloc(sizeof(*private), GFP_KERNEL);
89         if (!private)
90                 return -ENOMEM;
91         dev_set_drvdata(&sch->dev, private);
92         ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
93         if (ret) {
94                 CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n",
95                          sch->schid.ssid, sch->schid.sch_no, ret);
96                 dev_set_drvdata(&sch->dev, NULL);
97                 kfree(private);
98         } else {
99                 if (dev_get_uevent_suppress(&sch->dev)) {
100                         dev_set_uevent_suppress(&sch->dev, 0);
101                         kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
102                 }
103         }
104         return ret;
105 }
106
107 static int chsc_subchannel_remove(struct subchannel *sch)
108 {
109         struct chsc_private *private;
110
111         cio_disable_subchannel(sch);
112         private = dev_get_drvdata(&sch->dev);
113         dev_set_drvdata(&sch->dev, NULL);
114         if (private->request) {
115                 complete(&private->request->completion);
116                 put_device(&sch->dev);
117         }
118         kfree(private);
119         return 0;
120 }
121
122 static void chsc_subchannel_shutdown(struct subchannel *sch)
123 {
124         cio_disable_subchannel(sch);
125 }
126
127 static int chsc_subchannel_prepare(struct subchannel *sch)
128 {
129         int cc;
130         struct schib schib;
131         /*
132          * Don't allow suspend while the subchannel is not idle
133          * since we don't have a way to clear the subchannel and
134          * cannot disable it with a request running.
135          */
136         cc = stsch_err(sch->schid, &schib);
137         if (!cc && scsw_stctl(&schib.scsw))
138                 return -EAGAIN;
139         return 0;
140 }
141
142 static int chsc_subchannel_freeze(struct subchannel *sch)
143 {
144         return cio_disable_subchannel(sch);
145 }
146
147 static int chsc_subchannel_restore(struct subchannel *sch)
148 {
149         return cio_enable_subchannel(sch, (u32)(unsigned long)sch);
150 }
151
152 static struct css_device_id chsc_subchannel_ids[] = {
153         { .match_flags = 0x1, .type =SUBCHANNEL_TYPE_CHSC, },
154         { /* end of list */ },
155 };
156 MODULE_DEVICE_TABLE(css, chsc_subchannel_ids);
157
158 static struct css_driver chsc_subchannel_driver = {
159         .drv = {
160                 .owner = THIS_MODULE,
161                 .name = "chsc_subchannel",
162         },
163         .subchannel_type = chsc_subchannel_ids,
164         .irq = chsc_subchannel_irq,
165         .probe = chsc_subchannel_probe,
166         .remove = chsc_subchannel_remove,
167         .shutdown = chsc_subchannel_shutdown,
168         .prepare = chsc_subchannel_prepare,
169         .freeze = chsc_subchannel_freeze,
170         .thaw = chsc_subchannel_restore,
171         .restore = chsc_subchannel_restore,
172 };
173
174 static int __init chsc_init_dbfs(void)
175 {
176         chsc_debug_msg_id = debug_register("chsc_msg", 16, 1,
177                                            16 * sizeof(long));
178         if (!chsc_debug_msg_id)
179                 goto out;
180         debug_register_view(chsc_debug_msg_id, &debug_sprintf_view);
181         debug_set_level(chsc_debug_msg_id, 2);
182         chsc_debug_log_id = debug_register("chsc_log", 16, 1, 16);
183         if (!chsc_debug_log_id)
184                 goto out;
185         debug_register_view(chsc_debug_log_id, &debug_hex_ascii_view);
186         debug_set_level(chsc_debug_log_id, 2);
187         return 0;
188 out:
189         if (chsc_debug_msg_id)
190                 debug_unregister(chsc_debug_msg_id);
191         return -ENOMEM;
192 }
193
194 static void chsc_remove_dbfs(void)
195 {
196         debug_unregister(chsc_debug_log_id);
197         debug_unregister(chsc_debug_msg_id);
198 }
199
200 static int __init chsc_init_sch_driver(void)
201 {
202         return css_driver_register(&chsc_subchannel_driver);
203 }
204
205 static void chsc_cleanup_sch_driver(void)
206 {
207         css_driver_unregister(&chsc_subchannel_driver);
208 }
209
210 static DEFINE_SPINLOCK(chsc_lock);
211
212 static int chsc_subchannel_match_next_free(struct device *dev, void *data)
213 {
214         struct subchannel *sch = to_subchannel(dev);
215
216         return sch->schib.pmcw.ena && !scsw_fctl(&sch->schib.scsw);
217 }
218
219 static struct subchannel *chsc_get_next_subchannel(struct subchannel *sch)
220 {
221         struct device *dev;
222
223         dev = driver_find_device(&chsc_subchannel_driver.drv,
224                                  sch ? &sch->dev : NULL, NULL,
225                                  chsc_subchannel_match_next_free);
226         return dev ? to_subchannel(dev) : NULL;
227 }
228
229 /**
230  * chsc_async() - try to start a chsc request asynchronously
231  * @chsc_area: request to be started
232  * @request: request structure to associate
233  *
234  * Tries to start a chsc request on one of the existing chsc subchannels.
235  * Returns:
236  *  %0 if the request was performed synchronously
237  *  %-EINPROGRESS if the request was successfully started
238  *  %-EBUSY if all chsc subchannels are busy
239  *  %-ENODEV if no chsc subchannels are available
240  * Context:
241  *  interrupts disabled, chsc_lock held
242  */
243 static int chsc_async(struct chsc_async_area *chsc_area,
244                       struct chsc_request *request)
245 {
246         int cc;
247         struct chsc_private *private;
248         struct subchannel *sch = NULL;
249         int ret = -ENODEV;
250         char dbf[10];
251
252         chsc_area->header.key = PAGE_DEFAULT_KEY >> 4;
253         while ((sch = chsc_get_next_subchannel(sch))) {
254                 spin_lock(sch->lock);
255                 private = dev_get_drvdata(&sch->dev);
256                 if (private->request) {
257                         spin_unlock(sch->lock);
258                         ret = -EBUSY;
259                         continue;
260                 }
261                 chsc_area->header.sid = sch->schid;
262                 CHSC_LOG(2, "schid");
263                 CHSC_LOG_HEX(2, &sch->schid, sizeof(sch->schid));
264                 cc = chsc(chsc_area);
265                 snprintf(dbf, sizeof(dbf), "cc:%d", cc);
266                 CHSC_LOG(2, dbf);
267                 switch (cc) {
268                 case 0:
269                         ret = 0;
270                         break;
271                 case 1:
272                         sch->schib.scsw.cmd.fctl |= SCSW_FCTL_START_FUNC;
273                         ret = -EINPROGRESS;
274                         private->request = request;
275                         break;
276                 case 2:
277                         ret = -EBUSY;
278                         break;
279                 default:
280                         ret = -ENODEV;
281                 }
282                 spin_unlock(sch->lock);
283                 CHSC_MSG(2, "chsc on 0.%x.%04x returned cc=%d\n",
284                          sch->schid.ssid, sch->schid.sch_no, cc);
285                 if (ret == -EINPROGRESS)
286                         return -EINPROGRESS;
287                 put_device(&sch->dev);
288                 if (ret == 0)
289                         return 0;
290         }
291         return ret;
292 }
293
294 static void chsc_log_command(void *chsc_area)
295 {
296         char dbf[10];
297
298         snprintf(dbf, sizeof(dbf), "CHSC:%x", ((uint16_t *)chsc_area)[1]);
299         CHSC_LOG(0, dbf);
300         CHSC_LOG_HEX(0, chsc_area, 32);
301 }
302
303 static int chsc_examine_irb(struct chsc_request *request)
304 {
305         int backed_up;
306
307         if (!(scsw_stctl(&request->irb.scsw) & SCSW_STCTL_STATUS_PEND))
308                 return -EIO;
309         backed_up = scsw_cstat(&request->irb.scsw) & SCHN_STAT_CHAIN_CHECK;
310         request->irb.scsw.cmd.cstat &= ~SCHN_STAT_CHAIN_CHECK;
311         if (scsw_cstat(&request->irb.scsw) == 0)
312                 return 0;
313         if (!backed_up)
314                 return 0;
315         if (scsw_cstat(&request->irb.scsw) & SCHN_STAT_PROG_CHECK)
316                 return -EIO;
317         if (scsw_cstat(&request->irb.scsw) & SCHN_STAT_PROT_CHECK)
318                 return -EPERM;
319         if (scsw_cstat(&request->irb.scsw) & SCHN_STAT_CHN_DATA_CHK)
320                 return -EAGAIN;
321         if (scsw_cstat(&request->irb.scsw) & SCHN_STAT_CHN_CTRL_CHK)
322                 return -EAGAIN;
323         return -EIO;
324 }
325
326 static int chsc_ioctl_start(void __user *user_area)
327 {
328         struct chsc_request *request;
329         struct chsc_async_area *chsc_area;
330         int ret;
331         char dbf[10];
332
333         if (!css_general_characteristics.dynio)
334                 /* It makes no sense to try. */
335                 return -EOPNOTSUPP;
336         chsc_area = (void *)get_zeroed_page(GFP_DMA | GFP_KERNEL);
337         if (!chsc_area)
338                 return -ENOMEM;
339         request = kzalloc(sizeof(*request), GFP_KERNEL);
340         if (!request) {
341                 ret = -ENOMEM;
342                 goto out_free;
343         }
344         init_completion(&request->completion);
345         if (copy_from_user(chsc_area, user_area, PAGE_SIZE)) {
346                 ret = -EFAULT;
347                 goto out_free;
348         }
349         chsc_log_command(chsc_area);
350         spin_lock_irq(&chsc_lock);
351         ret = chsc_async(chsc_area, request);
352         spin_unlock_irq(&chsc_lock);
353         if (ret == -EINPROGRESS) {
354                 wait_for_completion(&request->completion);
355                 ret = chsc_examine_irb(request);
356         }
357         /* copy area back to user */
358         if (!ret)
359                 if (copy_to_user(user_area, chsc_area, PAGE_SIZE))
360                         ret = -EFAULT;
361 out_free:
362         snprintf(dbf, sizeof(dbf), "ret:%d", ret);
363         CHSC_LOG(0, dbf);
364         kfree(request);
365         free_page((unsigned long)chsc_area);
366         return ret;
367 }
368
369 static int chsc_ioctl_on_close_set(void __user *user_area)
370 {
371         char dbf[13];
372         int ret;
373
374         mutex_lock(&on_close_mutex);
375         if (on_close_chsc_area) {
376                 ret = -EBUSY;
377                 goto out_unlock;
378         }
379         on_close_request = kzalloc(sizeof(*on_close_request), GFP_KERNEL);
380         if (!on_close_request) {
381                 ret = -ENOMEM;
382                 goto out_unlock;
383         }
384         on_close_chsc_area = (void *)get_zeroed_page(GFP_DMA | GFP_KERNEL);
385         if (!on_close_chsc_area) {
386                 ret = -ENOMEM;
387                 goto out_free_request;
388         }
389         if (copy_from_user(on_close_chsc_area, user_area, PAGE_SIZE)) {
390                 ret = -EFAULT;
391                 goto out_free_chsc;
392         }
393         ret = 0;
394         goto out_unlock;
395
396 out_free_chsc:
397         free_page((unsigned long)on_close_chsc_area);
398         on_close_chsc_area = NULL;
399 out_free_request:
400         kfree(on_close_request);
401         on_close_request = NULL;
402 out_unlock:
403         mutex_unlock(&on_close_mutex);
404         snprintf(dbf, sizeof(dbf), "ocsret:%d", ret);
405         CHSC_LOG(0, dbf);
406         return ret;
407 }
408
409 static int chsc_ioctl_on_close_remove(void)
410 {
411         char dbf[13];
412         int ret;
413
414         mutex_lock(&on_close_mutex);
415         if (!on_close_chsc_area) {
416                 ret = -ENOENT;
417                 goto out_unlock;
418         }
419         free_page((unsigned long)on_close_chsc_area);
420         on_close_chsc_area = NULL;
421         kfree(on_close_request);
422         on_close_request = NULL;
423         ret = 0;
424 out_unlock:
425         mutex_unlock(&on_close_mutex);
426         snprintf(dbf, sizeof(dbf), "ocrret:%d", ret);
427         CHSC_LOG(0, dbf);
428         return ret;
429 }
430
431 static int chsc_ioctl_start_sync(void __user *user_area)
432 {
433         struct chsc_sync_area *chsc_area;
434         int ret, ccode;
435
436         chsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
437         if (!chsc_area)
438                 return -ENOMEM;
439         if (copy_from_user(chsc_area, user_area, PAGE_SIZE)) {
440                 ret = -EFAULT;
441                 goto out_free;
442         }
443         if (chsc_area->header.code & 0x4000) {
444                 ret = -EINVAL;
445                 goto out_free;
446         }
447         chsc_log_command(chsc_area);
448         ccode = chsc(chsc_area);
449         if (ccode != 0) {
450                 ret = -EIO;
451                 goto out_free;
452         }
453         if (copy_to_user(user_area, chsc_area, PAGE_SIZE))
454                 ret = -EFAULT;
455         else
456                 ret = 0;
457 out_free:
458         free_page((unsigned long)chsc_area);
459         return ret;
460 }
461
462 static int chsc_ioctl_info_channel_path(void __user *user_cd)
463 {
464         struct chsc_chp_cd *cd;
465         int ret, ccode;
466         struct {
467                 struct chsc_header request;
468                 u32 : 2;
469                 u32 m : 1;
470                 u32 : 1;
471                 u32 fmt1 : 4;
472                 u32 cssid : 8;
473                 u32 : 8;
474                 u32 first_chpid : 8;
475                 u32 : 24;
476                 u32 last_chpid : 8;
477                 u32 : 32;
478                 struct chsc_header response;
479                 u8 data[PAGE_SIZE - 20];
480         } __attribute__ ((packed)) *scpcd_area;
481
482         scpcd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
483         if (!scpcd_area)
484                 return -ENOMEM;
485         cd = kzalloc(sizeof(*cd), GFP_KERNEL);
486         if (!cd) {
487                 ret = -ENOMEM;
488                 goto out_free;
489         }
490         if (copy_from_user(cd, user_cd, sizeof(*cd))) {
491                 ret = -EFAULT;
492                 goto out_free;
493         }
494         scpcd_area->request.length = 0x0010;
495         scpcd_area->request.code = 0x0028;
496         scpcd_area->m = cd->m;
497         scpcd_area->fmt1 = cd->fmt;
498         scpcd_area->cssid = cd->chpid.cssid;
499         scpcd_area->first_chpid = cd->chpid.id;
500         scpcd_area->last_chpid = cd->chpid.id;
501
502         ccode = chsc(scpcd_area);
503         if (ccode != 0) {
504                 ret = -EIO;
505                 goto out_free;
506         }
507         if (scpcd_area->response.code != 0x0001) {
508                 ret = -EIO;
509                 CHSC_MSG(0, "scpcd: response code=%x\n",
510                          scpcd_area->response.code);
511                 goto out_free;
512         }
513         memcpy(&cd->cpcb, &scpcd_area->response, scpcd_area->response.length);
514         if (copy_to_user(user_cd, cd, sizeof(*cd)))
515                 ret = -EFAULT;
516         else
517                 ret = 0;
518 out_free:
519         kfree(cd);
520         free_page((unsigned long)scpcd_area);
521         return ret;
522 }
523
524 static int chsc_ioctl_info_cu(void __user *user_cd)
525 {
526         struct chsc_cu_cd *cd;
527         int ret, ccode;
528         struct {
529                 struct chsc_header request;
530                 u32 : 2;
531                 u32 m : 1;
532                 u32 : 1;
533                 u32 fmt1 : 4;
534                 u32 cssid : 8;
535                 u32 : 8;
536                 u32 first_cun : 8;
537                 u32 : 24;
538                 u32 last_cun : 8;
539                 u32 : 32;
540                 struct chsc_header response;
541                 u8 data[PAGE_SIZE - 20];
542         } __attribute__ ((packed)) *scucd_area;
543
544         scucd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
545         if (!scucd_area)
546                 return -ENOMEM;
547         cd = kzalloc(sizeof(*cd), GFP_KERNEL);
548         if (!cd) {
549                 ret = -ENOMEM;
550                 goto out_free;
551         }
552         if (copy_from_user(cd, user_cd, sizeof(*cd))) {
553                 ret = -EFAULT;
554                 goto out_free;
555         }
556         scucd_area->request.length = 0x0010;
557         scucd_area->request.code = 0x0028;
558         scucd_area->m = cd->m;
559         scucd_area->fmt1 = cd->fmt;
560         scucd_area->cssid = cd->cssid;
561         scucd_area->first_cun = cd->cun;
562         scucd_area->last_cun = cd->cun;
563
564         ccode = chsc(scucd_area);
565         if (ccode != 0) {
566                 ret = -EIO;
567                 goto out_free;
568         }
569         if (scucd_area->response.code != 0x0001) {
570                 ret = -EIO;
571                 CHSC_MSG(0, "scucd: response code=%x\n",
572                          scucd_area->response.code);
573                 goto out_free;
574         }
575         memcpy(&cd->cucb, &scucd_area->response, scucd_area->response.length);
576         if (copy_to_user(user_cd, cd, sizeof(*cd)))
577                 ret = -EFAULT;
578         else
579                 ret = 0;
580 out_free:
581         kfree(cd);
582         free_page((unsigned long)scucd_area);
583         return ret;
584 }
585
586 static int chsc_ioctl_info_sch_cu(void __user *user_cud)
587 {
588         struct chsc_sch_cud *cud;
589         int ret, ccode;
590         struct {
591                 struct chsc_header request;
592                 u32 : 2;
593                 u32 m : 1;
594                 u32 : 5;
595                 u32 fmt1 : 4;
596                 u32 : 2;
597                 u32 ssid : 2;
598                 u32 first_sch : 16;
599                 u32 : 8;
600                 u32 cssid : 8;
601                 u32 last_sch : 16;
602                 u32 : 32;
603                 struct chsc_header response;
604                 u8 data[PAGE_SIZE - 20];
605         } __attribute__ ((packed)) *sscud_area;
606
607         sscud_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
608         if (!sscud_area)
609                 return -ENOMEM;
610         cud = kzalloc(sizeof(*cud), GFP_KERNEL);
611         if (!cud) {
612                 ret = -ENOMEM;
613                 goto out_free;
614         }
615         if (copy_from_user(cud, user_cud, sizeof(*cud))) {
616                 ret = -EFAULT;
617                 goto out_free;
618         }
619         sscud_area->request.length = 0x0010;
620         sscud_area->request.code = 0x0006;
621         sscud_area->m = cud->schid.m;
622         sscud_area->fmt1 = cud->fmt;
623         sscud_area->ssid = cud->schid.ssid;
624         sscud_area->first_sch = cud->schid.sch_no;
625         sscud_area->cssid = cud->schid.cssid;
626         sscud_area->last_sch = cud->schid.sch_no;
627
628         ccode = chsc(sscud_area);
629         if (ccode != 0) {
630                 ret = -EIO;
631                 goto out_free;
632         }
633         if (sscud_area->response.code != 0x0001) {
634                 ret = -EIO;
635                 CHSC_MSG(0, "sscud: response code=%x\n",
636                          sscud_area->response.code);
637                 goto out_free;
638         }
639         memcpy(&cud->scub, &sscud_area->response, sscud_area->response.length);
640         if (copy_to_user(user_cud, cud, sizeof(*cud)))
641                 ret = -EFAULT;
642         else
643                 ret = 0;
644 out_free:
645         kfree(cud);
646         free_page((unsigned long)sscud_area);
647         return ret;
648 }
649
650 static int chsc_ioctl_conf_info(void __user *user_ci)
651 {
652         struct chsc_conf_info *ci;
653         int ret, ccode;
654         struct {
655                 struct chsc_header request;
656                 u32 : 2;
657                 u32 m : 1;
658                 u32 : 1;
659                 u32 fmt1 : 4;
660                 u32 cssid : 8;
661                 u32 : 6;
662                 u32 ssid : 2;
663                 u32 : 8;
664                 u64 : 64;
665                 struct chsc_header response;
666                 u8 data[PAGE_SIZE - 20];
667         } __attribute__ ((packed)) *sci_area;
668
669         sci_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
670         if (!sci_area)
671                 return -ENOMEM;
672         ci = kzalloc(sizeof(*ci), GFP_KERNEL);
673         if (!ci) {
674                 ret = -ENOMEM;
675                 goto out_free;
676         }
677         if (copy_from_user(ci, user_ci, sizeof(*ci))) {
678                 ret = -EFAULT;
679                 goto out_free;
680         }
681         sci_area->request.length = 0x0010;
682         sci_area->request.code = 0x0012;
683         sci_area->m = ci->id.m;
684         sci_area->fmt1 = ci->fmt;
685         sci_area->cssid = ci->id.cssid;
686         sci_area->ssid = ci->id.ssid;
687
688         ccode = chsc(sci_area);
689         if (ccode != 0) {
690                 ret = -EIO;
691                 goto out_free;
692         }
693         if (sci_area->response.code != 0x0001) {
694                 ret = -EIO;
695                 CHSC_MSG(0, "sci: response code=%x\n",
696                          sci_area->response.code);
697                 goto out_free;
698         }
699         memcpy(&ci->scid, &sci_area->response, sci_area->response.length);
700         if (copy_to_user(user_ci, ci, sizeof(*ci)))
701                 ret = -EFAULT;
702         else
703                 ret = 0;
704 out_free:
705         kfree(ci);
706         free_page((unsigned long)sci_area);
707         return ret;
708 }
709
710 static int chsc_ioctl_conf_comp_list(void __user *user_ccl)
711 {
712         struct chsc_comp_list *ccl;
713         int ret, ccode;
714         struct {
715                 struct chsc_header request;
716                 u32 ctype : 8;
717                 u32 : 4;
718                 u32 fmt : 4;
719                 u32 : 16;
720                 u64 : 64;
721                 u32 list_parm[2];
722                 u64 : 64;
723                 struct chsc_header response;
724                 u8 data[PAGE_SIZE - 36];
725         } __attribute__ ((packed)) *sccl_area;
726         struct {
727                 u32 m : 1;
728                 u32 : 31;
729                 u32 cssid : 8;
730                 u32 : 16;
731                 u32 chpid : 8;
732         } __attribute__ ((packed)) *chpid_parm;
733         struct {
734                 u32 f_cssid : 8;
735                 u32 l_cssid : 8;
736                 u32 : 16;
737                 u32 res;
738         } __attribute__ ((packed)) *cssids_parm;
739
740         sccl_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
741         if (!sccl_area)
742                 return -ENOMEM;
743         ccl = kzalloc(sizeof(*ccl), GFP_KERNEL);
744         if (!ccl) {
745                 ret = -ENOMEM;
746                 goto out_free;
747         }
748         if (copy_from_user(ccl, user_ccl, sizeof(*ccl))) {
749                 ret = -EFAULT;
750                 goto out_free;
751         }
752         sccl_area->request.length = 0x0020;
753         sccl_area->request.code = 0x0030;
754         sccl_area->fmt = ccl->req.fmt;
755         sccl_area->ctype = ccl->req.ctype;
756         switch (sccl_area->ctype) {
757         case CCL_CU_ON_CHP:
758         case CCL_IOP_CHP:
759                 chpid_parm = (void *)&sccl_area->list_parm;
760                 chpid_parm->m = ccl->req.chpid.m;
761                 chpid_parm->cssid = ccl->req.chpid.chp.cssid;
762                 chpid_parm->chpid = ccl->req.chpid.chp.id;
763                 break;
764         case CCL_CSS_IMG:
765         case CCL_CSS_IMG_CONF_CHAR:
766                 cssids_parm = (void *)&sccl_area->list_parm;
767                 cssids_parm->f_cssid = ccl->req.cssids.f_cssid;
768                 cssids_parm->l_cssid = ccl->req.cssids.l_cssid;
769                 break;
770         }
771         ccode = chsc(sccl_area);
772         if (ccode != 0) {
773                 ret = -EIO;
774                 goto out_free;
775         }
776         if (sccl_area->response.code != 0x0001) {
777                 ret = -EIO;
778                 CHSC_MSG(0, "sccl: response code=%x\n",
779                          sccl_area->response.code);
780                 goto out_free;
781         }
782         memcpy(&ccl->sccl, &sccl_area->response, sccl_area->response.length);
783         if (copy_to_user(user_ccl, ccl, sizeof(*ccl)))
784                 ret = -EFAULT;
785         else
786                 ret = 0;
787 out_free:
788         kfree(ccl);
789         free_page((unsigned long)sccl_area);
790         return ret;
791 }
792
793 static int chsc_ioctl_chpd(void __user *user_chpd)
794 {
795         struct chsc_scpd *scpd_area;
796         struct chsc_cpd_info *chpd;
797         int ret;
798
799         chpd = kzalloc(sizeof(*chpd), GFP_KERNEL);
800         scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
801         if (!scpd_area || !chpd) {
802                 ret = -ENOMEM;
803                 goto out_free;
804         }
805         if (copy_from_user(chpd, user_chpd, sizeof(*chpd))) {
806                 ret = -EFAULT;
807                 goto out_free;
808         }
809         ret = chsc_determine_channel_path_desc(chpd->chpid, chpd->fmt,
810                                                chpd->rfmt, chpd->c, chpd->m,
811                                                scpd_area);
812         if (ret)
813                 goto out_free;
814         memcpy(&chpd->chpdb, &scpd_area->response, scpd_area->response.length);
815         if (copy_to_user(user_chpd, chpd, sizeof(*chpd)))
816                 ret = -EFAULT;
817 out_free:
818         kfree(chpd);
819         free_page((unsigned long)scpd_area);
820         return ret;
821 }
822
823 static int chsc_ioctl_dcal(void __user *user_dcal)
824 {
825         struct chsc_dcal *dcal;
826         int ret, ccode;
827         struct {
828                 struct chsc_header request;
829                 u32 atype : 8;
830                 u32 : 4;
831                 u32 fmt : 4;
832                 u32 : 16;
833                 u32 res0[2];
834                 u32 list_parm[2];
835                 u32 res1[2];
836                 struct chsc_header response;
837                 u8 data[PAGE_SIZE - 36];
838         } __attribute__ ((packed)) *sdcal_area;
839
840         sdcal_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
841         if (!sdcal_area)
842                 return -ENOMEM;
843         dcal = kzalloc(sizeof(*dcal), GFP_KERNEL);
844         if (!dcal) {
845                 ret = -ENOMEM;
846                 goto out_free;
847         }
848         if (copy_from_user(dcal, user_dcal, sizeof(*dcal))) {
849                 ret = -EFAULT;
850                 goto out_free;
851         }
852         sdcal_area->request.length = 0x0020;
853         sdcal_area->request.code = 0x0034;
854         sdcal_area->atype = dcal->req.atype;
855         sdcal_area->fmt = dcal->req.fmt;
856         memcpy(&sdcal_area->list_parm, &dcal->req.list_parm,
857                sizeof(sdcal_area->list_parm));
858
859         ccode = chsc(sdcal_area);
860         if (ccode != 0) {
861                 ret = -EIO;
862                 goto out_free;
863         }
864         if (sdcal_area->response.code != 0x0001) {
865                 ret = -EIO;
866                 CHSC_MSG(0, "sdcal: response code=%x\n",
867                          sdcal_area->response.code);
868                 goto out_free;
869         }
870         memcpy(&dcal->sdcal, &sdcal_area->response,
871                sdcal_area->response.length);
872         if (copy_to_user(user_dcal, dcal, sizeof(*dcal)))
873                 ret = -EFAULT;
874         else
875                 ret = 0;
876 out_free:
877         kfree(dcal);
878         free_page((unsigned long)sdcal_area);
879         return ret;
880 }
881
882 static long chsc_ioctl(struct file *filp, unsigned int cmd,
883                        unsigned long arg)
884 {
885         void __user *argp;
886
887         CHSC_MSG(2, "chsc_ioctl called, cmd=%x\n", cmd);
888         if (is_compat_task())
889                 argp = compat_ptr(arg);
890         else
891                 argp = (void __user *)arg;
892         switch (cmd) {
893         case CHSC_START:
894                 return chsc_ioctl_start(argp);
895         case CHSC_START_SYNC:
896                 return chsc_ioctl_start_sync(argp);
897         case CHSC_INFO_CHANNEL_PATH:
898                 return chsc_ioctl_info_channel_path(argp);
899         case CHSC_INFO_CU:
900                 return chsc_ioctl_info_cu(argp);
901         case CHSC_INFO_SCH_CU:
902                 return chsc_ioctl_info_sch_cu(argp);
903         case CHSC_INFO_CI:
904                 return chsc_ioctl_conf_info(argp);
905         case CHSC_INFO_CCL:
906                 return chsc_ioctl_conf_comp_list(argp);
907         case CHSC_INFO_CPD:
908                 return chsc_ioctl_chpd(argp);
909         case CHSC_INFO_DCAL:
910                 return chsc_ioctl_dcal(argp);
911         case CHSC_ON_CLOSE_SET:
912                 return chsc_ioctl_on_close_set(argp);
913         case CHSC_ON_CLOSE_REMOVE:
914                 return chsc_ioctl_on_close_remove();
915         default: /* unknown ioctl number */
916                 return -ENOIOCTLCMD;
917         }
918 }
919
920 static atomic_t chsc_ready_for_use = ATOMIC_INIT(1);
921
922 static int chsc_open(struct inode *inode, struct file *file)
923 {
924         if (!atomic_dec_and_test(&chsc_ready_for_use)) {
925                 atomic_inc(&chsc_ready_for_use);
926                 return -EBUSY;
927         }
928         return nonseekable_open(inode, file);
929 }
930
931 static int chsc_release(struct inode *inode, struct file *filp)
932 {
933         char dbf[13];
934         int ret;
935
936         mutex_lock(&on_close_mutex);
937         if (!on_close_chsc_area)
938                 goto out_unlock;
939         init_completion(&on_close_request->completion);
940         CHSC_LOG(0, "on_close");
941         chsc_log_command(on_close_chsc_area);
942         spin_lock_irq(&chsc_lock);
943         ret = chsc_async(on_close_chsc_area, on_close_request);
944         spin_unlock_irq(&chsc_lock);
945         if (ret == -EINPROGRESS) {
946                 wait_for_completion(&on_close_request->completion);
947                 ret = chsc_examine_irb(on_close_request);
948         }
949         snprintf(dbf, sizeof(dbf), "relret:%d", ret);
950         CHSC_LOG(0, dbf);
951         free_page((unsigned long)on_close_chsc_area);
952         on_close_chsc_area = NULL;
953         kfree(on_close_request);
954         on_close_request = NULL;
955 out_unlock:
956         mutex_unlock(&on_close_mutex);
957         atomic_inc(&chsc_ready_for_use);
958         return 0;
959 }
960
961 static const struct file_operations chsc_fops = {
962         .owner = THIS_MODULE,
963         .open = chsc_open,
964         .release = chsc_release,
965         .unlocked_ioctl = chsc_ioctl,
966         .compat_ioctl = chsc_ioctl,
967         .llseek = no_llseek,
968 };
969
970 static struct miscdevice chsc_misc_device = {
971         .minor = MISC_DYNAMIC_MINOR,
972         .name = "chsc",
973         .fops = &chsc_fops,
974 };
975
976 static int __init chsc_misc_init(void)
977 {
978         return misc_register(&chsc_misc_device);
979 }
980
981 static void chsc_misc_cleanup(void)
982 {
983         misc_deregister(&chsc_misc_device);
984 }
985
986 static int __init chsc_sch_init(void)
987 {
988         int ret;
989
990         ret = chsc_init_dbfs();
991         if (ret)
992                 return ret;
993         isc_register(CHSC_SCH_ISC);
994         ret = chsc_init_sch_driver();
995         if (ret)
996                 goto out_dbf;
997         ret = chsc_misc_init();
998         if (ret)
999                 goto out_driver;
1000         return ret;
1001 out_driver:
1002         chsc_cleanup_sch_driver();
1003 out_dbf:
1004         isc_unregister(CHSC_SCH_ISC);
1005         chsc_remove_dbfs();
1006         return ret;
1007 }
1008
1009 static void __exit chsc_sch_exit(void)
1010 {
1011         chsc_misc_cleanup();
1012         chsc_cleanup_sch_driver();
1013         isc_unregister(CHSC_SCH_ISC);
1014         chsc_remove_dbfs();
1015 }
1016
1017 module_init(chsc_sch_init);
1018 module_exit(chsc_sch_exit);