hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/s390/cio/chsc.c
....@@ -24,6 +24,7 @@
2424 #include <asm/crw.h>
2525 #include <asm/isc.h>
2626 #include <asm/ebcdic.h>
27
+#include <asm/ap.h>
2728
2829 #include "css.h"
2930 #include "cio.h"
....@@ -56,6 +57,7 @@
5657 case 0x0104:
5758 return -EINVAL;
5859 case 0x0004:
60
+ case 0x0106: /* "Wrong Channel Parm" for the op 0x003d */
5961 return -EOPNOTSUPP;
6062 case 0x000b:
6163 case 0x0107: /* "Channel busy" for the op 0x003d */
....@@ -63,6 +65,8 @@
6365 case 0x0100:
6466 case 0x0102:
6567 return -ENOMEM;
68
+ case 0x0108: /* "HW limit exceeded" for the op 0x003d */
69
+ return -EUSERS;
6670 default:
6771 return -EIO;
6872 }
....@@ -179,11 +183,12 @@
179183 * @scssc: request and response block for SADC
180184 * @summary_indicator_addr: summary indicator address
181185 * @subchannel_indicator_addr: subchannel indicator address
186
+ * @isc: Interruption Subclass for this subchannel
182187 *
183188 * Returns 0 on success.
184189 */
185190 int chsc_sadc(struct subchannel_id schid, struct chsc_scssc_area *scssc,
186
- u64 summary_indicator_addr, u64 subchannel_indicator_addr)
191
+ u64 summary_indicator_addr, u64 subchannel_indicator_addr, u8 isc)
187192 {
188193 memset(scssc, 0, sizeof(*scssc));
189194 scssc->request.length = 0x0fe0;
....@@ -195,7 +200,7 @@
195200
196201 scssc->ks = PAGE_DEFAULT_KEY >> 4;
197202 scssc->kc = PAGE_DEFAULT_KEY >> 4;
198
- scssc->isc = QDIO_AIRQ_ISC;
203
+ scssc->isc = isc;
199204 scssc->schid = schid;
200205
201206 /* enable the time delay disablement facility */
....@@ -320,36 +325,6 @@
320325 u8 nt_area[PAGE_SIZE - 24];
321326 } u;
322327 } __packed __aligned(PAGE_SIZE);
323
-
324
-/*
325
- * Node Descriptor as defined in SA22-7204, "Common I/O-Device Commands"
326
- */
327
-
328
-#define ND_VALIDITY_VALID 0
329
-#define ND_VALIDITY_OUTDATED 1
330
-#define ND_VALIDITY_INVALID 2
331
-
332
-struct node_descriptor {
333
- /* Flags. */
334
- union {
335
- struct {
336
- u32 validity:3;
337
- u32 reserved:5;
338
- } __packed;
339
- u8 byte0;
340
- } __packed;
341
-
342
- /* Node parameters. */
343
- u32 params:24;
344
-
345
- /* Node ID. */
346
- char type[6];
347
- char model[3];
348
- char manufacturer[3];
349
- char plant[2];
350
- char seq[12];
351
- u16 tag;
352
-} __packed;
353328
354329 /*
355330 * Link Incident Record as defined in SA22-7202, "ESCON I/O Interface"
....@@ -586,6 +561,15 @@
586561 " failed (rc=%d).\n", ret);
587562 }
588563
564
+static void chsc_process_sei_ap_cfg_chg(struct chsc_sei_nt0_area *sei_area)
565
+{
566
+ CIO_CRW_EVENT(3, "chsc: ap config changed\n");
567
+ if (sei_area->rs != 5)
568
+ return;
569
+
570
+ ap_bus_cfg_chg();
571
+}
572
+
589573 static void chsc_process_sei_nt2(struct chsc_sei_nt2_area *sei_area)
590574 {
591575 switch (sei_area->cc) {
....@@ -611,6 +595,9 @@
611595 break;
612596 case 2: /* i/o resource accessibility */
613597 chsc_process_sei_res_acc(sei_area);
598
+ break;
599
+ case 3: /* ap config changed */
600
+ chsc_process_sei_ap_cfg_chg(sei_area);
614601 break;
615602 case 7: /* channel-path-availability information */
616603 chsc_process_sei_chp_avail(sei_area);
....@@ -1127,7 +1114,7 @@
11271114 return ret;
11281115 }
11291116
1130
-int __init chsc_get_cssid(int idx)
1117
+int __init chsc_get_cssid_iid(int idx, u8 *cssid, u8 *iid)
11311118 {
11321119 struct {
11331120 struct chsc_header request;
....@@ -1138,7 +1125,8 @@
11381125 u32 reserved2[3];
11391126 struct {
11401127 u8 cssid;
1141
- u32 : 24;
1128
+ u8 iid;
1129
+ u32 : 16;
11421130 } list[0];
11431131 } *sdcal_area;
11441132 int ret;
....@@ -1164,8 +1152,10 @@
11641152 }
11651153
11661154 if ((addr_t) &sdcal_area->list[idx] <
1167
- (addr_t) &sdcal_area->response + sdcal_area->response.length)
1168
- ret = sdcal_area->list[idx].cssid;
1155
+ (addr_t) &sdcal_area->response + sdcal_area->response.length) {
1156
+ *cssid = sdcal_area->list[idx].cssid;
1157
+ *iid = sdcal_area->list[idx].iid;
1158
+ }
11691159 else
11701160 ret = -ENODEV;
11711161 exit:
....@@ -1273,6 +1263,27 @@
12731263 return (rr->response.code == 0x0001) ? 0 : -EIO;
12741264 }
12751265
1266
+int chsc_stzi(void *page, void *result, size_t size)
1267
+{
1268
+ struct {
1269
+ struct chsc_header request;
1270
+ unsigned int rsvd0[3];
1271
+ struct chsc_header response;
1272
+ char data[];
1273
+ } *rr;
1274
+ int rc;
1275
+
1276
+ memset(page, 0, PAGE_SIZE);
1277
+ rr = page;
1278
+ rr->request.length = 0x0010;
1279
+ rr->request.code = 0x003e;
1280
+ rc = chsc(rr);
1281
+ if (rc)
1282
+ return -EIO;
1283
+ memcpy(result, &rr->data, size);
1284
+ return (rr->response.code == 0x0001) ? 0 : -EIO;
1285
+}
1286
+
12761287 int chsc_siosl(struct subchannel_id schid)
12771288 {
12781289 struct {
....@@ -1350,33 +1361,68 @@
13501361 EXPORT_SYMBOL_GPL(chsc_scm_info);
13511362
13521363 /**
1353
- * chsc_pnso_brinfo() - Perform Network-Subchannel Operation, Bridge Info.
1364
+ * chsc_pnso() - Perform Network-Subchannel Operation
13541365 * @schid: id of the subchannel on which PNSO is performed
1355
- * @brinfo_area: request and response block for the operation
1366
+ * @pnso_area: request and response block for the operation
1367
+ * @oc: Operation Code
13561368 * @resume_token: resume token for multiblock response
13571369 * @cnc: Boolean change-notification control
13581370 *
1359
- * brinfo_area must be allocated by the caller with get_zeroed_page(GFP_KERNEL)
1371
+ * pnso_area must be allocated by the caller with get_zeroed_page(GFP_KERNEL)
13601372 *
13611373 * Returns 0 on success.
13621374 */
1363
-int chsc_pnso_brinfo(struct subchannel_id schid,
1364
- struct chsc_pnso_area *brinfo_area,
1365
- struct chsc_brinfo_resume_token resume_token,
1366
- int cnc)
1375
+int chsc_pnso(struct subchannel_id schid, struct chsc_pnso_area *pnso_area,
1376
+ u8 oc, struct chsc_pnso_resume_token resume_token, int cnc)
13671377 {
1368
- memset(brinfo_area, 0, sizeof(*brinfo_area));
1369
- brinfo_area->request.length = 0x0030;
1370
- brinfo_area->request.code = 0x003d; /* network-subchannel operation */
1371
- brinfo_area->m = schid.m;
1372
- brinfo_area->ssid = schid.ssid;
1373
- brinfo_area->sch = schid.sch_no;
1374
- brinfo_area->cssid = schid.cssid;
1375
- brinfo_area->oc = 0; /* Store-network-bridging-information list */
1376
- brinfo_area->resume_token = resume_token;
1377
- brinfo_area->n = (cnc != 0);
1378
- if (chsc(brinfo_area))
1378
+ memset(pnso_area, 0, sizeof(*pnso_area));
1379
+ pnso_area->request.length = 0x0030;
1380
+ pnso_area->request.code = 0x003d; /* network-subchannel operation */
1381
+ pnso_area->m = schid.m;
1382
+ pnso_area->ssid = schid.ssid;
1383
+ pnso_area->sch = schid.sch_no;
1384
+ pnso_area->cssid = schid.cssid;
1385
+ pnso_area->oc = oc;
1386
+ pnso_area->resume_token = resume_token;
1387
+ pnso_area->n = (cnc != 0);
1388
+ if (chsc(pnso_area))
13791389 return -EIO;
1380
- return chsc_error_from_response(brinfo_area->response.code);
1390
+ return chsc_error_from_response(pnso_area->response.code);
13811391 }
1382
-EXPORT_SYMBOL_GPL(chsc_pnso_brinfo);
1392
+
1393
+int chsc_sgib(u32 origin)
1394
+{
1395
+ struct {
1396
+ struct chsc_header request;
1397
+ u16 op;
1398
+ u8 reserved01[2];
1399
+ u8 reserved02:4;
1400
+ u8 fmt:4;
1401
+ u8 reserved03[7];
1402
+ /* operation data area begin */
1403
+ u8 reserved04[4];
1404
+ u32 gib_origin;
1405
+ u8 reserved05[10];
1406
+ u8 aix;
1407
+ u8 reserved06[4029];
1408
+ struct chsc_header response;
1409
+ u8 reserved07[4];
1410
+ } *sgib_area;
1411
+ int ret;
1412
+
1413
+ spin_lock_irq(&chsc_page_lock);
1414
+ memset(chsc_page, 0, PAGE_SIZE);
1415
+ sgib_area = chsc_page;
1416
+ sgib_area->request.length = 0x0fe0;
1417
+ sgib_area->request.code = 0x0021;
1418
+ sgib_area->op = 0x1;
1419
+ sgib_area->gib_origin = origin;
1420
+
1421
+ ret = chsc(sgib_area);
1422
+ if (ret == 0)
1423
+ ret = chsc_error_from_response(sgib_area->response.code);
1424
+ spin_unlock_irq(&chsc_page_lock);
1425
+
1426
+ return ret;
1427
+}
1428
+EXPORT_SYMBOL_GPL(chsc_sgib);