aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Oberparleiter <peter.oberparleiter@de.ibm.com>2007-04-27 10:01:26 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-04-27 10:01:38 -0400
commitf86635fad14c4a6810cf0e08488fc9129a3b3b32 (patch)
treeabd431344a28415983f6dcabdc3ac3ce5675e519
parent6fc321fd7dd91f0592f37503219196835314fbb7 (diff)
[S390] cio: Introduce struct chp_id.
Introduce data type for channel-path IDs. Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
-rw-r--r--drivers/s390/cio/chpid.h51
-rw-r--r--drivers/s390/cio/chsc.c178
-rw-r--r--drivers/s390/cio/chsc.h8
-rw-r--r--drivers/s390/cio/cio.c5
-rw-r--r--drivers/s390/cio/device_fsm.c6
-rw-r--r--drivers/s390/cio/ioasm.h5
6 files changed, 167 insertions, 86 deletions
diff --git a/drivers/s390/cio/chpid.h b/drivers/s390/cio/chpid.h
new file mode 100644
index 000000000000..44cc00ed9b59
--- /dev/null
+++ b/drivers/s390/cio/chpid.h
@@ -0,0 +1,51 @@
1/*
2 * drivers/s390/cio/chpid.h
3 *
4 * Copyright IBM Corp. 2007
5 * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
6 */
7
8#ifndef S390_CHP_ID_H
9#define S390_CHP_ID_H S390_CHP_ID_H
10
11#include <linux/string.h>
12#include <asm/types.h>
13#include "css.h"
14
15struct chp_id {
16 u8 reserved1;
17 u8 cssid;
18 u8 reserved2;
19 u8 id;
20} __attribute__((packed));
21
22static inline void chp_id_init(struct chp_id *chpid)
23{
24 memset(chpid, 0, sizeof(struct chp_id));
25}
26
27static inline int chp_id_is_equal(struct chp_id *a, struct chp_id *b)
28{
29 return (a->id == b->id) && (a->cssid == b->cssid);
30}
31
32static inline void chp_id_next(struct chp_id *chpid)
33{
34 if (chpid->id < __MAX_CHPID)
35 chpid->id++;
36 else {
37 chpid->id = 0;
38 chpid->cssid++;
39 }
40}
41
42static inline int chp_id_is_valid(struct chp_id *chpid)
43{
44 return (chpid->cssid <= __MAX_CSSID);
45}
46
47
48#define chp_id_for_each(c) \
49 for (chp_id_init(c); chp_id_is_valid(c); chp_id_next(c))
50
51#endif /* S390_CHP_ID_H */
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
25static void *sei_page; 26static void *sei_page;
26 27
27static int new_channel_path(int chpid); 28static int new_channel_path(struct chp_id chpid);
28 29
29static inline void 30static inline struct channel_path *chpid_to_chp(struct chp_id chpid)
30set_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
35static int 35static void set_chp_logically_online(struct chp_id chpid, int onoff)
36get_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
41void 40static int get_chp_status(struct chp_id chpid)
42chsc_validate_chpids(struct subchannel *sch) 41{
42 return (chpid_to_chp(chpid) ? chpid_to_chp(chpid)->state : -ENODEV);
43}
44
45void 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
54void 60void chpid_is_actually_online(struct chp_id chpid)
55chpid_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
280static void 288static void s390_set_chpid_offline(struct chp_id chpid)
281s390_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
483static int chsc_process_sei_link_incident(struct chsc_sei_area *sei_area) 491static 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
660static int 675static int chp_add(struct chp_id chpid)
661chp_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 */
686int 700int chp_process_crw(int id, int on)
687chp_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
736static void 753static 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
783static int 800static int s390_subchannel_vary_chpid_off(struct device *dev, void *data)
784s390_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
796static int 812static int s390_subchannel_vary_chpid_on(struct device *dev, void *data)
797s390_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 */
836static int 851static int s390_vary_chpid(struct chp_id chpid, int on)
837s390_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
907static void 924static void chp_measurement_copy_block(struct cmg_entry *buf,
908chp_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
1230static int 1246static int chsc_determine_channel_path_description(struct chp_id chpid,
1231chsc_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 */
1399static int 1414static int new_channel_path(struct chp_id chpid)
1400new_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;
1462out_free: 1477out_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);
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 0fb2b024208f..2949c85b6d92 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -1,6 +1,10 @@
1#ifndef S390_CHSC_H 1#ifndef S390_CHSC_H
2#define S390_CHSC_H 2#define S390_CHSC_H
3 3
4#include <linux/types.h>
5#include <linux/device.h>
6#include "chpid.h"
7
4#define CHSC_SEI_ACC_CHPID 1 8#define CHSC_SEI_ACC_CHPID 1
5#define CHSC_SEI_ACC_LINKADDR 2 9#define CHSC_SEI_ACC_LINKADDR 2
6#define CHSC_SEI_ACC_FULLLINKADDR 3 10#define CHSC_SEI_ACC_FULLLINKADDR 3
@@ -34,7 +38,7 @@ struct channel_path_desc {
34} __attribute__ ((packed)); 38} __attribute__ ((packed));
35 39
36struct channel_path { 40struct channel_path {
37 int id; 41 struct chp_id chpid;
38 int state; 42 int state;
39 struct channel_path_desc desc; 43 struct channel_path_desc desc;
40 /* Channel-measurement related stuff: */ 44 /* Channel-measurement related stuff: */
@@ -46,7 +50,7 @@ struct channel_path {
46 50
47extern void s390_process_css( void ); 51extern void s390_process_css( void );
48extern void chsc_validate_chpids(struct subchannel *); 52extern void chsc_validate_chpids(struct subchannel *);
49extern void chpid_is_actually_online(int); 53extern void chpid_is_actually_online(struct chp_id);
50extern int css_get_ssd_info(struct subchannel *); 54extern int css_get_ssd_info(struct subchannel *);
51extern int chsc_process_crw(void); 55extern int chsc_process_crw(void);
52extern int chp_process_crw(int, int); 56extern int chp_process_crw(int, int);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 21af446c1f2d..bab729202f49 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -954,6 +954,7 @@ static void css_reset(void)
954{ 954{
955 int i, ret; 955 int i, ret;
956 unsigned long long timeout; 956 unsigned long long timeout;
957 struct chp_id chpid;
957 958
958 /* Reset subchannels. */ 959 /* Reset subchannels. */
959 for_each_subchannel(__shutdown_subchannel_easy, NULL); 960 for_each_subchannel(__shutdown_subchannel_easy, NULL);
@@ -963,8 +964,10 @@ static void css_reset(void)
963 __ctl_set_bit(14, 28); 964 __ctl_set_bit(14, 28);
964 /* Temporarily reenable machine checks. */ 965 /* Temporarily reenable machine checks. */
965 local_mcck_enable(); 966 local_mcck_enable();
967 chp_id_init(&chpid);
966 for (i = 0; i <= __MAX_CHPID; i++) { 968 for (i = 0; i <= __MAX_CHPID; i++) {
967 ret = rchp(i); 969 chpid.id = i;
970 ret = rchp(chpid);
968 if ((ret == 0) || (ret == 2)) 971 if ((ret == 0) || (ret == 2))
969 /* 972 /*
970 * rchp either succeeded, or another rchp is already 973 * rchp either succeeded, or another rchp is already
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 089a3ddd6265..5f5ee1eef07a 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -22,6 +22,7 @@
22#include "device.h" 22#include "device.h"
23#include "chsc.h" 23#include "chsc.h"
24#include "ioasm.h" 24#include "ioasm.h"
25#include "chpid.h"
25 26
26int 27int
27device_is_online(struct subchannel *sch) 28device_is_online(struct subchannel *sch)
@@ -210,14 +211,17 @@ static void
210__recover_lost_chpids(struct subchannel *sch, int old_lpm) 211__recover_lost_chpids(struct subchannel *sch, int old_lpm)
211{ 212{
212 int mask, i; 213 int mask, i;
214 struct chp_id chpid;
213 215
216 chp_id_init(&chpid);
214 for (i = 0; i<8; i++) { 217 for (i = 0; i<8; i++) {
215 mask = 0x80 >> i; 218 mask = 0x80 >> i;
216 if (!(sch->lpm & mask)) 219 if (!(sch->lpm & mask))
217 continue; 220 continue;
218 if (old_lpm & mask) 221 if (old_lpm & mask)
219 continue; 222 continue;
220 chpid_is_actually_online(sch->schib.pmcw.chpid[i]); 223 chpid.id = sch->schib.pmcw.chpid[i];
224 chpid_is_actually_online(chpid);
221 } 225 }
222} 226}
223 227
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index ad6d82940069..78c7db6daa84 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -2,6 +2,7 @@
2#define S390_CIO_IOASM_H 2#define S390_CIO_IOASM_H
3 3
4#include "schid.h" 4#include "schid.h"
5#include "chpid.h"
5 6
6/* 7/*
7 * TPI info structure 8 * TPI info structure
@@ -189,9 +190,9 @@ static inline int chsc(void *chsc_area)
189 return cc; 190 return cc;
190} 191}
191 192
192static inline int rchp(int chpid) 193static inline int rchp(struct chp_id chpid)
193{ 194{
194 register unsigned int reg1 asm ("1") = chpid; 195 register struct chp_id reg1 asm ("1") = chpid;
195 int ccode; 196 int ccode;
196 197
197 asm volatile( 198 asm volatile(