aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_id.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/device_id.c')
-rw-r--r--drivers/s390/cio/device_id.c107
1 files changed, 64 insertions, 43 deletions
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 918b8b89cf9a..dc4d87f77f6c 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -26,17 +26,18 @@
26#include "ioasm.h" 26#include "ioasm.h"
27#include "io_sch.h" 27#include "io_sch.h"
28 28
29/* 29/**
30 * Input : 30 * vm_vdev_to_cu_type - Convert vm virtual device into control unit type
31 * devno - device number 31 * for certain devices.
32 * ps - pointer to sense ID data area 32 * @class: virtual device class
33 * Output : none 33 * @type: virtual device type
34 *
35 * Returns control unit type if a match was made or %0xffff otherwise.
34 */ 36 */
35static void 37static int vm_vdev_to_cu_type(int class, int type)
36VM_virtual_device_info (__u16 devno, struct senseid *ps)
37{ 38{
38 static struct { 39 static struct {
39 int vrdcvcla, vrdcvtyp, cu_type; 40 int class, type, cu_type;
40 } vm_devices[] = { 41 } vm_devices[] = {
41 { 0x08, 0x01, 0x3480 }, 42 { 0x08, 0x01, 0x3480 },
42 { 0x08, 0x02, 0x3430 }, 43 { 0x08, 0x02, 0x3430 },
@@ -68,8 +69,26 @@ VM_virtual_device_info (__u16 devno, struct senseid *ps)
68 { 0x40, 0xc0, 0x5080 }, 69 { 0x40, 0xc0, 0x5080 },
69 { 0x80, 0x00, 0x3215 }, 70 { 0x80, 0x00, 0x3215 },
70 }; 71 };
72 int i;
73
74 for (i = 0; i < ARRAY_SIZE(vm_devices); i++)
75 if (class == vm_devices[i].class && type == vm_devices[i].type)
76 return vm_devices[i].cu_type;
77
78 return 0xffff;
79}
80
81/**
82 * diag_get_dev_info - retrieve device information via DIAG X'210'
83 * @devno: device number
84 * @ps: pointer to sense ID data area
85 *
86 * Returns zero on success, non-zero otherwise.
87 */
88static int diag_get_dev_info(u16 devno, struct senseid *ps)
89{
71 struct diag210 diag_data; 90 struct diag210 diag_data;
72 int ccode, i; 91 int ccode;
73 92
74 CIO_TRACE_EVENT (4, "VMvdinf"); 93 CIO_TRACE_EVENT (4, "VMvdinf");
75 94
@@ -79,21 +98,21 @@ VM_virtual_device_info (__u16 devno, struct senseid *ps)
79 }; 98 };
80 99
81 ccode = diag210 (&diag_data); 100 ccode = diag210 (&diag_data);
82 ps->reserved = 0xff; 101 if ((ccode == 0) || (ccode == 2)) {
102 ps->reserved = 0xff;
83 103
84 /* Special case for bloody osa devices. */ 104 /* Special case for osa devices. */
85 if (diag_data.vrdcvcla == 0x02 && 105 if (diag_data.vrdcvcla == 0x02 && diag_data.vrdcvtyp == 0x20) {
86 diag_data.vrdcvtyp == 0x20) { 106 ps->cu_type = 0x3088;
87 ps->cu_type = 0x3088; 107 ps->cu_model = 0x60;
88 ps->cu_model = 0x60; 108 return 0;
89 return;
90 }
91 for (i = 0; i < ARRAY_SIZE(vm_devices); i++)
92 if (diag_data.vrdcvcla == vm_devices[i].vrdcvcla &&
93 diag_data.vrdcvtyp == vm_devices[i].vrdcvtyp) {
94 ps->cu_type = vm_devices[i].cu_type;
95 return;
96 } 109 }
110 ps->cu_type = vm_vdev_to_cu_type(diag_data.vrdcvcla,
111 diag_data.vrdcvtyp);
112 if (ps->cu_type != 0xffff)
113 return 0;
114 }
115
97 CIO_MSG_EVENT(0, "DIAG X'210' for device %04X returned (cc = %d):" 116 CIO_MSG_EVENT(0, "DIAG X'210' for device %04X returned (cc = %d):"
98 "vdev class : %02X, vdev type : %04X \n ... " 117 "vdev class : %02X, vdev type : %04X \n ... "
99 "rdev class : %02X, rdev type : %04X, " 118 "rdev class : %02X, rdev type : %04X, "
@@ -102,6 +121,8 @@ VM_virtual_device_info (__u16 devno, struct senseid *ps)
102 diag_data.vrdcvcla, diag_data.vrdcvtyp, 121 diag_data.vrdcvcla, diag_data.vrdcvtyp,
103 diag_data.vrdcrccl, diag_data.vrdccrty, 122 diag_data.vrdcrccl, diag_data.vrdccrty,
104 diag_data.vrdccrmd); 123 diag_data.vrdccrmd);
124
125 return -ENODEV;
105} 126}
106 127
107/* 128/*
@@ -130,6 +151,7 @@ __ccw_device_sense_id_start(struct ccw_device *cdev)
130 /* Try on every path. */ 151 /* Try on every path. */
131 ret = -ENODEV; 152 ret = -ENODEV;
132 while (cdev->private->imask != 0) { 153 while (cdev->private->imask != 0) {
154 cdev->private->senseid.cu_type = 0xFFFF;
133 if ((sch->opm & cdev->private->imask) != 0 && 155 if ((sch->opm & cdev->private->imask) != 0 &&
134 cdev->private->iretry > 0) { 156 cdev->private->iretry > 0) {
135 cdev->private->iretry--; 157 cdev->private->iretry--;
@@ -153,7 +175,6 @@ ccw_device_sense_id_start(struct ccw_device *cdev)
153 int ret; 175 int ret;
154 176
155 memset (&cdev->private->senseid, 0, sizeof (struct senseid)); 177 memset (&cdev->private->senseid, 0, sizeof (struct senseid));
156 cdev->private->senseid.cu_type = 0xFFFF;
157 cdev->private->imask = 0x80; 178 cdev->private->imask = 0x80;
158 cdev->private->iretry = 5; 179 cdev->private->iretry = 5;
159 ret = __ccw_device_sense_id_start(cdev); 180 ret = __ccw_device_sense_id_start(cdev);
@@ -173,13 +194,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
173 194
174 sch = to_subchannel(cdev->dev.parent); 195 sch = to_subchannel(cdev->dev.parent);
175 irb = &cdev->private->irb; 196 irb = &cdev->private->irb;
176 /* Did we get a proper answer ? */ 197
177 if (cdev->private->senseid.cu_type != 0xFFFF &&
178 cdev->private->senseid.reserved == 0xFF) {
179 if (irb->scsw.count < sizeof (struct senseid) - 8)
180 cdev->private->flags.esid = 1;
181 return 0; /* Success */
182 }
183 /* Check the error cases. */ 198 /* Check the error cases. */
184 if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) { 199 if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
185 /* Retry Sense ID if requested. */ 200 /* Retry Sense ID if requested. */
@@ -231,6 +246,15 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
231 sch->schid.ssid, sch->schid.sch_no); 246 sch->schid.ssid, sch->schid.sch_no);
232 return -EACCES; 247 return -EACCES;
233 } 248 }
249
250 /* Did we get a proper answer ? */
251 if (irb->scsw.cc == 0 && cdev->private->senseid.cu_type != 0xFFFF &&
252 cdev->private->senseid.reserved == 0xFF) {
253 if (irb->scsw.count < sizeof(struct senseid) - 8)
254 cdev->private->flags.esid = 1;
255 return 0; /* Success */
256 }
257
234 /* Hmm, whatever happened, try again. */ 258 /* Hmm, whatever happened, try again. */
235 CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on " 259 CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on "
236 "subchannel 0.%x.%04x returns status %02X%02X\n", 260 "subchannel 0.%x.%04x returns status %02X%02X\n",
@@ -283,20 +307,17 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
283 break; 307 break;
284 /* fall through. */ 308 /* fall through. */
285 default: /* Sense ID failed. Try asking VM. */ 309 default: /* Sense ID failed. Try asking VM. */
286 if (MACHINE_IS_VM) { 310 if (MACHINE_IS_VM)
287 VM_virtual_device_info (cdev->private->dev_id.devno, 311 ret = diag_get_dev_info(cdev->private->dev_id.devno,
288 &cdev->private->senseid); 312 &cdev->private->senseid);
289 if (cdev->private->senseid.cu_type != 0xFFFF) { 313 else
290 /* Got the device information from VM. */ 314 /*
291 ccw_device_sense_id_done(cdev, 0); 315 * If we can't couldn't identify the device type we
292 return; 316 * consider the device "not operational".
293 } 317 */
294 } 318 ret = -ENODEV;
295 /* 319
296 * If we can't couldn't identify the device type we 320 ccw_device_sense_id_done(cdev, ret);
297 * consider the device "not operational".
298 */
299 ccw_device_sense_id_done(cdev, -ENODEV);
300 break; 321 break;
301 } 322 }
302} 323}