aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/chsc.c
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2008-07-14 03:59:05 -0400
committerHeiko Carstens <heiko.carstens@de.ibm.com>2008-07-14 04:02:12 -0400
commit9d92a7e1b0d095c8be96ce5e592c6c5541684631 (patch)
tree22cfca810de07a7d7f87f17a89de0ae10d462038 /drivers/s390/cio/chsc.c
parent683c5418e6ac9f40f925dab6f547a5b0a4ad43c6 (diff)
[S390] cio: Add chsc subchannel driver.
This patch adds a driver for subchannels of type chsc. A device /dev/chsc is created which may be used to issue ioctls to: - obtain information about the machine's I/O configuration - dynamically change the machine's I/O configuration via asynchronous chsc commands Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/chsc.c')
-rw-r--r--drivers/s390/cio/chsc.c48
1 files changed, 41 insertions, 7 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index e23c3806972a..65264a38057d 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -15,6 +15,7 @@
15 15
16#include <asm/cio.h> 16#include <asm/cio.h>
17#include <asm/chpid.h> 17#include <asm/chpid.h>
18#include <asm/chsc.h>
18 19
19#include "../s390mach.h" 20#include "../s390mach.h"
20#include "css.h" 21#include "css.h"
@@ -627,23 +628,33 @@ chsc_secm(struct channel_subsystem *css, int enable)
627 return ret; 628 return ret;
628} 629}
629 630
630int chsc_determine_channel_path_description(struct chp_id chpid, 631int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt,
631 struct channel_path_desc *desc) 632 int c, int m,
633 struct chsc_response_struct *resp)
632{ 634{
633 int ccode, ret; 635 int ccode, ret;
634 636
635 struct { 637 struct {
636 struct chsc_header request; 638 struct chsc_header request;
637 u32 : 24; 639 u32 : 2;
640 u32 m : 1;
641 u32 c : 1;
642 u32 fmt : 4;
643 u32 cssid : 8;
644 u32 : 4;
645 u32 rfmt : 4;
638 u32 first_chpid : 8; 646 u32 first_chpid : 8;
639 u32 : 24; 647 u32 : 24;
640 u32 last_chpid : 8; 648 u32 last_chpid : 8;
641 u32 zeroes1; 649 u32 zeroes1;
642 struct chsc_header response; 650 struct chsc_header response;
643 u32 zeroes2; 651 u8 data[PAGE_SIZE - 20];
644 struct channel_path_desc desc;
645 } __attribute__ ((packed)) *scpd_area; 652 } __attribute__ ((packed)) *scpd_area;
646 653
654 if ((rfmt == 1) && !css_general_characteristics.fcs)
655 return -EINVAL;
656 if ((rfmt == 2) && !css_general_characteristics.cib)
657 return -EINVAL;
647 scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); 658 scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
648 if (!scpd_area) 659 if (!scpd_area)
649 return -ENOMEM; 660 return -ENOMEM;
@@ -651,8 +662,13 @@ int chsc_determine_channel_path_description(struct chp_id chpid,
651 scpd_area->request.length = 0x0010; 662 scpd_area->request.length = 0x0010;
652 scpd_area->request.code = 0x0002; 663 scpd_area->request.code = 0x0002;
653 664
665 scpd_area->cssid = chpid.cssid;
654 scpd_area->first_chpid = chpid.id; 666 scpd_area->first_chpid = chpid.id;
655 scpd_area->last_chpid = chpid.id; 667 scpd_area->last_chpid = chpid.id;
668 scpd_area->m = m;
669 scpd_area->c = c;
670 scpd_area->fmt = fmt;
671 scpd_area->rfmt = rfmt;
656 672
657 ccode = chsc(scpd_area); 673 ccode = chsc(scpd_area);
658 if (ccode > 0) { 674 if (ccode > 0) {
@@ -663,8 +679,7 @@ int chsc_determine_channel_path_description(struct chp_id chpid,
663 ret = chsc_error_from_response(scpd_area->response.code); 679 ret = chsc_error_from_response(scpd_area->response.code);
664 if (ret == 0) 680 if (ret == 0)
665 /* Success. */ 681 /* Success. */
666 memcpy(desc, &scpd_area->desc, 682 memcpy(resp, &scpd_area->response, scpd_area->response.length);
667 sizeof(struct channel_path_desc));
668 else 683 else
669 CIO_CRW_EVENT(2, "chsc: scpd failed (rc=%04x)\n", 684 CIO_CRW_EVENT(2, "chsc: scpd failed (rc=%04x)\n",
670 scpd_area->response.code); 685 scpd_area->response.code);
@@ -672,6 +687,25 @@ out:
672 free_page((unsigned long)scpd_area); 687 free_page((unsigned long)scpd_area);
673 return ret; 688 return ret;
674} 689}
690EXPORT_SYMBOL_GPL(chsc_determine_channel_path_desc);
691
692int chsc_determine_base_channel_path_desc(struct chp_id chpid,
693 struct channel_path_desc *desc)
694{
695 struct chsc_response_struct *chsc_resp;
696 int ret;
697
698 chsc_resp = kzalloc(sizeof(*chsc_resp), GFP_KERNEL);
699 if (!chsc_resp)
700 return -ENOMEM;
701 ret = chsc_determine_channel_path_desc(chpid, 0, 0, 0, 0, chsc_resp);
702 if (ret)
703 goto out_free;
704 memcpy(desc, &chsc_resp->data, chsc_resp->length);
705out_free:
706 kfree(chsc_resp);
707 return ret;
708}
675 709
676static void 710static void
677chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv, 711chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,