0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/export.h>
0009 #include <linux/init.h>
0010 #include <linux/errno.h>
0011 #include <linux/slab.h>
0012 #include <linux/list.h>
0013 #include <linux/device.h>
0014 #include <linux/delay.h>
0015 #include <linux/completion.h>
0016
0017 #include <asm/ccwdev.h>
0018 #include <asm/idals.h>
0019 #include <asm/chpid.h>
0020 #include <asm/fcx.h>
0021
0022 #include "cio.h"
0023 #include "cio_debug.h"
0024 #include "css.h"
0025 #include "chsc.h"
0026 #include "device.h"
0027 #include "chp.h"
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags)
0040 {
0041
0042
0043
0044 if ((flags & CCWDEV_EARLY_NOTIFICATION) &&
0045 (flags & CCWDEV_REPORT_ALL))
0046 return -EINVAL;
0047 cdev->private->options.fast = (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
0048 cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0;
0049 cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0;
0050 cdev->private->options.force = (flags & CCWDEV_ALLOW_FORCE) != 0;
0051 cdev->private->options.mpath = (flags & CCWDEV_DO_MULTIPATH) != 0;
0052 return 0;
0053 }
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags)
0065 {
0066
0067
0068
0069 if (((flags & CCWDEV_EARLY_NOTIFICATION) &&
0070 (flags & CCWDEV_REPORT_ALL)) ||
0071 ((flags & CCWDEV_EARLY_NOTIFICATION) &&
0072 cdev->private->options.repall) ||
0073 ((flags & CCWDEV_REPORT_ALL) &&
0074 cdev->private->options.fast))
0075 return -EINVAL;
0076 cdev->private->options.fast |= (flags & CCWDEV_EARLY_NOTIFICATION) != 0;
0077 cdev->private->options.repall |= (flags & CCWDEV_REPORT_ALL) != 0;
0078 cdev->private->options.pgroup |= (flags & CCWDEV_DO_PATHGROUP) != 0;
0079 cdev->private->options.force |= (flags & CCWDEV_ALLOW_FORCE) != 0;
0080 cdev->private->options.mpath |= (flags & CCWDEV_DO_MULTIPATH) != 0;
0081 return 0;
0082 }
0083
0084
0085
0086
0087
0088
0089
0090
0091 void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags)
0092 {
0093 cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0;
0094 cdev->private->options.repall &= (flags & CCWDEV_REPORT_ALL) == 0;
0095 cdev->private->options.pgroup &= (flags & CCWDEV_DO_PATHGROUP) == 0;
0096 cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0;
0097 cdev->private->options.mpath &= (flags & CCWDEV_DO_MULTIPATH) == 0;
0098 }
0099
0100
0101
0102
0103
0104
0105
0106 int ccw_device_is_pathgroup(struct ccw_device *cdev)
0107 {
0108 return cdev->private->flags.pgroup;
0109 }
0110 EXPORT_SYMBOL(ccw_device_is_pathgroup);
0111
0112
0113
0114
0115
0116
0117
0118 int ccw_device_is_multipath(struct ccw_device *cdev)
0119 {
0120 return cdev->private->flags.mpath;
0121 }
0122 EXPORT_SYMBOL(ccw_device_is_multipath);
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137 int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
0138 {
0139 struct subchannel *sch;
0140 int ret;
0141
0142 if (!cdev || !cdev->dev.parent)
0143 return -ENODEV;
0144 sch = to_subchannel(cdev->dev.parent);
0145 if (!sch->schib.pmcw.ena)
0146 return -EINVAL;
0147 if (cdev->private->state == DEV_STATE_NOT_OPER)
0148 return -ENODEV;
0149 if (cdev->private->state != DEV_STATE_ONLINE &&
0150 cdev->private->state != DEV_STATE_W4SENSE)
0151 return -EINVAL;
0152
0153 ret = cio_clear(sch);
0154 if (ret == 0)
0155 cdev->private->intparm = intparm;
0156 return ret;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
0192 unsigned long intparm, __u8 lpm, __u8 key,
0193 unsigned long flags, int expires)
0194 {
0195 struct subchannel *sch;
0196 int ret;
0197
0198 if (!cdev || !cdev->dev.parent)
0199 return -ENODEV;
0200 sch = to_subchannel(cdev->dev.parent);
0201 if (!sch->schib.pmcw.ena)
0202 return -EINVAL;
0203 if (cdev->private->state == DEV_STATE_NOT_OPER)
0204 return -ENODEV;
0205 if (cdev->private->state == DEV_STATE_VERIFY) {
0206
0207 if (!cdev->private->flags.fake_irb) {
0208 cdev->private->flags.fake_irb = FAKE_CMD_IRB;
0209 cdev->private->intparm = intparm;
0210 return 0;
0211 } else
0212
0213 return -EBUSY;
0214 }
0215 if (cdev->private->state != DEV_STATE_ONLINE ||
0216 ((sch->schib.scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) &&
0217 !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS)) ||
0218 cdev->private->flags.doverify)
0219 return -EBUSY;
0220 ret = cio_set_options (sch, flags);
0221 if (ret)
0222 return ret;
0223
0224 if (lpm) {
0225 lpm &= sch->lpm;
0226 if (lpm == 0)
0227 return -EACCES;
0228 }
0229 ret = cio_start_key (sch, cpa, lpm, key);
0230 switch (ret) {
0231 case 0:
0232 cdev->private->intparm = intparm;
0233 if (expires)
0234 ccw_device_set_timeout(cdev, expires);
0235 break;
0236 case -EACCES:
0237 case -ENODEV:
0238 dev_fsm_event(cdev, DEV_EVENT_VERIFY);
0239 break;
0240 }
0241 return ret;
0242 }
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271 int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
0272 unsigned long intparm, __u8 lpm, __u8 key,
0273 unsigned long flags)
0274 {
0275 return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm, key,
0276 flags, 0);
0277 }
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305 int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa,
0306 unsigned long intparm, __u8 lpm, unsigned long flags)
0307 {
0308 return ccw_device_start_key(cdev, cpa, intparm, lpm,
0309 PAGE_DEFAULT_KEY, flags);
0310 }
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343 int ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa,
0344 unsigned long intparm, __u8 lpm,
0345 unsigned long flags, int expires)
0346 {
0347 return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm,
0348 PAGE_DEFAULT_KEY, flags,
0349 expires);
0350 }
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370 int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
0371 {
0372 struct subchannel *sch;
0373 int ret;
0374
0375 if (!cdev || !cdev->dev.parent)
0376 return -ENODEV;
0377 sch = to_subchannel(cdev->dev.parent);
0378 if (!sch->schib.pmcw.ena)
0379 return -EINVAL;
0380 if (cdev->private->state == DEV_STATE_NOT_OPER)
0381 return -ENODEV;
0382 if (cdev->private->state != DEV_STATE_ONLINE &&
0383 cdev->private->state != DEV_STATE_W4SENSE)
0384 return -EINVAL;
0385
0386 ret = cio_halt(sch);
0387 if (ret == 0)
0388 cdev->private->intparm = intparm;
0389 return ret;
0390 }
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405 int ccw_device_resume(struct ccw_device *cdev)
0406 {
0407 struct subchannel *sch;
0408
0409 if (!cdev || !cdev->dev.parent)
0410 return -ENODEV;
0411 sch = to_subchannel(cdev->dev.parent);
0412 if (!sch->schib.pmcw.ena)
0413 return -EINVAL;
0414 if (cdev->private->state == DEV_STATE_NOT_OPER)
0415 return -ENODEV;
0416 if (cdev->private->state != DEV_STATE_ONLINE ||
0417 !(sch->schib.scsw.cmd.actl & SCSW_ACTL_SUSPENDED))
0418 return -EINVAL;
0419 return cio_resume(sch);
0420 }
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436 struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct)
0437 {
0438 int ciw_cnt;
0439
0440 if (cdev->private->flags.esid == 0)
0441 return NULL;
0442 for (ciw_cnt = 0; ciw_cnt < MAX_CIWS; ciw_cnt++)
0443 if (cdev->private->dma_area->senseid.ciw[ciw_cnt].ct == ct)
0444 return cdev->private->dma_area->senseid.ciw + ciw_cnt;
0445 return NULL;
0446 }
0447
0448
0449
0450
0451
0452
0453
0454
0455 __u8 ccw_device_get_path_mask(struct ccw_device *cdev)
0456 {
0457 struct subchannel *sch;
0458
0459 if (!cdev->dev.parent)
0460 return 0;
0461
0462 sch = to_subchannel(cdev->dev.parent);
0463 return sch->lpm;
0464 }
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474 struct channel_path_desc_fmt0 *ccw_device_get_chp_desc(struct ccw_device *cdev,
0475 int chp_idx)
0476 {
0477 struct subchannel *sch;
0478 struct chp_id chpid;
0479
0480 sch = to_subchannel(cdev->dev.parent);
0481 chp_id_init(&chpid);
0482 chpid.id = sch->schib.pmcw.chpid[chp_idx];
0483 return chp_get_chp_desc(chpid);
0484 }
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494 u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx)
0495 {
0496 struct subchannel *sch = to_subchannel(cdev->dev.parent);
0497 struct channel_path *chp;
0498 struct chp_id chpid;
0499 u8 *util_str;
0500
0501 chp_id_init(&chpid);
0502 chpid.id = sch->schib.pmcw.chpid[chp_idx];
0503 chp = chpid_to_chp(chpid);
0504
0505 util_str = kmalloc(sizeof(chp->desc_fmt3.util_str), GFP_KERNEL);
0506 if (!util_str)
0507 return NULL;
0508
0509 mutex_lock(&chp->lock);
0510 memcpy(util_str, chp->desc_fmt3.util_str, sizeof(chp->desc_fmt3.util_str));
0511 mutex_unlock(&chp->lock);
0512
0513 return util_str;
0514 }
0515
0516
0517
0518
0519
0520
0521 void ccw_device_get_id(struct ccw_device *cdev, struct ccw_dev_id *dev_id)
0522 {
0523 *dev_id = cdev->private->dev_id;
0524 }
0525 EXPORT_SYMBOL(ccw_device_get_id);
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539 int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw,
0540 unsigned long intparm, u8 lpm, u8 key,
0541 int expires)
0542 {
0543 struct subchannel *sch;
0544 int rc;
0545
0546 sch = to_subchannel(cdev->dev.parent);
0547 if (!sch->schib.pmcw.ena)
0548 return -EINVAL;
0549 if (cdev->private->state == DEV_STATE_VERIFY) {
0550
0551 if (!cdev->private->flags.fake_irb) {
0552 cdev->private->flags.fake_irb = FAKE_TM_IRB;
0553 cdev->private->intparm = intparm;
0554 return 0;
0555 } else
0556
0557 return -EBUSY;
0558 }
0559 if (cdev->private->state != DEV_STATE_ONLINE)
0560 return -EIO;
0561
0562 if (lpm) {
0563 lpm &= sch->lpm;
0564 if (lpm == 0)
0565 return -EACCES;
0566 }
0567 rc = cio_tm_start_key(sch, tcw, lpm, key);
0568 if (rc == 0) {
0569 cdev->private->intparm = intparm;
0570 if (expires)
0571 ccw_device_set_timeout(cdev, expires);
0572 }
0573 return rc;
0574 }
0575 EXPORT_SYMBOL(ccw_device_tm_start_timeout_key);
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588 int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
0589 unsigned long intparm, u8 lpm, u8 key)
0590 {
0591 return ccw_device_tm_start_timeout_key(cdev, tcw, intparm, lpm, key, 0);
0592 }
0593 EXPORT_SYMBOL(ccw_device_tm_start_key);
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605 int ccw_device_tm_start(struct ccw_device *cdev, struct tcw *tcw,
0606 unsigned long intparm, u8 lpm)
0607 {
0608 return ccw_device_tm_start_key(cdev, tcw, intparm, lpm,
0609 PAGE_DEFAULT_KEY);
0610 }
0611 EXPORT_SYMBOL(ccw_device_tm_start);
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624 int ccw_device_tm_start_timeout(struct ccw_device *cdev, struct tcw *tcw,
0625 unsigned long intparm, u8 lpm, int expires)
0626 {
0627 return ccw_device_tm_start_timeout_key(cdev, tcw, intparm, lpm,
0628 PAGE_DEFAULT_KEY, expires);
0629 }
0630 EXPORT_SYMBOL(ccw_device_tm_start_timeout);
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640 int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)
0641 {
0642 struct subchannel *sch = to_subchannel(cdev->dev.parent);
0643 struct channel_path *chp;
0644 struct chp_id chpid;
0645 int mdc = 0, i;
0646
0647
0648 if (mask)
0649 mask &= sch->lpm;
0650 else
0651 mask = sch->lpm;
0652
0653 chp_id_init(&chpid);
0654 for (i = 0; i < 8; i++) {
0655 if (!(mask & (0x80 >> i)))
0656 continue;
0657 chpid.id = sch->schib.pmcw.chpid[i];
0658 chp = chpid_to_chp(chpid);
0659 if (!chp)
0660 continue;
0661
0662 mutex_lock(&chp->lock);
0663 if (!chp->desc_fmt1.f) {
0664 mutex_unlock(&chp->lock);
0665 return 0;
0666 }
0667 if (!chp->desc_fmt1.r)
0668 mdc = 1;
0669 mdc = mdc ? min_t(int, mdc, chp->desc_fmt1.mdc) :
0670 chp->desc_fmt1.mdc;
0671 mutex_unlock(&chp->lock);
0672 }
0673
0674 return mdc;
0675 }
0676 EXPORT_SYMBOL(ccw_device_get_mdc);
0677
0678
0679
0680
0681
0682
0683
0684
0685 int ccw_device_tm_intrg(struct ccw_device *cdev)
0686 {
0687 struct subchannel *sch = to_subchannel(cdev->dev.parent);
0688
0689 if (!sch->schib.pmcw.ena)
0690 return -EINVAL;
0691 if (cdev->private->state != DEV_STATE_ONLINE)
0692 return -EIO;
0693 if (!scsw_is_tm(&sch->schib.scsw) ||
0694 !(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_START_PEND))
0695 return -EINVAL;
0696 return cio_tm_intrg(sch);
0697 }
0698 EXPORT_SYMBOL(ccw_device_tm_intrg);
0699
0700
0701
0702
0703
0704
0705 void ccw_device_get_schid(struct ccw_device *cdev, struct subchannel_id *schid)
0706 {
0707 struct subchannel *sch = to_subchannel(cdev->dev.parent);
0708
0709 *schid = sch->schid;
0710 }
0711 EXPORT_SYMBOL_GPL(ccw_device_get_schid);
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725 int ccw_device_pnso(struct ccw_device *cdev,
0726 struct chsc_pnso_area *pnso_area, u8 oc,
0727 struct chsc_pnso_resume_token resume_token, int cnc)
0728 {
0729 struct subchannel_id schid;
0730
0731 ccw_device_get_schid(cdev, &schid);
0732 return chsc_pnso(schid, pnso_area, oc, resume_token, cnc);
0733 }
0734 EXPORT_SYMBOL_GPL(ccw_device_pnso);
0735
0736
0737
0738
0739
0740
0741 int ccw_device_get_cssid(struct ccw_device *cdev, u8 *cssid)
0742 {
0743 struct device *sch_dev = cdev->dev.parent;
0744 struct channel_subsystem *css = to_css(sch_dev->parent);
0745
0746 if (css->id_valid)
0747 *cssid = css->cssid;
0748 return css->id_valid ? 0 : -ENODEV;
0749 }
0750 EXPORT_SYMBOL_GPL(ccw_device_get_cssid);
0751
0752
0753
0754
0755
0756
0757 int ccw_device_get_iid(struct ccw_device *cdev, u8 *iid)
0758 {
0759 struct device *sch_dev = cdev->dev.parent;
0760 struct channel_subsystem *css = to_css(sch_dev->parent);
0761
0762 if (css->id_valid)
0763 *iid = css->iid;
0764 return css->id_valid ? 0 : -ENODEV;
0765 }
0766 EXPORT_SYMBOL_GPL(ccw_device_get_iid);
0767
0768
0769
0770
0771
0772
0773
0774 int ccw_device_get_chpid(struct ccw_device *cdev, int chp_idx, u8 *chpid)
0775 {
0776 struct subchannel *sch = to_subchannel(cdev->dev.parent);
0777 int mask;
0778
0779 if ((chp_idx < 0) || (chp_idx > 7))
0780 return -EINVAL;
0781 mask = 0x80 >> chp_idx;
0782 if (!(sch->schib.pmcw.pim & mask))
0783 return -ENODEV;
0784
0785 *chpid = sch->schib.pmcw.chpid[chp_idx];
0786 return 0;
0787 }
0788 EXPORT_SYMBOL_GPL(ccw_device_get_chpid);
0789
0790
0791
0792
0793
0794
0795
0796 int ccw_device_get_chid(struct ccw_device *cdev, int chp_idx, u16 *chid)
0797 {
0798 struct chp_id cssid_chpid;
0799 struct channel_path *chp;
0800 int rc;
0801
0802 chp_id_init(&cssid_chpid);
0803 rc = ccw_device_get_chpid(cdev, chp_idx, &cssid_chpid.id);
0804 if (rc)
0805 return rc;
0806 chp = chpid_to_chp(cssid_chpid);
0807 if (!chp)
0808 return -ENODEV;
0809
0810 mutex_lock(&chp->lock);
0811 if (chp->desc_fmt1.flags & 0x10)
0812 *chid = chp->desc_fmt1.chid;
0813 else
0814 rc = -ENODEV;
0815 mutex_unlock(&chp->lock);
0816
0817 return rc;
0818 }
0819 EXPORT_SYMBOL_GPL(ccw_device_get_chid);
0820
0821
0822
0823
0824
0825
0826 void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size)
0827 {
0828 void *addr;
0829
0830 if (!get_device(&cdev->dev))
0831 return NULL;
0832 addr = cio_gp_dma_zalloc(cdev->private->dma_pool, &cdev->dev, size);
0833 if (IS_ERR_OR_NULL(addr))
0834 put_device(&cdev->dev);
0835 return addr;
0836 }
0837 EXPORT_SYMBOL(ccw_device_dma_zalloc);
0838
0839 void ccw_device_dma_free(struct ccw_device *cdev, void *cpu_addr, size_t size)
0840 {
0841 if (!cpu_addr)
0842 return;
0843 cio_gp_dma_free(cdev->private->dma_pool, cpu_addr, size);
0844 put_device(&cdev->dev);
0845 }
0846 EXPORT_SYMBOL(ccw_device_dma_free);
0847
0848 EXPORT_SYMBOL(ccw_device_set_options_mask);
0849 EXPORT_SYMBOL(ccw_device_set_options);
0850 EXPORT_SYMBOL(ccw_device_clear_options);
0851 EXPORT_SYMBOL(ccw_device_clear);
0852 EXPORT_SYMBOL(ccw_device_halt);
0853 EXPORT_SYMBOL(ccw_device_resume);
0854 EXPORT_SYMBOL(ccw_device_start_timeout);
0855 EXPORT_SYMBOL(ccw_device_start);
0856 EXPORT_SYMBOL(ccw_device_start_timeout_key);
0857 EXPORT_SYMBOL(ccw_device_start_key);
0858 EXPORT_SYMBOL(ccw_device_get_ciw);
0859 EXPORT_SYMBOL(ccw_device_get_path_mask);
0860 EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc);
0861 EXPORT_SYMBOL_GPL(ccw_device_get_util_str);