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