diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2011-01-05 06:47:56 -0500 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2011-01-05 06:47:28 -0500 |
commit | ce322ccd53f2505cf8b0ed204631d6ac054ac66a (patch) | |
tree | c3b9b9145d691b3c8a389be9299b96b574b8f69e | |
parent | 37e8952174c6c239d1c86125e032fd6ad107a3e6 (diff) |
[S390] cio: obtain mdc value per channel path
Add support to accumulate the number of 64K-bytes blocks all paths
to a device at least support for a transport command.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/include/asm/ccwdev.h | 2 | ||||
-rw-r--r-- | drivers/s390/cio/chsc.c | 19 | ||||
-rw-r--r-- | drivers/s390/cio/chsc.h | 18 | ||||
-rw-r--r-- | drivers/s390/cio/device_ops.c | 40 |
4 files changed, 79 insertions, 0 deletions
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h index e8501115eca8..ff6f62e0ec3e 100644 --- a/arch/s390/include/asm/ccwdev.h +++ b/arch/s390/include/asm/ccwdev.h | |||
@@ -204,6 +204,8 @@ int ccw_device_tm_start_timeout(struct ccw_device *, struct tcw *, | |||
204 | unsigned long, u8, int); | 204 | unsigned long, u8, int); |
205 | int ccw_device_tm_intrg(struct ccw_device *cdev); | 205 | int ccw_device_tm_intrg(struct ccw_device *cdev); |
206 | 206 | ||
207 | int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask); | ||
208 | |||
207 | extern int ccw_device_set_online(struct ccw_device *cdev); | 209 | extern int ccw_device_set_online(struct ccw_device *cdev); |
208 | extern int ccw_device_set_offline(struct ccw_device *cdev); | 210 | extern int ccw_device_set_offline(struct ccw_device *cdev); |
209 | 211 | ||
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 1aaddea673e0..0689fcf23a11 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -695,6 +695,25 @@ out: | |||
695 | return ret; | 695 | return ret; |
696 | } | 696 | } |
697 | 697 | ||
698 | int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid, | ||
699 | struct channel_path_desc_fmt1 *desc) | ||
700 | { | ||
701 | struct chsc_response_struct *chsc_resp; | ||
702 | struct chsc_scpd *scpd_area; | ||
703 | int ret; | ||
704 | |||
705 | spin_lock_irq(&chsc_page_lock); | ||
706 | scpd_area = chsc_page; | ||
707 | ret = chsc_determine_channel_path_desc(chpid, 0, 0, 1, 0, scpd_area); | ||
708 | if (ret) | ||
709 | goto out; | ||
710 | chsc_resp = (void *)&scpd_area->response; | ||
711 | memcpy(desc, &chsc_resp->data, sizeof(*desc)); | ||
712 | out: | ||
713 | spin_unlock_irq(&chsc_page_lock); | ||
714 | return ret; | ||
715 | } | ||
716 | |||
698 | static void | 717 | static void |
699 | chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv, | 718 | chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv, |
700 | struct cmg_chars *chars) | 719 | struct cmg_chars *chars) |
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 6693f5e3176f..3f15b2aaeaea 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -35,6 +35,22 @@ struct channel_path_desc { | |||
35 | u8 chpp; | 35 | u8 chpp; |
36 | } __attribute__ ((packed)); | 36 | } __attribute__ ((packed)); |
37 | 37 | ||
38 | struct channel_path_desc_fmt1 { | ||
39 | u8 flags; | ||
40 | u8 lsn; | ||
41 | u8 desc; | ||
42 | u8 chpid; | ||
43 | u32:24; | ||
44 | u8 chpp; | ||
45 | u32 unused[3]; | ||
46 | u16 mdc; | ||
47 | u16:13; | ||
48 | u8 r:1; | ||
49 | u8 s:1; | ||
50 | u8 f:1; | ||
51 | u32 zeros[2]; | ||
52 | } __attribute__ ((packed)); | ||
53 | |||
38 | struct channel_path; | 54 | struct channel_path; |
39 | 55 | ||
40 | struct css_chsc_char { | 56 | struct css_chsc_char { |
@@ -92,6 +108,8 @@ int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt, | |||
92 | int c, int m, void *page); | 108 | int c, int m, void *page); |
93 | int chsc_determine_base_channel_path_desc(struct chp_id chpid, | 109 | int chsc_determine_base_channel_path_desc(struct chp_id chpid, |
94 | struct channel_path_desc *desc); | 110 | struct channel_path_desc *desc); |
111 | int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid, | ||
112 | struct channel_path_desc_fmt1 *desc); | ||
95 | void chsc_chp_online(struct chp_id chpid); | 113 | void chsc_chp_online(struct chp_id chpid); |
96 | void chsc_chp_offline(struct chp_id chpid); | 114 | void chsc_chp_offline(struct chp_id chpid); |
97 | int chsc_get_channel_measurement_chars(struct channel_path *chp); | 115 | int chsc_get_channel_measurement_chars(struct channel_path *chp); |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 6da84543dfe9..651976b54af8 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
@@ -687,6 +687,46 @@ int ccw_device_tm_start_timeout(struct ccw_device *cdev, struct tcw *tcw, | |||
687 | EXPORT_SYMBOL(ccw_device_tm_start_timeout); | 687 | EXPORT_SYMBOL(ccw_device_tm_start_timeout); |
688 | 688 | ||
689 | /** | 689 | /** |
690 | * ccw_device_get_mdc - accumulate max data count | ||
691 | * @cdev: ccw device for which the max data count is accumulated | ||
692 | * @mask: mask of paths to use | ||
693 | * | ||
694 | * Return the number of 64K-bytes blocks all paths at least support | ||
695 | * for a transport command. Return values <= 0 indicate failures. | ||
696 | */ | ||
697 | int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask) | ||
698 | { | ||
699 | struct subchannel *sch = to_subchannel(cdev->dev.parent); | ||
700 | struct channel_path_desc_fmt1 desc; | ||
701 | struct chp_id chpid; | ||
702 | int mdc = 0, ret, i; | ||
703 | |||
704 | /* Adjust requested path mask to excluded varied off paths. */ | ||
705 | if (mask) | ||
706 | mask &= sch->lpm; | ||
707 | else | ||
708 | mask = sch->lpm; | ||
709 | |||
710 | chp_id_init(&chpid); | ||
711 | for (i = 0; i < 8; i++) { | ||
712 | if (!(mask & (0x80 >> i))) | ||
713 | continue; | ||
714 | chpid.id = sch->schib.pmcw.chpid[i]; | ||
715 | ret = chsc_determine_fmt1_channel_path_desc(chpid, &desc); | ||
716 | if (ret) | ||
717 | return ret; | ||
718 | if (!desc.f) | ||
719 | return 0; | ||
720 | if (!desc.r) | ||
721 | mdc = 1; | ||
722 | mdc = mdc ? min(mdc, (int)desc.mdc) : desc.mdc; | ||
723 | } | ||
724 | |||
725 | return mdc; | ||
726 | } | ||
727 | EXPORT_SYMBOL(ccw_device_get_mdc); | ||
728 | |||
729 | /** | ||
690 | * ccw_device_tm_intrg - perform interrogate function | 730 | * ccw_device_tm_intrg - perform interrogate function |
691 | * @cdev: ccw device on which to perform the interrogate function | 731 | * @cdev: ccw device on which to perform the interrogate function |
692 | * | 732 | * |