diff options
Diffstat (limited to 'drivers/s390/cio/chsc.c')
-rw-r--r-- | drivers/s390/cio/chsc.c | 178 |
1 files changed, 98 insertions, 80 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 6f05a44e3817..bb6f876e53c2 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -20,43 +20,48 @@ | |||
20 | #include "cio.h" | 20 | #include "cio.h" |
21 | #include "cio_debug.h" | 21 | #include "cio_debug.h" |
22 | #include "ioasm.h" | 22 | #include "ioasm.h" |
23 | #include "chpid.h" | ||
23 | #include "chsc.h" | 24 | #include "chsc.h" |
24 | 25 | ||
25 | static void *sei_page; | 26 | static void *sei_page; |
26 | 27 | ||
27 | static int new_channel_path(int chpid); | 28 | static int new_channel_path(struct chp_id chpid); |
28 | 29 | ||
29 | static inline void | 30 | static inline struct channel_path *chpid_to_chp(struct chp_id chpid) |
30 | set_chp_logically_online(int chp, int onoff) | ||
31 | { | 31 | { |
32 | css[0]->chps[chp]->state = onoff; | 32 | return css[chpid.cssid]->chps[chpid.id]; |
33 | } | 33 | } |
34 | 34 | ||
35 | static int | 35 | static void set_chp_logically_online(struct chp_id chpid, int onoff) |
36 | get_chp_status(int chp) | ||
37 | { | 36 | { |
38 | return (css[0]->chps[chp] ? css[0]->chps[chp]->state : -ENODEV); | 37 | chpid_to_chp(chpid)->state = onoff; |
39 | } | 38 | } |
40 | 39 | ||
41 | void | 40 | static int get_chp_status(struct chp_id chpid) |
42 | chsc_validate_chpids(struct subchannel *sch) | 41 | { |
42 | return (chpid_to_chp(chpid) ? chpid_to_chp(chpid)->state : -ENODEV); | ||
43 | } | ||
44 | |||
45 | void chsc_validate_chpids(struct subchannel *sch) | ||
43 | { | 46 | { |
44 | int mask, chp; | 47 | int mask, chp; |
48 | struct chp_id chpid; | ||
45 | 49 | ||
50 | chp_id_init(&chpid); | ||
46 | for (chp = 0; chp <= 7; chp++) { | 51 | for (chp = 0; chp <= 7; chp++) { |
47 | mask = 0x80 >> chp; | 52 | mask = 0x80 >> chp; |
48 | if (!get_chp_status(sch->schib.pmcw.chpid[chp])) | 53 | chpid.id = sch->schib.pmcw.chpid[chp]; |
54 | if (!get_chp_status(chpid)) | ||
49 | /* disable using this path */ | 55 | /* disable using this path */ |
50 | sch->opm &= ~mask; | 56 | sch->opm &= ~mask; |
51 | } | 57 | } |
52 | } | 58 | } |
53 | 59 | ||
54 | void | 60 | void chpid_is_actually_online(struct chp_id chpid) |
55 | chpid_is_actually_online(int chp) | ||
56 | { | 61 | { |
57 | int state; | 62 | int state; |
58 | 63 | ||
59 | state = get_chp_status(chp); | 64 | state = get_chp_status(chpid); |
60 | if (state < 0) { | 65 | if (state < 0) { |
61 | need_rescan = 1; | 66 | need_rescan = 1; |
62 | queue_work(slow_path_wq, &slow_path_work); | 67 | queue_work(slow_path_wq, &slow_path_work); |
@@ -200,11 +205,14 @@ css_get_ssd_info(struct subchannel *sch) | |||
200 | spin_unlock_irq(sch->lock); | 205 | spin_unlock_irq(sch->lock); |
201 | free_page((unsigned long)page); | 206 | free_page((unsigned long)page); |
202 | if (!ret) { | 207 | if (!ret) { |
203 | int j, chpid, mask; | 208 | int j, mask; |
209 | struct chp_id chpid; | ||
210 | |||
211 | chp_id_init(&chpid); | ||
204 | /* Allocate channel path structures, if needed. */ | 212 | /* Allocate channel path structures, if needed. */ |
205 | for (j = 0; j < 8; j++) { | 213 | for (j = 0; j < 8; j++) { |
206 | mask = 0x80 >> j; | 214 | mask = 0x80 >> j; |
207 | chpid = sch->ssd_info.chpid[j]; | 215 | chpid.id = sch->ssd_info.chpid[j]; |
208 | if ((sch->schib.pmcw.pim & mask) && | 216 | if ((sch->schib.pmcw.pim & mask) && |
209 | (get_chp_status(chpid) < 0)) | 217 | (get_chp_status(chpid) < 0)) |
210 | new_channel_path(chpid); | 218 | new_channel_path(chpid); |
@@ -227,7 +235,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) | |||
227 | for (j = 0; j < 8; j++) { | 235 | for (j = 0; j < 8; j++) { |
228 | mask = 0x80 >> j; | 236 | mask = 0x80 >> j; |
229 | if ((sch->schib.pmcw.pim & mask) && | 237 | if ((sch->schib.pmcw.pim & mask) && |
230 | (sch->schib.pmcw.chpid[j] == chpid->id)) | 238 | (sch->schib.pmcw.chpid[j] == chpid->chpid.id)) |
231 | break; | 239 | break; |
232 | } | 240 | } |
233 | if (j >= 8) | 241 | if (j >= 8) |
@@ -277,18 +285,17 @@ out_unreg: | |||
277 | return 0; | 285 | return 0; |
278 | } | 286 | } |
279 | 287 | ||
280 | static void | 288 | static void s390_set_chpid_offline(struct chp_id chpid) |
281 | s390_set_chpid_offline( __u8 chpid) | ||
282 | { | 289 | { |
283 | char dbf_txt[15]; | 290 | char dbf_txt[15]; |
284 | struct device *dev; | 291 | struct device *dev; |
285 | 292 | ||
286 | sprintf(dbf_txt, "chpr%x", chpid); | 293 | sprintf(dbf_txt, "chpr%x.%02x", chpid.cssid, chpid.id); |
287 | CIO_TRACE_EVENT(2, dbf_txt); | 294 | CIO_TRACE_EVENT(2, dbf_txt); |
288 | 295 | ||
289 | if (get_chp_status(chpid) <= 0) | 296 | if (get_chp_status(chpid) <= 0) |
290 | return; | 297 | return; |
291 | dev = get_device(&css[0]->chps[chpid]->dev); | 298 | dev = get_device(&(chpid_to_chp(chpid)->dev)); |
292 | bus_for_each_dev(&css_bus_type, NULL, to_channelpath(dev), | 299 | bus_for_each_dev(&css_bus_type, NULL, to_channelpath(dev), |
293 | s390_subchannel_remove_chpid); | 300 | s390_subchannel_remove_chpid); |
294 | 301 | ||
@@ -316,7 +323,7 @@ s390_process_res_acc_sch(struct res_acc_data *res_data, struct subchannel *sch) | |||
316 | * check if chpid is in information updated by ssd | 323 | * check if chpid is in information updated by ssd |
317 | */ | 324 | */ |
318 | if (sch->ssd_info.valid && | 325 | if (sch->ssd_info.valid && |
319 | sch->ssd_info.chpid[chp] == res_data->chp->id && | 326 | sch->ssd_info.chpid[chp] == res_data->chp->chpid.id && |
320 | (sch->ssd_info.fla[chp] & res_data->fla_mask) | 327 | (sch->ssd_info.fla[chp] & res_data->fla_mask) |
321 | == res_data->fla) { | 328 | == res_data->fla) { |
322 | found = 1; | 329 | found = 1; |
@@ -409,7 +416,8 @@ s390_process_res_acc (struct res_acc_data *res_data) | |||
409 | int rc; | 416 | int rc; |
410 | char dbf_txt[15]; | 417 | char dbf_txt[15]; |
411 | 418 | ||
412 | sprintf(dbf_txt, "accpr%x", res_data->chp->id); | 419 | sprintf(dbf_txt, "accpr%x.%02x", res_data->chp->chpid.cssid, |
420 | res_data->chp->chpid.id); | ||
413 | CIO_TRACE_EVENT( 2, dbf_txt); | 421 | CIO_TRACE_EVENT( 2, dbf_txt); |
414 | if (res_data->fla != 0) { | 422 | if (res_data->fla != 0) { |
415 | sprintf(dbf_txt, "fla%x", res_data->fla); | 423 | sprintf(dbf_txt, "fla%x", res_data->fla); |
@@ -482,17 +490,21 @@ struct chsc_sei_area { | |||
482 | 490 | ||
483 | static int chsc_process_sei_link_incident(struct chsc_sei_area *sei_area) | 491 | static int chsc_process_sei_link_incident(struct chsc_sei_area *sei_area) |
484 | { | 492 | { |
485 | int chpid; | 493 | struct chp_id chpid; |
494 | int id; | ||
486 | 495 | ||
487 | CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x)\n", | 496 | CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x)\n", |
488 | sei_area->rs, sei_area->rsid); | 497 | sei_area->rs, sei_area->rsid); |
489 | if (sei_area->rs != 4) | 498 | if (sei_area->rs != 4) |
490 | return 0; | 499 | return 0; |
491 | chpid = __get_chpid_from_lir(sei_area->ccdf); | 500 | id = __get_chpid_from_lir(sei_area->ccdf); |
492 | if (chpid < 0) | 501 | if (id < 0) |
493 | CIO_CRW_EVENT(4, "chsc: link incident - invalid LIR\n"); | 502 | CIO_CRW_EVENT(4, "chsc: link incident - invalid LIR\n"); |
494 | else | 503 | else { |
504 | chp_id_init(&chpid); | ||
505 | chpid.id = id; | ||
495 | s390_set_chpid_offline(chpid); | 506 | s390_set_chpid_offline(chpid); |
507 | } | ||
496 | 508 | ||
497 | return 0; | 509 | return 0; |
498 | } | 510 | } |
@@ -501,6 +513,7 @@ static int chsc_process_sei_res_acc(struct chsc_sei_area *sei_area) | |||
501 | { | 513 | { |
502 | struct res_acc_data res_data; | 514 | struct res_acc_data res_data; |
503 | struct device *dev; | 515 | struct device *dev; |
516 | struct chp_id chpid; | ||
504 | int status; | 517 | int status; |
505 | int rc; | 518 | int rc; |
506 | 519 | ||
@@ -508,13 +521,15 @@ static int chsc_process_sei_res_acc(struct chsc_sei_area *sei_area) | |||
508 | "rs_id=%04x)\n", sei_area->rs, sei_area->rsid); | 521 | "rs_id=%04x)\n", sei_area->rs, sei_area->rsid); |
509 | if (sei_area->rs != 4) | 522 | if (sei_area->rs != 4) |
510 | return 0; | 523 | return 0; |
524 | chp_id_init(&chpid); | ||
525 | chpid.id = sei_area->rsid; | ||
511 | /* allocate a new channel path structure, if needed */ | 526 | /* allocate a new channel path structure, if needed */ |
512 | status = get_chp_status(sei_area->rsid); | 527 | status = get_chp_status(chpid); |
513 | if (status < 0) | 528 | if (status < 0) |
514 | new_channel_path(sei_area->rsid); | 529 | new_channel_path(chpid); |
515 | else if (!status) | 530 | else if (!status) |
516 | return 0; | 531 | return 0; |
517 | dev = get_device(&css[0]->chps[sei_area->rsid]->dev); | 532 | dev = get_device(&(chpid_to_chp(chpid)->dev)); |
518 | memset(&res_data, 0, sizeof(struct res_acc_data)); | 533 | memset(&res_data, 0, sizeof(struct res_acc_data)); |
519 | res_data.chp = to_channelpath(dev); | 534 | res_data.chp = to_channelpath(dev); |
520 | if ((sei_area->vf & 0xc0) != 0) { | 535 | if ((sei_area->vf & 0xc0) != 0) { |
@@ -631,7 +646,7 @@ __chp_add(struct subchannel_id schid, void *data) | |||
631 | for (i=0; i<8; i++) { | 646 | for (i=0; i<8; i++) { |
632 | mask = 0x80 >> i; | 647 | mask = 0x80 >> i; |
633 | if ((sch->schib.pmcw.pim & mask) && | 648 | if ((sch->schib.pmcw.pim & mask) && |
634 | (sch->schib.pmcw.chpid[i] == chp->id)) { | 649 | (sch->schib.pmcw.chpid[i] == chp->chpid.id)) { |
635 | if (stsch(sch->schid, &sch->schib) != 0) { | 650 | if (stsch(sch->schid, &sch->schib) != 0) { |
636 | /* Endgame. */ | 651 | /* Endgame. */ |
637 | spin_unlock_irq(sch->lock); | 652 | spin_unlock_irq(sch->lock); |
@@ -657,8 +672,7 @@ __chp_add(struct subchannel_id schid, void *data) | |||
657 | return 0; | 672 | return 0; |
658 | } | 673 | } |
659 | 674 | ||
660 | static int | 675 | static int chp_add(struct chp_id chpid) |
661 | chp_add(int chpid) | ||
662 | { | 676 | { |
663 | int rc; | 677 | int rc; |
664 | char dbf_txt[15]; | 678 | char dbf_txt[15]; |
@@ -667,10 +681,10 @@ chp_add(int chpid) | |||
667 | if (!get_chp_status(chpid)) | 681 | if (!get_chp_status(chpid)) |
668 | return 0; /* no need to do the rest */ | 682 | return 0; /* no need to do the rest */ |
669 | 683 | ||
670 | sprintf(dbf_txt, "cadd%x", chpid); | 684 | sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id); |
671 | CIO_TRACE_EVENT(2, dbf_txt); | 685 | CIO_TRACE_EVENT(2, dbf_txt); |
672 | 686 | ||
673 | dev = get_device(&css[0]->chps[chpid]->dev); | 687 | dev = get_device(&(chpid_to_chp(chpid)->dev)); |
674 | rc = for_each_subchannel(__chp_add, to_channelpath(dev)); | 688 | rc = for_each_subchannel(__chp_add, to_channelpath(dev)); |
675 | if (css_slow_subchannels_exist()) | 689 | if (css_slow_subchannels_exist()) |
676 | rc = -EAGAIN; | 690 | rc = -EAGAIN; |
@@ -683,9 +697,12 @@ chp_add(int chpid) | |||
683 | /* | 697 | /* |
684 | * Handling of crw machine checks with channel path source. | 698 | * Handling of crw machine checks with channel path source. |
685 | */ | 699 | */ |
686 | int | 700 | int chp_process_crw(int id, int on) |
687 | chp_process_crw(int chpid, int on) | ||
688 | { | 701 | { |
702 | struct chp_id chpid; | ||
703 | |||
704 | chp_id_init(&chpid); | ||
705 | chpid.id = id; | ||
689 | if (on == 0) { | 706 | if (on == 0) { |
690 | /* Path has gone. We use the link incident routine.*/ | 707 | /* Path has gone. We use the link incident routine.*/ |
691 | s390_set_chpid_offline(chpid); | 708 | s390_set_chpid_offline(chpid); |
@@ -733,8 +750,8 @@ static void terminate_internal_io(struct subchannel *sch) | |||
733 | sch->driver->termination(&sch->dev); | 750 | sch->driver->termination(&sch->dev); |
734 | } | 751 | } |
735 | 752 | ||
736 | static void | 753 | static void __s390_subchannel_vary_chpid(struct subchannel *sch, |
737 | __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) | 754 | struct chp_id chpid, int on) |
738 | { | 755 | { |
739 | int chp, old_lpm; | 756 | int chp, old_lpm; |
740 | unsigned long flags; | 757 | unsigned long flags; |
@@ -745,7 +762,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) | |||
745 | spin_lock_irqsave(sch->lock, flags); | 762 | spin_lock_irqsave(sch->lock, flags); |
746 | old_lpm = sch->lpm; | 763 | old_lpm = sch->lpm; |
747 | for (chp = 0; chp < 8; chp++) { | 764 | for (chp = 0; chp < 8; chp++) { |
748 | if (sch->ssd_info.chpid[chp] != chpid) | 765 | if (sch->ssd_info.chpid[chp] != chpid.id) |
749 | continue; | 766 | continue; |
750 | 767 | ||
751 | if (on) { | 768 | if (on) { |
@@ -780,11 +797,10 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) | |||
780 | spin_unlock_irqrestore(sch->lock, flags); | 797 | spin_unlock_irqrestore(sch->lock, flags); |
781 | } | 798 | } |
782 | 799 | ||
783 | static int | 800 | static int s390_subchannel_vary_chpid_off(struct device *dev, void *data) |
784 | s390_subchannel_vary_chpid_off(struct device *dev, void *data) | ||
785 | { | 801 | { |
786 | struct subchannel *sch; | 802 | struct subchannel *sch; |
787 | __u8 *chpid; | 803 | struct chp_id *chpid; |
788 | 804 | ||
789 | sch = to_subchannel(dev); | 805 | sch = to_subchannel(dev); |
790 | chpid = data; | 806 | chpid = data; |
@@ -793,11 +809,10 @@ s390_subchannel_vary_chpid_off(struct device *dev, void *data) | |||
793 | return 0; | 809 | return 0; |
794 | } | 810 | } |
795 | 811 | ||
796 | static int | 812 | static int s390_subchannel_vary_chpid_on(struct device *dev, void *data) |
797 | s390_subchannel_vary_chpid_on(struct device *dev, void *data) | ||
798 | { | 813 | { |
799 | struct subchannel *sch; | 814 | struct subchannel *sch; |
800 | __u8 *chpid; | 815 | struct chp_id *chpid; |
801 | 816 | ||
802 | sch = to_subchannel(dev); | 817 | sch = to_subchannel(dev); |
803 | chpid = data; | 818 | chpid = data; |
@@ -833,23 +848,25 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data) | |||
833 | * Function: s390_vary_chpid | 848 | * Function: s390_vary_chpid |
834 | * Varies the specified chpid online or offline | 849 | * Varies the specified chpid online or offline |
835 | */ | 850 | */ |
836 | static int | 851 | static int s390_vary_chpid(struct chp_id chpid, int on) |
837 | s390_vary_chpid( __u8 chpid, int on) | ||
838 | { | 852 | { |
839 | char dbf_text[15]; | 853 | char dbf_text[15]; |
840 | int status; | 854 | int status; |
841 | 855 | ||
842 | sprintf(dbf_text, on?"varyon%x":"varyoff%x", chpid); | 856 | sprintf(dbf_text, on?"varyon%x.%02x":"varyoff%x.%02x", chpid.cssid, |
857 | chpid.id); | ||
843 | CIO_TRACE_EVENT( 2, dbf_text); | 858 | CIO_TRACE_EVENT( 2, dbf_text); |
844 | 859 | ||
845 | status = get_chp_status(chpid); | 860 | status = get_chp_status(chpid); |
846 | if (status < 0) { | 861 | if (status < 0) { |
847 | printk(KERN_ERR "Can't vary unknown chpid %02X\n", chpid); | 862 | printk(KERN_ERR "Can't vary unknown chpid %x.%02x\n", |
863 | chpid.cssid, chpid.id); | ||
848 | return -EINVAL; | 864 | return -EINVAL; |
849 | } | 865 | } |
850 | 866 | ||
851 | if (!on && !status) { | 867 | if (!on && !status) { |
852 | printk(KERN_ERR "chpid %x is already offline\n", chpid); | 868 | printk(KERN_ERR "chpid %x.%02x is already offline\n", |
869 | chpid.cssid, chpid.id); | ||
853 | return -EINVAL; | 870 | return -EINVAL; |
854 | } | 871 | } |
855 | 872 | ||
@@ -904,20 +921,19 @@ static struct bin_attribute chp_measurement_chars_attr = { | |||
904 | .read = chp_measurement_chars_read, | 921 | .read = chp_measurement_chars_read, |
905 | }; | 922 | }; |
906 | 923 | ||
907 | static void | 924 | static void chp_measurement_copy_block(struct cmg_entry *buf, |
908 | chp_measurement_copy_block(struct cmg_entry *buf, | 925 | struct channel_subsystem *css, struct chp_id chpid) |
909 | struct channel_subsystem *css, int chpid) | ||
910 | { | 926 | { |
911 | void *area; | 927 | void *area; |
912 | struct cmg_entry *entry, reference_buf; | 928 | struct cmg_entry *entry, reference_buf; |
913 | int idx; | 929 | int idx; |
914 | 930 | ||
915 | if (chpid < 128) { | 931 | if (chpid.id < 128) { |
916 | area = css->cub_addr1; | 932 | area = css->cub_addr1; |
917 | idx = chpid; | 933 | idx = chpid.id; |
918 | } else { | 934 | } else { |
919 | area = css->cub_addr2; | 935 | area = css->cub_addr2; |
920 | idx = chpid - 128; | 936 | idx = chpid.id - 128; |
921 | } | 937 | } |
922 | entry = area + (idx * sizeof(struct cmg_entry)); | 938 | entry = area + (idx * sizeof(struct cmg_entry)); |
923 | do { | 939 | do { |
@@ -941,7 +957,7 @@ chp_measurement_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
941 | /* Only allow single reads. */ | 957 | /* Only allow single reads. */ |
942 | if (off || count < size) | 958 | if (off || count < size) |
943 | return 0; | 959 | return 0; |
944 | chp_measurement_copy_block((struct cmg_entry *)buf, css, chp->id); | 960 | chp_measurement_copy_block((struct cmg_entry *)buf, css, chp->chpid); |
945 | count = size; | 961 | count = size; |
946 | return count; | 962 | return count; |
947 | } | 963 | } |
@@ -1137,7 +1153,7 @@ chp_status_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
1137 | 1153 | ||
1138 | if (!chp) | 1154 | if (!chp) |
1139 | return 0; | 1155 | return 0; |
1140 | return (get_chp_status(chp->id) ? sprintf(buf, "online\n") : | 1156 | return (get_chp_status(chp->chpid) ? sprintf(buf, "online\n") : |
1141 | sprintf(buf, "offline\n")); | 1157 | sprintf(buf, "offline\n")); |
1142 | } | 1158 | } |
1143 | 1159 | ||
@@ -1154,9 +1170,9 @@ chp_status_write(struct device *dev, struct device_attribute *attr, const char * | |||
1154 | return count; | 1170 | return count; |
1155 | 1171 | ||
1156 | if (!strnicmp(cmd, "on", 2)) | 1172 | if (!strnicmp(cmd, "on", 2)) |
1157 | error = s390_vary_chpid(cp->id, 1); | 1173 | error = s390_vary_chpid(cp->chpid, 1); |
1158 | else if (!strnicmp(cmd, "off", 3)) | 1174 | else if (!strnicmp(cmd, "off", 3)) |
1159 | error = s390_vary_chpid(cp->id, 0); | 1175 | error = s390_vary_chpid(cp->chpid, 0); |
1160 | else | 1176 | else |
1161 | error = -EINVAL; | 1177 | error = -EINVAL; |
1162 | 1178 | ||
@@ -1227,9 +1243,8 @@ chp_release(struct device *dev) | |||
1227 | kfree(cp); | 1243 | kfree(cp); |
1228 | } | 1244 | } |
1229 | 1245 | ||
1230 | static int | 1246 | static int chsc_determine_channel_path_description(struct chp_id chpid, |
1231 | chsc_determine_channel_path_description(int chpid, | 1247 | struct channel_path_desc *desc) |
1232 | struct channel_path_desc *desc) | ||
1233 | { | 1248 | { |
1234 | int ccode, ret; | 1249 | int ccode, ret; |
1235 | 1250 | ||
@@ -1252,8 +1267,8 @@ chsc_determine_channel_path_description(int chpid, | |||
1252 | scpd_area->request.length = 0x0010; | 1267 | scpd_area->request.length = 0x0010; |
1253 | scpd_area->request.code = 0x0002; | 1268 | scpd_area->request.code = 0x0002; |
1254 | 1269 | ||
1255 | scpd_area->first_chpid = chpid; | 1270 | scpd_area->first_chpid = chpid.id; |
1256 | scpd_area->last_chpid = chpid; | 1271 | scpd_area->last_chpid = chpid.id; |
1257 | 1272 | ||
1258 | ccode = chsc(scpd_area); | 1273 | ccode = chsc(scpd_area); |
1259 | if (ccode > 0) { | 1274 | if (ccode > 0) { |
@@ -1349,8 +1364,8 @@ chsc_get_channel_measurement_chars(struct channel_path *chp) | |||
1349 | scmc_area->request.length = 0x0010; | 1364 | scmc_area->request.length = 0x0010; |
1350 | scmc_area->request.code = 0x0022; | 1365 | scmc_area->request.code = 0x0022; |
1351 | 1366 | ||
1352 | scmc_area->first_chpid = chp->id; | 1367 | scmc_area->first_chpid = chp->chpid.id; |
1353 | scmc_area->last_chpid = chp->id; | 1368 | scmc_area->last_chpid = chp->chpid.id; |
1354 | 1369 | ||
1355 | ccode = chsc(scmc_area); | 1370 | ccode = chsc(scmc_area); |
1356 | if (ccode > 0) { | 1371 | if (ccode > 0) { |
@@ -1396,8 +1411,7 @@ out: | |||
1396 | * Entries for chpids on the system bus. | 1411 | * Entries for chpids on the system bus. |
1397 | * This replaces /proc/chpids. | 1412 | * This replaces /proc/chpids. |
1398 | */ | 1413 | */ |
1399 | static int | 1414 | static int new_channel_path(struct chp_id chpid) |
1400 | new_channel_path(int chpid) | ||
1401 | { | 1415 | { |
1402 | struct channel_path *chp; | 1416 | struct channel_path *chp; |
1403 | int ret; | 1417 | int ret; |
@@ -1407,11 +1421,12 @@ new_channel_path(int chpid) | |||
1407 | return -ENOMEM; | 1421 | return -ENOMEM; |
1408 | 1422 | ||
1409 | /* fill in status, etc. */ | 1423 | /* fill in status, etc. */ |
1410 | chp->id = chpid; | 1424 | chp->chpid = chpid; |
1411 | chp->state = 1; | 1425 | chp->state = 1; |
1412 | chp->dev.parent = &css[0]->device; | 1426 | chp->dev.parent = &css[chpid.cssid]->device; |
1413 | chp->dev.release = chp_release; | 1427 | chp->dev.release = chp_release; |
1414 | snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid); | 1428 | snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp%x.%02x", chpid.cssid, |
1429 | chpid.id); | ||
1415 | 1430 | ||
1416 | /* Obtain channel path description and fill it in. */ | 1431 | /* Obtain channel path description and fill it in. */ |
1417 | ret = chsc_determine_channel_path_description(chpid, &chp->desc); | 1432 | ret = chsc_determine_channel_path_description(chpid, &chp->desc); |
@@ -1437,8 +1452,8 @@ new_channel_path(int chpid) | |||
1437 | /* make it known to the system */ | 1452 | /* make it known to the system */ |
1438 | ret = device_register(&chp->dev); | 1453 | ret = device_register(&chp->dev); |
1439 | if (ret) { | 1454 | if (ret) { |
1440 | printk(KERN_WARNING "%s: could not register %02x\n", | 1455 | printk(KERN_WARNING "%s: could not register %x.%02x\n", |
1441 | __func__, chpid); | 1456 | __func__, chpid.cssid, chpid.id); |
1442 | goto out_free; | 1457 | goto out_free; |
1443 | } | 1458 | } |
1444 | ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group); | 1459 | ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group); |
@@ -1446,18 +1461,18 @@ new_channel_path(int chpid) | |||
1446 | device_unregister(&chp->dev); | 1461 | device_unregister(&chp->dev); |
1447 | goto out_free; | 1462 | goto out_free; |
1448 | } | 1463 | } |
1449 | mutex_lock(&css[0]->mutex); | 1464 | mutex_lock(&css[chpid.cssid]->mutex); |
1450 | if (css[0]->cm_enabled) { | 1465 | if (css[chpid.cssid]->cm_enabled) { |
1451 | ret = chsc_add_chp_cmg_attr(chp); | 1466 | ret = chsc_add_chp_cmg_attr(chp); |
1452 | if (ret) { | 1467 | if (ret) { |
1453 | sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); | 1468 | sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); |
1454 | device_unregister(&chp->dev); | 1469 | device_unregister(&chp->dev); |
1455 | mutex_unlock(&css[0]->mutex); | 1470 | mutex_unlock(&css[chpid.cssid]->mutex); |
1456 | goto out_free; | 1471 | goto out_free; |
1457 | } | 1472 | } |
1458 | } | 1473 | } |
1459 | css[0]->chps[chpid] = chp; | 1474 | css[chpid.cssid]->chps[chpid.id] = chp; |
1460 | mutex_unlock(&css[0]->mutex); | 1475 | mutex_unlock(&css[chpid.cssid]->mutex); |
1461 | return ret; | 1476 | return ret; |
1462 | out_free: | 1477 | out_free: |
1463 | kfree(chp); | 1478 | kfree(chp); |
@@ -1469,8 +1484,11 @@ chsc_get_chp_desc(struct subchannel *sch, int chp_no) | |||
1469 | { | 1484 | { |
1470 | struct channel_path *chp; | 1485 | struct channel_path *chp; |
1471 | struct channel_path_desc *desc; | 1486 | struct channel_path_desc *desc; |
1487 | struct chp_id chpid; | ||
1472 | 1488 | ||
1473 | chp = css[0]->chps[sch->schib.pmcw.chpid[chp_no]]; | 1489 | chp_id_init(&chpid); |
1490 | chpid.id = sch->schib.pmcw.chpid[chp_no]; | ||
1491 | chp = chpid_to_chp(chpid); | ||
1474 | if (!chp) | 1492 | if (!chp) |
1475 | return NULL; | 1493 | return NULL; |
1476 | desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL); | 1494 | desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL); |