1 /* 2 * Handling of internal CCW device requests. 3 * 4 * Copyright IBM Corp. 2009 5 * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com> 6 */ 7 8 #include <linux/types.h> 9 #include <linux/err.h> 10 #include <asm/ccwdev.h> 11 #include <asm/cio.h> 12 13 #include "io_sch.h" 14 #include "cio.h" 15 #include "device.h" 16 #include "cio_debug.h" 17 18 /** 19 * lpm_adjust - adjust path mask 20 * @lpm: path mask to adjust 21 * @mask: mask of available paths 22 * 23 * Shift @lpm right until @lpm and @mask have at least one bit in common or 24 * until @lpm is zero. Return the resulting lpm. 25 */ 26 int lpm_adjust(int lpm, int mask) 27 { 28 while (lpm && ((lpm & mask) == 0)) 29 lpm >>= 1; 30 return lpm; 31 } 32 33 /* 34 * Adjust path mask to use next path and reset retry count. Return resulting 35 * path mask. 36 */ 37 static u16 ccwreq_next_path(struct ccw_device *cdev) 38 { 39 struct ccw_request *req = &cdev->private->req; 40 41 req->retries = req->maxretries; 42 req->mask = lpm_adjust(req->mask >>= 1, req->lpm); 43 44 return req->mask; 45 } 46 47 /* 48 * Clean up device state and report to callback. 49 */ 50 static void ccwreq_stop(struct ccw_device *cdev, int rc) 51 { 52 struct ccw_request *req = &cdev->private->req; 53 54 if (req->done) 55 return; 56 req->done = 1; 57 ccw_device_set_timeout(cdev, 0); 58 memset(&cdev->private->irb, 0, sizeof(struct irb)); 59 if (rc && rc != -ENODEV && req->drc) 60 rc = req->drc; 61 req->callback(cdev, req->data, rc); 62 } 63 64 /* 65 * (Re-)Start the operation until retries and paths are exhausted. 66 */ 67 static void ccwreq_do(struct ccw_device *cdev) 68 { 69 struct ccw_request *req = &cdev->private->req; 70 struct subchannel *sch = to_subchannel(cdev->dev.parent); 71 struct ccw1 *cp = req->cp; 72 int rc = -EACCES; 73 74 while (req->mask) { 75 if (req->retries-- == 0) { 76 /* Retries exhausted, try next path. */ 77 ccwreq_next_path(cdev); 78 continue; 79 } 80 /* Perform start function. */ 81 memset(&cdev->private->irb, 0, sizeof(struct irb)); 82 rc = cio_start(sch, cp, (u8) req->mask); 83 if (rc == 0) { 84 /* I/O started successfully. */ 85 ccw_device_set_timeout(cdev, req->timeout); 86 return; 87 } 88 if (rc == -ENODEV) { 89 /* Permanent device error. */ 90 break; 91 } 92 if (rc == -EACCES) { 93 /* Permant path error. */ 94 ccwreq_next_path(cdev); 95 continue; 96 } 97 /* Temporary improper status. */ 98 rc = cio_clear(sch); 99 if (rc) 100 break; 101 return; 102 } 103 ccwreq_stop(cdev, rc); 104 } 105 106 /** 107 * ccw_request_start - perform I/O request 108 * @cdev: ccw device 109 * 110 * Perform the I/O request specified by cdev->req. 111 */ 112 void ccw_request_start(struct ccw_device *cdev) 113 { 114 struct ccw_request *req = &cdev->private->req; 115 116 /* Try all paths twice to counter link flapping. */ 117 req->mask = 0x8080; 118 req->retries = req->maxretries; 119 req->mask = lpm_adjust(req->mask, req->lpm); 120 req->drc = 0; 121 req->done = 0; 122 req->cancel = 0; 123 if (!req->mask) 124 goto out_nopath; 125 ccwreq_do(cdev); 126 return; 127 128 out_nopath: 129 ccwreq_stop(cdev, -EACCES); 130 } 131 132 /** 133 * ccw_request_cancel - cancel running I/O request 134 * @cdev: ccw device 135 * 136 * Cancel the I/O request specified by cdev->req. Return non-zero if request 137 * has already finished, zero otherwise. 138 */ 139 int ccw_request_cancel(struct ccw_device *cdev) 140 { 141 struct subchannel *sch = to_subchannel(cdev->dev.parent); 142 struct ccw_request *req = &cdev->private->req; 143 int rc; 144 145 if (req->done) 146 return 1; 147 req->cancel = 1; 148 rc = cio_clear(sch); 149 if (rc) 150 ccwreq_stop(cdev, rc); 151 return 0; 152 } 153 154 /* 155 * Return the status of the internal I/O started on the specified ccw device. 156 * Perform BASIC SENSE if required. 157 */ 158 static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb) 159 { 160 struct irb *irb = &cdev->private->irb; 161 struct cmd_scsw *scsw = &irb->scsw.cmd; 162 enum uc_todo todo; 163 164 /* Perform BASIC SENSE if needed. */ 165 if (ccw_device_accumulate_and_sense(cdev, lcirb)) 166 return IO_RUNNING; 167 /* Check for halt/clear interrupt. */ 168 if (scsw->fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) 169 return IO_KILLED; 170 /* Check for path error. */ 171 if (scsw->cc == 3 || scsw->pno) 172 return IO_PATH_ERROR; 173 /* Handle BASIC SENSE data. */ 174 if (irb->esw.esw0.erw.cons) { 175 CIO_TRACE_EVENT(2, "sensedata"); 176 CIO_HEX_EVENT(2, &cdev->private->dev_id, 177 sizeof(struct ccw_dev_id)); 178 CIO_HEX_EVENT(2, &cdev->private->irb.ecw, SENSE_MAX_COUNT); 179 /* Check for command reject. */ 180 if (irb->ecw[0] & SNS0_CMD_REJECT) 181 return IO_REJECTED; 182 /* Ask the driver what to do */ 183 if (cdev->drv && cdev->drv->uc_handler) { 184 todo = cdev->drv->uc_handler(cdev, lcirb); 185 switch (todo) { 186 case UC_TODO_RETRY: 187 return IO_STATUS_ERROR; 188 case UC_TODO_RETRY_ON_NEW_PATH: 189 return IO_PATH_ERROR; 190 case UC_TODO_STOP: 191 return IO_REJECTED; 192 default: 193 return IO_STATUS_ERROR; 194 } 195 } 196 /* Assume that unexpected SENSE data implies an error. */ 197 return IO_STATUS_ERROR; 198 } 199 /* Check for channel errors. */ 200 if (scsw->cstat != 0) 201 return IO_STATUS_ERROR; 202 /* Check for device errors. */ 203 if (scsw->dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) 204 return IO_STATUS_ERROR; 205 /* Check for final state. */ 206 if (!(scsw->dstat & DEV_STAT_DEV_END)) 207 return IO_RUNNING; 208 /* Check for other improper status. */ 209 if (scsw->cc == 1 && (scsw->stctl & SCSW_STCTL_ALERT_STATUS)) 210 return IO_STATUS_ERROR; 211 return IO_DONE; 212 } 213 214 /* 215 * Log ccw request status. 216 */ 217 static void ccwreq_log_status(struct ccw_device *cdev, enum io_status status) 218 { 219 struct ccw_request *req = &cdev->private->req; 220 struct { 221 struct ccw_dev_id dev_id; 222 u16 retries; 223 u8 lpm; 224 u8 status; 225 } __attribute__ ((packed)) data; 226 data.dev_id = cdev->private->dev_id; 227 data.retries = req->retries; 228 data.lpm = (u8) req->mask; 229 data.status = (u8) status; 230 CIO_TRACE_EVENT(2, "reqstat"); 231 CIO_HEX_EVENT(2, &data, sizeof(data)); 232 } 233 234 /** 235 * ccw_request_handler - interrupt handler for I/O request procedure. 236 * @cdev: ccw device 237 * 238 * Handle interrupt during I/O request procedure. 239 */ 240 void ccw_request_handler(struct ccw_device *cdev) 241 { 242 struct irb *irb = (struct irb *)&S390_lowcore.irb; 243 struct ccw_request *req = &cdev->private->req; 244 enum io_status status; 245 int rc = -EOPNOTSUPP; 246 247 /* Check status of I/O request. */ 248 status = ccwreq_status(cdev, irb); 249 if (req->filter) 250 status = req->filter(cdev, req->data, irb, status); 251 if (status != IO_RUNNING) 252 ccw_device_set_timeout(cdev, 0); 253 if (status != IO_DONE && status != IO_RUNNING) 254 ccwreq_log_status(cdev, status); 255 switch (status) { 256 case IO_DONE: 257 break; 258 case IO_RUNNING: 259 return; 260 case IO_REJECTED: 261 goto err; 262 case IO_PATH_ERROR: 263 goto out_next_path; 264 case IO_STATUS_ERROR: 265 goto out_restart; 266 case IO_KILLED: 267 /* Check if request was cancelled on purpose. */ 268 if (req->cancel) { 269 rc = -EIO; 270 goto err; 271 } 272 goto out_restart; 273 } 274 /* Check back with request initiator. */ 275 if (!req->check) 276 goto out; 277 switch (req->check(cdev, req->data)) { 278 case 0: 279 break; 280 case -EAGAIN: 281 goto out_restart; 282 case -EACCES: 283 goto out_next_path; 284 default: 285 goto err; 286 } 287 out: 288 ccwreq_stop(cdev, 0); 289 return; 290 291 out_next_path: 292 /* Try next path and restart I/O. */ 293 if (!ccwreq_next_path(cdev)) { 294 rc = -EACCES; 295 goto err; 296 } 297 out_restart: 298 /* Restart. */ 299 ccwreq_do(cdev); 300 return; 301 err: 302 ccwreq_stop(cdev, rc); 303 } 304 305 306 /** 307 * ccw_request_timeout - timeout handler for I/O request procedure 308 * @cdev: ccw device 309 * 310 * Handle timeout during I/O request procedure. 311 */ 312 void ccw_request_timeout(struct ccw_device *cdev) 313 { 314 struct subchannel *sch = to_subchannel(cdev->dev.parent); 315 struct ccw_request *req = &cdev->private->req; 316 int rc; 317 318 if (!ccwreq_next_path(cdev)) { 319 /* set the final return code for this request */ 320 req->drc = -ETIME; 321 } 322 rc = cio_clear(sch); 323 if (rc) 324 goto err; 325 return; 326 327 err: 328 ccwreq_stop(cdev, rc); 329 } 330 331 /** 332 * ccw_request_notoper - notoper handler for I/O request procedure 333 * @cdev: ccw device 334 * 335 * Handle timeout during I/O request procedure. 336 */ 337 void ccw_request_notoper(struct ccw_device *cdev) 338 { 339 ccwreq_stop(cdev, -ENODEV); 340 } 341