diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2010-10-25 10:10:30 -0400 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-10-25 10:10:18 -0400 |
commit | 906c9768c7750ce76b85597174b9c3599a6ca9f6 (patch) | |
tree | 8676732f1a6bf8f83575a0d7c69048d76097ddde /drivers/s390/cio/chsc.c | |
parent | 34196f82b16749e119db5572271944c4add0a9aa (diff) |
[S390] chsc: use the global page to determine the chp desriptor
chsc_determine_channel_path_desc is called by a wrapper
who allocates a response struct. The response data
is then memcpy'ed to this response struct by
chsc_determine_channel_path_desc.
Change chsc_determine_base_channel_path_desc to use the
global chsc_page and deliver it to the function doing
the actual chsc call. The channel path desriptor is
then directly read from the response data.
As a result we get rid of the additional allocation
for the response struct.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/chsc.c')
-rw-r--r-- | drivers/s390/cio/chsc.c | 54 |
1 files changed, 15 insertions, 39 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index d12c152cb691..27aca3906a53 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -639,36 +639,18 @@ chsc_secm(struct channel_subsystem *css, int enable) | |||
639 | } | 639 | } |
640 | 640 | ||
641 | int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt, | 641 | int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt, |
642 | int c, int m, | 642 | int c, int m, void *page) |
643 | struct chsc_response_struct *resp) | ||
644 | { | 643 | { |
644 | struct chsc_scpd *scpd_area; | ||
645 | int ccode, ret; | 645 | int ccode, ret; |
646 | 646 | ||
647 | struct { | ||
648 | struct chsc_header request; | ||
649 | u32 : 2; | ||
650 | u32 m : 1; | ||
651 | u32 c : 1; | ||
652 | u32 fmt : 4; | ||
653 | u32 cssid : 8; | ||
654 | u32 : 4; | ||
655 | u32 rfmt : 4; | ||
656 | u32 first_chpid : 8; | ||
657 | u32 : 24; | ||
658 | u32 last_chpid : 8; | ||
659 | u32 zeroes1; | ||
660 | struct chsc_header response; | ||
661 | u8 data[PAGE_SIZE - 20]; | ||
662 | } __attribute__ ((packed)) *scpd_area; | ||
663 | |||
664 | if ((rfmt == 1) && !css_general_characteristics.fcs) | 647 | if ((rfmt == 1) && !css_general_characteristics.fcs) |
665 | return -EINVAL; | 648 | return -EINVAL; |
666 | if ((rfmt == 2) && !css_general_characteristics.cib) | 649 | if ((rfmt == 2) && !css_general_characteristics.cib) |
667 | return -EINVAL; | 650 | return -EINVAL; |
668 | 651 | ||
669 | spin_lock_irq(&chsc_page_lock); | 652 | memset(page, 0, PAGE_SIZE); |
670 | memset(chsc_page, 0, PAGE_SIZE); | 653 | scpd_area = page; |
671 | scpd_area = chsc_page; | ||
672 | scpd_area->request.length = 0x0010; | 654 | scpd_area->request.length = 0x0010; |
673 | scpd_area->request.code = 0x0002; | 655 | scpd_area->request.code = 0x0002; |
674 | scpd_area->cssid = chpid.cssid; | 656 | scpd_area->cssid = chpid.cssid; |
@@ -680,20 +662,13 @@ int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt, | |||
680 | scpd_area->rfmt = rfmt; | 662 | scpd_area->rfmt = rfmt; |
681 | 663 | ||
682 | ccode = chsc(scpd_area); | 664 | ccode = chsc(scpd_area); |
683 | if (ccode > 0) { | 665 | if (ccode > 0) |
684 | ret = (ccode == 3) ? -ENODEV : -EBUSY; | 666 | return (ccode == 3) ? -ENODEV : -EBUSY; |
685 | goto out; | ||
686 | } | ||
687 | 667 | ||
688 | ret = chsc_error_from_response(scpd_area->response.code); | 668 | ret = chsc_error_from_response(scpd_area->response.code); |
689 | if (ret == 0) | 669 | if (ret) |
690 | /* Success. */ | ||
691 | memcpy(resp, &scpd_area->response, scpd_area->response.length); | ||
692 | else | ||
693 | CIO_CRW_EVENT(2, "chsc: scpd failed (rc=%04x)\n", | 670 | CIO_CRW_EVENT(2, "chsc: scpd failed (rc=%04x)\n", |
694 | scpd_area->response.code); | 671 | scpd_area->response.code); |
695 | out: | ||
696 | spin_unlock_irq(&chsc_page_lock); | ||
697 | return ret; | 672 | return ret; |
698 | } | 673 | } |
699 | EXPORT_SYMBOL_GPL(chsc_determine_channel_path_desc); | 674 | EXPORT_SYMBOL_GPL(chsc_determine_channel_path_desc); |
@@ -702,17 +677,18 @@ int chsc_determine_base_channel_path_desc(struct chp_id chpid, | |||
702 | struct channel_path_desc *desc) | 677 | struct channel_path_desc *desc) |
703 | { | 678 | { |
704 | struct chsc_response_struct *chsc_resp; | 679 | struct chsc_response_struct *chsc_resp; |
680 | struct chsc_scpd *scpd_area; | ||
705 | int ret; | 681 | int ret; |
706 | 682 | ||
707 | chsc_resp = kzalloc(sizeof(*chsc_resp), GFP_KERNEL); | 683 | spin_lock_irq(&chsc_page_lock); |
708 | if (!chsc_resp) | 684 | scpd_area = chsc_page; |
709 | return -ENOMEM; | 685 | ret = chsc_determine_channel_path_desc(chpid, 0, 0, 0, 0, scpd_area); |
710 | ret = chsc_determine_channel_path_desc(chpid, 0, 0, 0, 0, chsc_resp); | ||
711 | if (ret) | 686 | if (ret) |
712 | goto out_free; | 687 | goto out; |
688 | chsc_resp = (void *)&scpd_area->response; | ||
713 | memcpy(desc, &chsc_resp->data, sizeof(*desc)); | 689 | memcpy(desc, &chsc_resp->data, sizeof(*desc)); |
714 | out_free: | 690 | out: |
715 | kfree(chsc_resp); | 691 | spin_unlock_irq(&chsc_page_lock); |
716 | return ret; | 692 | return ret; |
717 | } | 693 | } |
718 | 694 | ||