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 | |
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')
-rw-r--r-- | drivers/s390/cio/chsc.c | 54 | ||||
-rw-r--r-- | drivers/s390/cio/chsc.h | 22 | ||||
-rw-r--r-- | drivers/s390/cio/chsc_sch.c | 12 |
3 files changed, 44 insertions, 44 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 | ||
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 852b61fc56ea..6693f5e3176f 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -57,6 +57,25 @@ struct chsc_ssd_info { | |||
57 | struct chp_id chpid[8]; | 57 | struct chp_id chpid[8]; |
58 | u16 fla[8]; | 58 | u16 fla[8]; |
59 | }; | 59 | }; |
60 | |||
61 | struct chsc_scpd { | ||
62 | struct chsc_header request; | ||
63 | u32:2; | ||
64 | u32 m:1; | ||
65 | u32 c:1; | ||
66 | u32 fmt:4; | ||
67 | u32 cssid:8; | ||
68 | u32:4; | ||
69 | u32 rfmt:4; | ||
70 | u32 first_chpid:8; | ||
71 | u32:24; | ||
72 | u32 last_chpid:8; | ||
73 | u32 zeroes1; | ||
74 | struct chsc_header response; | ||
75 | u8 data[PAGE_SIZE - 20]; | ||
76 | } __attribute__ ((packed)); | ||
77 | |||
78 | |||
60 | extern int chsc_get_ssd_info(struct subchannel_id schid, | 79 | extern int chsc_get_ssd_info(struct subchannel_id schid, |
61 | struct chsc_ssd_info *ssd); | 80 | struct chsc_ssd_info *ssd); |
62 | extern int chsc_determine_css_characteristics(void); | 81 | extern int chsc_determine_css_characteristics(void); |
@@ -70,8 +89,7 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable); | |||
70 | 89 | ||
71 | int chsc_chp_vary(struct chp_id chpid, int on); | 90 | int chsc_chp_vary(struct chp_id chpid, int on); |
72 | int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt, | 91 | int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt, |
73 | int c, int m, | 92 | int c, int m, void *page); |
74 | struct chsc_response_struct *resp); | ||
75 | int chsc_determine_base_channel_path_desc(struct chp_id chpid, | 93 | int chsc_determine_base_channel_path_desc(struct chp_id chpid, |
76 | struct channel_path_desc *desc); | 94 | struct channel_path_desc *desc); |
77 | void chsc_chp_online(struct chp_id chpid); | 95 | void chsc_chp_online(struct chp_id chpid); |
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index f2b77e7bfc6f..3c3f3ffe2179 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c | |||
@@ -688,25 +688,31 @@ out_free: | |||
688 | 688 | ||
689 | static int chsc_ioctl_chpd(void __user *user_chpd) | 689 | static int chsc_ioctl_chpd(void __user *user_chpd) |
690 | { | 690 | { |
691 | struct chsc_scpd *scpd_area; | ||
691 | struct chsc_cpd_info *chpd; | 692 | struct chsc_cpd_info *chpd; |
692 | int ret; | 693 | int ret; |
693 | 694 | ||
694 | chpd = kzalloc(sizeof(*chpd), GFP_KERNEL); | 695 | chpd = kzalloc(sizeof(*chpd), GFP_KERNEL); |
695 | if (!chpd) | 696 | scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); |
696 | return -ENOMEM; | 697 | if (!scpd_area || !chpd) { |
698 | ret = -ENOMEM; | ||
699 | goto out_free; | ||
700 | } | ||
697 | if (copy_from_user(chpd, user_chpd, sizeof(*chpd))) { | 701 | if (copy_from_user(chpd, user_chpd, sizeof(*chpd))) { |
698 | ret = -EFAULT; | 702 | ret = -EFAULT; |
699 | goto out_free; | 703 | goto out_free; |
700 | } | 704 | } |
701 | ret = chsc_determine_channel_path_desc(chpd->chpid, chpd->fmt, | 705 | ret = chsc_determine_channel_path_desc(chpd->chpid, chpd->fmt, |
702 | chpd->rfmt, chpd->c, chpd->m, | 706 | chpd->rfmt, chpd->c, chpd->m, |
703 | &chpd->chpdb); | 707 | scpd_area); |
704 | if (ret) | 708 | if (ret) |
705 | goto out_free; | 709 | goto out_free; |
710 | memcpy(&chpd->chpdb, &scpd_area->response, scpd_area->response.length); | ||
706 | if (copy_to_user(user_chpd, chpd, sizeof(*chpd))) | 711 | if (copy_to_user(user_chpd, chpd, sizeof(*chpd))) |
707 | ret = -EFAULT; | 712 | ret = -EFAULT; |
708 | out_free: | 713 | out_free: |
709 | kfree(chpd); | 714 | kfree(chpd); |
715 | free_page((unsigned long)scpd_area); | ||
710 | return ret; | 716 | return ret; |
711 | } | 717 | } |
712 | 718 | ||