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); 1019