.. | .. |
---|
24 | 24 | #include <asm/crw.h> |
---|
25 | 25 | #include <asm/isc.h> |
---|
26 | 26 | #include <asm/ebcdic.h> |
---|
| 27 | +#include <asm/ap.h> |
---|
27 | 28 | |
---|
28 | 29 | #include "css.h" |
---|
29 | 30 | #include "cio.h" |
---|
.. | .. |
---|
56 | 57 | case 0x0104: |
---|
57 | 58 | return -EINVAL; |
---|
58 | 59 | case 0x0004: |
---|
| 60 | + case 0x0106: /* "Wrong Channel Parm" for the op 0x003d */ |
---|
59 | 61 | return -EOPNOTSUPP; |
---|
60 | 62 | case 0x000b: |
---|
61 | 63 | case 0x0107: /* "Channel busy" for the op 0x003d */ |
---|
.. | .. |
---|
63 | 65 | case 0x0100: |
---|
64 | 66 | case 0x0102: |
---|
65 | 67 | return -ENOMEM; |
---|
| 68 | + case 0x0108: /* "HW limit exceeded" for the op 0x003d */ |
---|
| 69 | + return -EUSERS; |
---|
66 | 70 | default: |
---|
67 | 71 | return -EIO; |
---|
68 | 72 | } |
---|
.. | .. |
---|
179 | 183 | * @scssc: request and response block for SADC |
---|
180 | 184 | * @summary_indicator_addr: summary indicator address |
---|
181 | 185 | * @subchannel_indicator_addr: subchannel indicator address |
---|
| 186 | + * @isc: Interruption Subclass for this subchannel |
---|
182 | 187 | * |
---|
183 | 188 | * Returns 0 on success. |
---|
184 | 189 | */ |
---|
185 | 190 | 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) |
---|
187 | 192 | { |
---|
188 | 193 | memset(scssc, 0, sizeof(*scssc)); |
---|
189 | 194 | scssc->request.length = 0x0fe0; |
---|
.. | .. |
---|
195 | 200 | |
---|
196 | 201 | scssc->ks = PAGE_DEFAULT_KEY >> 4; |
---|
197 | 202 | scssc->kc = PAGE_DEFAULT_KEY >> 4; |
---|
198 | | - scssc->isc = QDIO_AIRQ_ISC; |
---|
| 203 | + scssc->isc = isc; |
---|
199 | 204 | scssc->schid = schid; |
---|
200 | 205 | |
---|
201 | 206 | /* enable the time delay disablement facility */ |
---|
.. | .. |
---|
320 | 325 | u8 nt_area[PAGE_SIZE - 24]; |
---|
321 | 326 | } u; |
---|
322 | 327 | } __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; |
---|
353 | 328 | |
---|
354 | 329 | /* |
---|
355 | 330 | * Link Incident Record as defined in SA22-7202, "ESCON I/O Interface" |
---|
.. | .. |
---|
586 | 561 | " failed (rc=%d).\n", ret); |
---|
587 | 562 | } |
---|
588 | 563 | |
---|
| 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 | + |
---|
589 | 573 | static void chsc_process_sei_nt2(struct chsc_sei_nt2_area *sei_area) |
---|
590 | 574 | { |
---|
591 | 575 | switch (sei_area->cc) { |
---|
.. | .. |
---|
611 | 595 | break; |
---|
612 | 596 | case 2: /* i/o resource accessibility */ |
---|
613 | 597 | chsc_process_sei_res_acc(sei_area); |
---|
| 598 | + break; |
---|
| 599 | + case 3: /* ap config changed */ |
---|
| 600 | + chsc_process_sei_ap_cfg_chg(sei_area); |
---|
614 | 601 | break; |
---|
615 | 602 | case 7: /* channel-path-availability information */ |
---|
616 | 603 | chsc_process_sei_chp_avail(sei_area); |
---|
.. | .. |
---|
1127 | 1114 | return ret; |
---|
1128 | 1115 | } |
---|
1129 | 1116 | |
---|
1130 | | -int __init chsc_get_cssid(int idx) |
---|
| 1117 | +int __init chsc_get_cssid_iid(int idx, u8 *cssid, u8 *iid) |
---|
1131 | 1118 | { |
---|
1132 | 1119 | struct { |
---|
1133 | 1120 | struct chsc_header request; |
---|
.. | .. |
---|
1138 | 1125 | u32 reserved2[3]; |
---|
1139 | 1126 | struct { |
---|
1140 | 1127 | u8 cssid; |
---|
1141 | | - u32 : 24; |
---|
| 1128 | + u8 iid; |
---|
| 1129 | + u32 : 16; |
---|
1142 | 1130 | } list[0]; |
---|
1143 | 1131 | } *sdcal_area; |
---|
1144 | 1132 | int ret; |
---|
.. | .. |
---|
1164 | 1152 | } |
---|
1165 | 1153 | |
---|
1166 | 1154 | 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 | + } |
---|
1169 | 1159 | else |
---|
1170 | 1160 | ret = -ENODEV; |
---|
1171 | 1161 | exit: |
---|
.. | .. |
---|
1273 | 1263 | return (rr->response.code == 0x0001) ? 0 : -EIO; |
---|
1274 | 1264 | } |
---|
1275 | 1265 | |
---|
| 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 | + |
---|
1276 | 1287 | int chsc_siosl(struct subchannel_id schid) |
---|
1277 | 1288 | { |
---|
1278 | 1289 | struct { |
---|
.. | .. |
---|
1350 | 1361 | EXPORT_SYMBOL_GPL(chsc_scm_info); |
---|
1351 | 1362 | |
---|
1352 | 1363 | /** |
---|
1353 | | - * chsc_pnso_brinfo() - Perform Network-Subchannel Operation, Bridge Info. |
---|
| 1364 | + * chsc_pnso() - Perform Network-Subchannel Operation |
---|
1354 | 1365 | * @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 |
---|
1356 | 1368 | * @resume_token: resume token for multiblock response |
---|
1357 | 1369 | * @cnc: Boolean change-notification control |
---|
1358 | 1370 | * |
---|
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) |
---|
1360 | 1372 | * |
---|
1361 | 1373 | * Returns 0 on success. |
---|
1362 | 1374 | */ |
---|
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) |
---|
1367 | 1377 | { |
---|
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)) |
---|
1379 | 1389 | return -EIO; |
---|
1380 | | - return chsc_error_from_response(brinfo_area->response.code); |
---|
| 1390 | + return chsc_error_from_response(pnso_area->response.code); |
---|
1381 | 1391 | } |
---|
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); |
---|