aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/cio/chsc.c32
-rw-r--r--drivers/s390/cio/chsc.h5
-rw-r--r--drivers/s390/cio/css.c67
-rw-r--r--drivers/s390/cio/css.h25
-rw-r--r--drivers/s390/cio/device.c4
-rw-r--r--drivers/s390/cio/device_pgid.c2
6 files changed, 90 insertions, 45 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 78e082311f48..ebd924962df0 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -24,8 +24,6 @@
24#include "ioasm.h" 24#include "ioasm.h"
25#include "chsc.h" 25#include "chsc.h"
26 26
27static struct channel_path *chps[NR_CHPIDS];
28
29static void *sei_page; 27static void *sei_page;
30 28
31static int new_channel_path(int chpid); 29static int new_channel_path(int chpid);
@@ -33,13 +31,13 @@ static int new_channel_path(int chpid);
33static inline void 31static inline void
34set_chp_logically_online(int chp, int onoff) 32set_chp_logically_online(int chp, int onoff)
35{ 33{
36 chps[chp]->state = onoff; 34 css[0]->chps[chp]->state = onoff;
37} 35}
38 36
39static int 37static int
40get_chp_status(int chp) 38get_chp_status(int chp)
41{ 39{
42 return (chps[chp] ? chps[chp]->state : -ENODEV); 40 return (css[0]->chps[chp] ? css[0]->chps[chp]->state : -ENODEV);
43} 41}
44 42
45void 43void
@@ -219,13 +217,13 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
219 int j; 217 int j;
220 int mask; 218 int mask;
221 struct subchannel *sch; 219 struct subchannel *sch;
222 __u8 *chpid; 220 struct channel_path *chpid;
223 struct schib schib; 221 struct schib schib;
224 222
225 sch = to_subchannel(dev); 223 sch = to_subchannel(dev);
226 chpid = data; 224 chpid = data;
227 for (j = 0; j < 8; j++) 225 for (j = 0; j < 8; j++)
228 if (sch->schib.pmcw.chpid[j] == *chpid) 226 if (sch->schib.pmcw.chpid[j] == chpid->id)
229 break; 227 break;
230 if (j >= 8) 228 if (j >= 8)
231 return 0; 229 return 0;
@@ -296,18 +294,20 @@ static inline void
296s390_set_chpid_offline( __u8 chpid) 294s390_set_chpid_offline( __u8 chpid)
297{ 295{
298 char dbf_txt[15]; 296 char dbf_txt[15];
297 struct device *dev;
299 298
300 sprintf(dbf_txt, "chpr%x", chpid); 299 sprintf(dbf_txt, "chpr%x", chpid);
301 CIO_TRACE_EVENT(2, dbf_txt); 300 CIO_TRACE_EVENT(2, dbf_txt);
302 301
303 if (get_chp_status(chpid) <= 0) 302 if (get_chp_status(chpid) <= 0)
304 return; 303 return;
305 304 dev = get_device(&css[0]->chps[chpid]->dev);
306 bus_for_each_dev(&css_bus_type, NULL, &chpid, 305 bus_for_each_dev(&css_bus_type, NULL, to_channelpath(dev),
307 s390_subchannel_remove_chpid); 306 s390_subchannel_remove_chpid);
308 307
309 if (need_rescan || css_slow_subchannels_exist()) 308 if (need_rescan || css_slow_subchannels_exist())
310 queue_work(slow_path_wq, &slow_path_work); 309 queue_work(slow_path_wq, &slow_path_work);
310 put_device(dev);
311} 311}
312 312
313struct res_acc_data { 313struct res_acc_data {
@@ -511,6 +511,7 @@ chsc_process_crw(void)
511 ret = 0; 511 ret = 0;
512 do { 512 do {
513 int ccode, status; 513 int ccode, status;
514 struct device *dev;
514 memset(sei_area, 0, sizeof(*sei_area)); 515 memset(sei_area, 0, sizeof(*sei_area));
515 memset(&res_data, 0, sizeof(struct res_acc_data)); 516 memset(&res_data, 0, sizeof(struct res_acc_data));
516 sei_area->request = (struct chsc_header) { 517 sei_area->request = (struct chsc_header) {
@@ -586,7 +587,8 @@ chsc_process_crw(void)
586 new_channel_path(sei_area->rsid); 587 new_channel_path(sei_area->rsid);
587 else if (!status) 588 else if (!status)
588 break; 589 break;
589 res_data.chp = chps[sei_area->rsid]; 590 dev = get_device(&css[0]->chps[sei_area->rsid]->dev);
591 res_data.chp = to_channelpath(dev);
590 pr_debug("chpid: %x", sei_area->rsid); 592 pr_debug("chpid: %x", sei_area->rsid);
591 if ((sei_area->vf & 0xc0) != 0) { 593 if ((sei_area->vf & 0xc0) != 0) {
592 res_data.fla = sei_area->fla; 594 res_data.fla = sei_area->fla;
@@ -602,6 +604,7 @@ chsc_process_crw(void)
602 } 604 }
603 ret = s390_process_res_acc(&res_data); 605 ret = s390_process_res_acc(&res_data);
604 pr_debug("\n\n"); 606 pr_debug("\n\n");
607 put_device(dev);
605 break; 608 break;
606 609
607 default: /* other stuff */ 610 default: /* other stuff */
@@ -678,6 +681,7 @@ chp_add(int chpid)
678{ 681{
679 int rc; 682 int rc;
680 char dbf_txt[15]; 683 char dbf_txt[15];
684 struct device *dev;
681 685
682 if (!get_chp_status(chpid)) 686 if (!get_chp_status(chpid))
683 return 0; /* no need to do the rest */ 687 return 0; /* no need to do the rest */
@@ -685,11 +689,13 @@ chp_add(int chpid)
685 sprintf(dbf_txt, "cadd%x", chpid); 689 sprintf(dbf_txt, "cadd%x", chpid);
686 CIO_TRACE_EVENT(2, dbf_txt); 690 CIO_TRACE_EVENT(2, dbf_txt);
687 691
688 rc = for_each_subchannel(__chp_add, chps[chpid]); 692 dev = get_device(&css[0]->chps[chpid]->dev);
693 rc = for_each_subchannel(__chp_add, to_channelpath(dev));
689 if (css_slow_subchannels_exist()) 694 if (css_slow_subchannels_exist())
690 rc = -EAGAIN; 695 rc = -EAGAIN;
691 if (rc != -EAGAIN) 696 if (rc != -EAGAIN)
692 rc = 0; 697 rc = 0;
698 put_device(dev);
693 return rc; 699 return rc;
694} 700}
695 701
@@ -1016,7 +1022,7 @@ new_channel_path(int chpid)
1016 chp->id = chpid; 1022 chp->id = chpid;
1017 chp->state = 1; 1023 chp->state = 1;
1018 chp->dev = (struct device) { 1024 chp->dev = (struct device) {
1019 .parent = &css_bus_device, 1025 .parent = &css[0]->device,
1020 .release = chp_release, 1026 .release = chp_release,
1021 }; 1027 };
1022 snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid); 1028 snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid);
@@ -1038,7 +1044,7 @@ new_channel_path(int chpid)
1038 device_unregister(&chp->dev); 1044 device_unregister(&chp->dev);
1039 goto out_free; 1045 goto out_free;
1040 } else 1046 } else
1041 chps[chpid] = chp; 1047 css[0]->chps[chpid] = chp;
1042 return ret; 1048 return ret;
1043out_free: 1049out_free:
1044 kfree(chp); 1050 kfree(chp);
@@ -1051,7 +1057,7 @@ chsc_get_chp_desc(struct subchannel *sch, int chp_no)
1051 struct channel_path *chp; 1057 struct channel_path *chp;
1052 struct channel_path_desc *desc; 1058 struct channel_path_desc *desc;
1053 1059
1054 chp = chps[sch->schib.pmcw.chpid[chp_no]]; 1060 chp = css[0]->chps[sch->schib.pmcw.chpid[chp_no]];
1055 if (!chp) 1061 if (!chp)
1056 return NULL; 1062 return NULL;
1057 desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL); 1063 desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL);
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 69450134bec7..170083ca4349 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -1,8 +1,6 @@
1#ifndef S390_CHSC_H 1#ifndef S390_CHSC_H
2#define S390_CHSC_H 2#define S390_CHSC_H
3 3
4#define NR_CHPIDS 256
5
6#define CHSC_SEI_ACC_CHPID 1 4#define CHSC_SEI_ACC_CHPID 1
7#define CHSC_SEI_ACC_LINKADDR 2 5#define CHSC_SEI_ACC_LINKADDR 2
8#define CHSC_SEI_ACC_FULLLINKADDR 3 6#define CHSC_SEI_ACC_FULLLINKADDR 3
@@ -65,4 +63,7 @@ extern int chsc_determine_css_characteristics(void);
65extern int css_characteristics_avail; 63extern int css_characteristics_avail;
66 64
67extern void *chsc_get_chp_desc(struct subchannel*, int); 65extern void *chsc_get_chp_desc(struct subchannel*, int);
66
67#define to_channelpath(dev) container_of(dev, struct channel_path, dev)
68
68#endif 69#endif
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index dba632a5f71f..b6225cbbbee7 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -24,12 +24,9 @@
24int need_rescan = 0; 24int need_rescan = 0;
25int css_init_done = 0; 25int css_init_done = 0;
26 26
27struct pgid global_pgid; 27struct channel_subsystem *css[__MAX_CSSID + 1];
28int css_characteristics_avail = 0;
29 28
30struct device css_bus_device = { 29int css_characteristics_avail = 0;
31 .bus_id = "css0",
32};
33 30
34inline int 31inline int
35for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data) 32for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
@@ -112,7 +109,7 @@ css_register_subchannel(struct subchannel *sch)
112 int ret; 109 int ret;
113 110
114 /* Initialize the subchannel structure */ 111 /* Initialize the subchannel structure */
115 sch->dev.parent = &css_bus_device; 112 sch->dev.parent = &css[0]->device;
116 sch->dev.bus = &css_bus_type; 113 sch->dev.bus = &css_bus_type;
117 sch->dev.release = &css_subchannel_release; 114 sch->dev.release = &css_subchannel_release;
118 115
@@ -421,21 +418,35 @@ __init_channel_subsystem(struct subchannel_id schid, void *data)
421} 418}
422 419
423static void __init 420static void __init
424css_generate_pgid(void) 421css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
425{ 422{
426 /* Let's build our path group ID here. */ 423 if (css_characteristics_avail && css_general_characteristics.mcss) {
427 if (css_characteristics_avail && css_general_characteristics.mcss) 424 css->global_pgid.pgid_high.ext_cssid.version = 0x80;
428 global_pgid.cpu_addr = 0x8000; 425 css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid;
429 else { 426 } else {
430#ifdef CONFIG_SMP 427#ifdef CONFIG_SMP
431 global_pgid.cpu_addr = hard_smp_processor_id(); 428 css->global_pgid.pgid_high.cpu_addr = hard_smp_processor_id();
432#else 429#else
433 global_pgid.cpu_addr = 0; 430 css->global_pgid.pgid_high.cpu_addr = 0;
434#endif 431#endif
435 } 432 }
436 global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident; 433 css->global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident;
437 global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine; 434 css->global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine;
438 global_pgid.tod_high = (__u32) (get_clock() >> 32); 435 css->global_pgid.tod_high = tod_high;
436
437}
438
439static inline void __init
440setup_css(int nr)
441{
442 u32 tod_high;
443
444 memset(css[nr], 0, sizeof(struct channel_subsystem));
445 css[nr]->valid = 1;
446 css[nr]->cssid = nr;
447 sprintf(css[nr]->device.bus_id, "css%x", nr);
448 tod_high = (u32) (get_clock() >> 32);
449 css_generate_pgid(css[nr], tod_high);
439} 450}
440 451
441/* 452/*
@@ -446,25 +457,39 @@ css_generate_pgid(void)
446static int __init 457static int __init
447init_channel_subsystem (void) 458init_channel_subsystem (void)
448{ 459{
449 int ret; 460 int ret, i;
450 461
451 if (chsc_determine_css_characteristics() == 0) 462 if (chsc_determine_css_characteristics() == 0)
452 css_characteristics_avail = 1; 463 css_characteristics_avail = 1;
453 464
454 css_generate_pgid();
455
456 if ((ret = bus_register(&css_bus_type))) 465 if ((ret = bus_register(&css_bus_type)))
457 goto out; 466 goto out;
458 if ((ret = device_register (&css_bus_device)))
459 goto out_bus;
460 467
468 /* Setup css structure. */
469 for (i = 0; i <= __MAX_CSSID; i++) {
470 css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL);
471 if (!css[i]) {
472 ret = -ENOMEM;
473 goto out_bus;
474 }
475 setup_css(i);
476 ret = device_register(&css[i]->device);
477 if (ret)
478 goto out_free;
479 }
461 css_init_done = 1; 480 css_init_done = 1;
462 481
463 ctl_set_bit(6, 28); 482 ctl_set_bit(6, 28);
464 483
465 for_each_subchannel(__init_channel_subsystem, NULL); 484 for_each_subchannel(__init_channel_subsystem, NULL);
466 return 0; 485 return 0;
486out_free:
487 kfree(css[i]);
467out_bus: 488out_bus:
489 while (i > 0) {
490 i--;
491 device_unregister(&css[i]->device);
492 }
468 bus_unregister(&css_bus_type); 493 bus_unregister(&css_bus_type);
469out: 494out:
470 return ret; 495 return ret;
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 71efca25476d..b74659cab0af 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -35,19 +35,25 @@ struct path_state {
35 __u8 resvd : 3; /* reserved */ 35 __u8 resvd : 3; /* reserved */
36} __attribute__ ((packed)); 36} __attribute__ ((packed));
37 37
38struct extended_cssid {
39 u8 version;
40 u8 cssid;
41} __attribute__ ((packed));
42
38struct pgid { 43struct pgid {
39 union { 44 union {
40 __u8 fc; /* SPID function code */ 45 __u8 fc; /* SPID function code */
41 struct path_state ps; /* SNID path state */ 46 struct path_state ps; /* SNID path state */
42 } inf; 47 } inf;
43 __u32 cpu_addr : 16; /* CPU address */ 48 union {
49 __u32 cpu_addr : 16; /* CPU address */
50 struct extended_cssid ext_cssid;
51 } pgid_high;
44 __u32 cpu_id : 24; /* CPU identification */ 52 __u32 cpu_id : 24; /* CPU identification */
45 __u32 cpu_model : 16; /* CPU model */ 53 __u32 cpu_model : 16; /* CPU model */
46 __u32 tod_high; /* high word TOD clock */ 54 __u32 tod_high; /* high word TOD clock */
47} __attribute__ ((packed)); 55} __attribute__ ((packed));
48 56
49extern struct pgid global_pgid;
50
51#define MAX_CIWS 8 57#define MAX_CIWS 8
52 58
53/* 59/*
@@ -129,9 +135,20 @@ extern int css_init_done;
129extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); 135extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
130 136
131#define __MAX_SUBCHANNEL 65535 137#define __MAX_SUBCHANNEL 65535
138#define __MAX_CHPID 255
139#define __MAX_CSSID 0
140
141struct channel_subsystem {
142 u8 cssid;
143 int valid;
144 struct channel_path *chps[__MAX_CHPID];
145 struct device device;
146 struct pgid global_pgid;
147};
148#define to_css(dev) container_of(dev, struct channel_subsystem, device)
132 149
133extern struct bus_type css_bus_type; 150extern struct bus_type css_bus_type;
134extern struct device css_bus_device; 151extern struct channel_subsystem *css[];
135 152
136/* Some helper functions for disconnected state. */ 153/* Some helper functions for disconnected state. */
137int device_is_disconnected(struct subchannel *); 154int device_is_disconnected(struct subchannel *);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 9ac07aeffbe6..ba9f7c11f63f 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -986,10 +986,6 @@ ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
986 cdev->dev = (struct device) { 986 cdev->dev = (struct device) {
987 .parent = &sch->dev, 987 .parent = &sch->dev,
988 }; 988 };
989 /* Initialize the subchannel structure */
990 sch->dev.parent = &css_bus_device;
991 sch->dev.bus = &css_bus_type;
992
993 rc = io_subchannel_recog(cdev, sch); 989 rc = io_subchannel_recog(cdev, sch);
994 if (rc) 990 if (rc)
995 return rc; 991 return rc;
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index f08e84cc3563..3c89d70b9c09 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -164,7 +164,7 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
164 /* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */ 164 /* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */
165 case 0: /* Sense Path Group ID successful. */ 165 case 0: /* Sense Path Group ID successful. */
166 if (cdev->private->pgid.inf.ps.state1 == SNID_STATE1_RESET) 166 if (cdev->private->pgid.inf.ps.state1 == SNID_STATE1_RESET)
167 memcpy(&cdev->private->pgid, &global_pgid, 167 memcpy(&cdev->private->pgid, &css[0]->global_pgid,
168 sizeof(struct pgid)); 168 sizeof(struct pgid));
169 ccw_device_sense_pgid_done(cdev, 0); 169 ccw_device_sense_pgid_done(cdev, 0);
170 break; 170 break;