aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2011-01-05 06:47:56 -0500
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2011-01-05 06:47:28 -0500
commitce322ccd53f2505cf8b0ed204631d6ac054ac66a (patch)
treec3b9b9145d691b3c8a389be9299b96b574b8f69e
parent37e8952174c6c239d1c86125e032fd6ad107a3e6 (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.h2
-rw-r--r--drivers/s390/cio/chsc.c19
-rw-r--r--drivers/s390/cio/chsc.h18
-rw-r--r--drivers/s390/cio/device_ops.c40
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);
205int ccw_device_tm_intrg(struct ccw_device *cdev); 205int ccw_device_tm_intrg(struct ccw_device *cdev);
206 206
207int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask);
208
207extern int ccw_device_set_online(struct ccw_device *cdev); 209extern int ccw_device_set_online(struct ccw_device *cdev);
208extern int ccw_device_set_offline(struct ccw_device *cdev); 210extern 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
698int 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));
712out:
713 spin_unlock_irq(&chsc_page_lock);
714 return ret;
715}
716
698static void 717static void
699chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv, 718chsc_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
38struct 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
38struct channel_path; 54struct channel_path;
39 55
40struct css_chsc_char { 56struct 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);
93int chsc_determine_base_channel_path_desc(struct chp_id chpid, 109int chsc_determine_base_channel_path_desc(struct chp_id chpid,
94 struct channel_path_desc *desc); 110 struct channel_path_desc *desc);
111int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid,
112 struct channel_path_desc_fmt1 *desc);
95void chsc_chp_online(struct chp_id chpid); 113void chsc_chp_online(struct chp_id chpid);
96void chsc_chp_offline(struct chp_id chpid); 114void chsc_chp_offline(struct chp_id chpid);
97int chsc_get_channel_measurement_chars(struct channel_path *chp); 115int 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,
687EXPORT_SYMBOL(ccw_device_tm_start_timeout); 687EXPORT_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 */
697int 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}
727EXPORT_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 *