1/* 2 * Copyright (c) 2004-07 Applied Micro Circuits Corporation. 3 * Copyright (c) 2004-05 Vinod Kashyap. 4 * Copyright (c) 2000 Michael Smith 5 * Copyright (c) 2000 BSDi 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * |
29 * $FreeBSD: head/sys/dev/twa/tw_osl_freebsd.c 212008 2010-08-30 19:15:04Z delphij $ |
30 */ 31 32/* 33 * AMCC'S 3ware driver for 9000 series storage controllers. 34 * 35 * Author: Vinod Kashyap 36 * Modifications by: Adam Radford 37 * Modifications by: Manjunath Ranganathaiah --- 132 unchanged lines hidden (view full) --- 170 171 172static TW_INT32 twa_probe(device_t dev); 173static TW_INT32 twa_attach(device_t dev); 174static TW_INT32 twa_detach(device_t dev); 175static TW_INT32 twa_shutdown(device_t dev); 176static TW_VOID twa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op); 177static TW_VOID twa_pci_intr(TW_VOID *arg); |
178static TW_VOID twa_watchdog(TW_VOID *arg); 179int twa_setup_intr(struct twa_softc *sc); 180int twa_teardown_intr(struct twa_softc *sc); |
181 182static TW_INT32 tw_osli_alloc_mem(struct twa_softc *sc); 183static TW_VOID tw_osli_free_resources(struct twa_softc *sc); 184 185static TW_VOID twa_map_load_data_callback(TW_VOID *arg, 186 bus_dma_segment_t *segs, TW_INT32 nsegments, TW_INT32 error); 187static TW_VOID twa_map_load_callback(TW_VOID *arg, 188 bus_dma_segment_t *segs, TW_INT32 nsegments, TW_INT32 error); --- 47 unchanged lines hidden (view full) --- 236 TW_OSL_DRIVER_VERSION_STRING); 237 first_ctlr = 0; 238 } 239 return(0); 240 } 241 return(ENXIO); 242} 243 |
244int twa_setup_intr(struct twa_softc *sc) 245{ 246 int error = 0; |
247 |
248 if (!(sc->intr_handle) && (sc->irq_res)) { 249 error = bus_setup_intr(sc->bus_dev, sc->irq_res, 250 INTR_TYPE_CAM | INTR_MPSAFE, 251 NULL, twa_pci_intr, 252 sc, &sc->intr_handle); 253 } 254 return( error ); 255} |
256 |
257 258int twa_teardown_intr(struct twa_softc *sc) 259{ 260 int error = 0; 261 262 if ((sc->intr_handle) && (sc->irq_res)) { 263 error = bus_teardown_intr(sc->bus_dev, 264 sc->irq_res, sc->intr_handle); 265 sc->intr_handle = NULL; 266 } 267 return( error ); 268} 269 270 271 |
272/* 273 * Function name: twa_attach 274 * Description: Allocates pci resources; updates sc; adds a node to the 275 * sysctl tree to expose the driver version; makes calls 276 * (to the Common Layer) to initialize ctlr, and to 277 * attach to CAM. 278 * 279 * Input: dev -- bus device corresponding to the ctlr --- 98 unchanged lines hidden (view full) --- 378 TW_CL_SEVERITY_ERROR_STRING, 379 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 380 0x2003, 381 "Can't allocate interrupt", 382 ENXIO); 383 tw_osli_free_resources(sc); 384 return(ENXIO); 385 } |
386 if ((error = twa_setup_intr(sc))) { |
387 tw_osli_printf(sc, "error = %d", 388 TW_CL_SEVERITY_ERROR_STRING, 389 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 390 0x2004, 391 "Can't set up interrupt", 392 error); 393 tw_osli_free_resources(sc); 394 return(error); --- 38 unchanged lines hidden (view full) --- 433 TW_CL_SEVERITY_ERROR_STRING, 434 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 435 0x2007, 436 "Failed to initialize CAM", 437 error); 438 return(error); 439 } 440 |
441 sc->watchdog_index = 0; 442 callout_init(&(sc->watchdog_callout[0]), CALLOUT_MPSAFE); 443 callout_init(&(sc->watchdog_callout[1]), CALLOUT_MPSAFE); 444 callout_reset(&(sc->watchdog_callout[0]), 5*hz, twa_watchdog, &sc->ctlr_handle); 445 |
446 return(0); 447} 448 449 |
450static TW_VOID 451twa_watchdog(TW_VOID *arg) 452{ 453 struct tw_cl_ctlr_handle *ctlr_handle = 454 (struct tw_cl_ctlr_handle *)arg; 455 struct twa_softc *sc = ctlr_handle->osl_ctlr_ctxt; 456 int i; 457 int i_need_a_reset = 0; 458 int driver_is_active = 0; 459 int my_watchdog_was_pending = 1234; 460 TW_UINT64 current_time; 461 struct tw_osli_req_context *my_req; |
462 |
463 464//============================================================================== 465 current_time = (TW_UINT64) (tw_osl_get_local_time()); 466 467 for (i = 0; i < TW_OSLI_MAX_NUM_REQUESTS; i++) { 468 my_req = &(sc->req_ctx_buf[i]); 469 470 if ((my_req->state == TW_OSLI_REQ_STATE_BUSY) && 471 (my_req->deadline) && 472 (my_req->deadline < current_time)) { 473 tw_cl_set_reset_needed(ctlr_handle); 474#ifdef TW_OSL_DEBUG 475 device_printf((sc)->bus_dev, "Request %d timed out! d = %p, c = %p\n", i, (void*)my_req->deadline, (void*)current_time); 476#else /* TW_OSL_DEBUG */ 477 device_printf((sc)->bus_dev, "Request %d timed out!\n", i); 478#endif /* TW_OSL_DEBUG */ 479 break; 480 } 481 } 482//============================================================================== 483 484 i_need_a_reset = tw_cl_is_reset_needed(ctlr_handle); 485 486 i = (int) ((sc->watchdog_index++) & 1); 487 488 driver_is_active = tw_cl_is_active(ctlr_handle); 489 490 if (i_need_a_reset) { 491#ifdef TW_OSL_DEBUG 492 device_printf((sc)->bus_dev, "Watchdog rescheduled in 70 seconds\n"); 493#endif /* TW_OSL_DEBUG */ 494 my_watchdog_was_pending = 495 callout_reset(&(sc->watchdog_callout[i]), 70*hz, twa_watchdog, &sc->ctlr_handle); 496 tw_cl_reset_ctlr(ctlr_handle); 497#ifdef TW_OSL_DEBUG 498 device_printf((sc)->bus_dev, "Watchdog reset completed!\n"); 499#endif /* TW_OSL_DEBUG */ 500 } else if (driver_is_active) { 501 my_watchdog_was_pending = 502 callout_reset(&(sc->watchdog_callout[i]), 5*hz, twa_watchdog, &sc->ctlr_handle); 503 } 504#ifdef TW_OSL_DEBUG 505 if (i_need_a_reset || my_watchdog_was_pending) 506 device_printf((sc)->bus_dev, "i_need_a_reset = %d, " 507 "driver_is_active = %d, my_watchdog_was_pending = %d\n", 508 i_need_a_reset, driver_is_active, my_watchdog_was_pending); 509#endif /* TW_OSL_DEBUG */ 510} 511 512 |
513/* 514 * Function name: tw_osli_alloc_mem 515 * Description: Allocates memory needed both by CL and OSL. 516 * 517 * Input: sc -- OSL internal controller context 518 * Output: None 519 * Return value: 0 -- success 520 * non-zero-- failure --- 282 unchanged lines hidden (view full) --- 803 804 if (sc->parent_tag) 805 if ((error = bus_dma_tag_destroy(sc->parent_tag))) 806 tw_osli_dbg_dprintf(1, sc, 807 "dma_tag_destroy(parent) returned %d", error); 808 809 810 /* Disconnect the interrupt handler. */ |
811 if ((error = twa_teardown_intr(sc))) |
812 tw_osli_dbg_dprintf(1, sc, 813 "teardown_intr returned %d", error); 814 815 if (sc->irq_res != NULL) 816 if ((error = bus_release_resource(sc->bus_dev, 817 SYS_RES_IRQ, sc->irq_res_id, sc->irq_res))) 818 tw_osli_dbg_dprintf(1, sc, 819 "release_resource(irq) returned %d", error); --- 75 unchanged lines hidden (view full) --- 895static TW_INT32 896twa_shutdown(device_t dev) 897{ 898 struct twa_softc *sc = device_get_softc(dev); 899 TW_INT32 error = 0; 900 901 tw_osli_dbg_dprintf(3, sc, "entered"); 902 |
903 /* Disconnect interrupts. */ 904 error = twa_teardown_intr(sc); 905 |
906 /* Disconnect from the controller. */ 907 if ((error = tw_cl_shutdown_ctlr(&(sc->ctlr_handle), 0))) { 908 tw_osli_printf(sc, "error = %d", 909 TW_CL_SEVERITY_ERROR_STRING, 910 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 911 0x2015, 912 "Failed to shutdown Common Layer/controller", 913 error); --- 172 unchanged lines hidden (view full) --- 1086 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1087 0x7777, 1088 "FALSE Passthru timeout!", 1089 req); 1090#endif /* TW_OSL_DEBUG */ 1091 error = 0; /* False error */ 1092 break; 1093 } |
1094 if (!(tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) { 1095#ifdef TW_OSL_DEBUG 1096 tw_osli_printf(sc, "request = %p", 1097 TW_CL_SEVERITY_ERROR_STRING, 1098 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1099 0x2018, 1100 "Passthru request timed out!", 1101 req); 1102#else /* TW_OSL_DEBUG */ 1103 device_printf((sc)->bus_dev, "Passthru request timed out!\n"); 1104#endif /* TW_OSL_DEBUG */ 1105 tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle)); 1106 } 1107 1108 error = 0; 1109 end_time = tw_osl_get_local_time() + timeout; 1110 continue; |
1111 /* |
1112 * Don't touch req after a reset. It (and any |
1113 * associated data) will be |
1114 * unmapped by the callback. 1115 */ |
1116 } 1117 /* 1118 * Either the request got completed, or we were woken up by a 1119 * signal. Calculate the new timeout, in case it was the latter. 1120 */ 1121 timeout = (end_time - tw_osl_get_local_time()); |
1122 } /* End of while loop */ |
1123 1124 /* If there was a payload, copy it back. */ 1125 if ((!error) && (req->length)) 1126 if ((error = copyout(req->data, user_buf->pdata, 1127 user_buf->driver_pkt.buffer_length))) 1128 tw_osli_printf(sc, "error = %d", 1129 TW_CL_SEVERITY_ERROR_STRING, 1130 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1131 0x2019, 1132 "Could not copyout fw_passthru data_buf", 1133 error); 1134 1135fw_passthru_err: |
1136 |
1137 if (req_pkt->status == TW_CL_ERR_REQ_BUS_RESET) 1138 error = EBUSY; 1139 |
1140 user_buf->driver_pkt.os_status = error; 1141 /* Free resources. */ 1142 if (req->data) 1143 free(req->data, TW_OSLI_MALLOC_CLASS); 1144 tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q); 1145 return(error); 1146} 1147 --- 6 unchanged lines hidden (view full) --- 1154 * Input: req_handle -- ptr to request handle 1155 * Output: None 1156 * Return value: None 1157 */ 1158TW_VOID 1159tw_osl_complete_passthru(struct tw_cl_req_handle *req_handle) 1160{ 1161 struct tw_osli_req_context *req = req_handle->osl_req_ctxt; |
1162 struct tw_cl_req_packet *req_pkt = 1163 (struct tw_cl_req_packet *)(&req->req_pkt); |
1164 struct twa_softc *sc = req->ctlr; 1165 1166 tw_osli_dbg_dprintf(5, sc, "entered"); 1167 1168 if (req->state != TW_OSLI_REQ_STATE_BUSY) { 1169 tw_osli_printf(sc, "request = %p, status = %d", 1170 TW_CL_SEVERITY_ERROR_STRING, 1171 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, --- 31 unchanged lines hidden (view full) --- 1203 } else { 1204 /* 1205 * If the request completed even before mtx_sleep 1206 * was called, simply return. 1207 */ 1208 if (req->flags & TW_OSLI_REQ_FLAGS_MAPPED) 1209 return; 1210 |
1211 if (req_pkt->status == TW_CL_ERR_REQ_BUS_RESET) 1212 return; 1213 |
1214 tw_osli_printf(sc, "request = %p", 1215 TW_CL_SEVERITY_ERROR_STRING, 1216 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1217 0x201C, 1218 "Passthru callback called, " 1219 "and caller not sleeping", 1220 req); 1221 } --- 30 unchanged lines hidden (view full) --- 1252 1253 /* Initialize some fields to their defaults. */ 1254 if (req) { 1255 req->req_handle.osl_req_ctxt = NULL; 1256 req->req_handle.cl_req_ctxt = NULL; 1257 req->req_handle.is_io = 0; 1258 req->data = NULL; 1259 req->length = 0; |
1260 req->deadline = 0; |
1261 req->real_data = NULL; 1262 req->real_length = 0; 1263 req->state = TW_OSLI_REQ_STATE_INIT;/* req being initialized */ 1264 req->flags = 0; 1265 req->error_code = 0; 1266 req->orig_req = NULL; 1267 1268 bzero(&(req->req_pkt), sizeof(struct tw_cl_req_packet)); --- 25 unchanged lines hidden (view full) --- 1294{ 1295 struct tw_osli_req_context *req = 1296 (struct tw_osli_req_context *)arg; 1297 struct twa_softc *sc = req->ctlr; 1298 struct tw_cl_req_packet *req_pkt = &(req->req_pkt); 1299 1300 tw_osli_dbg_dprintf(10, sc, "entered"); 1301 |
1302 if (error == EINVAL) { 1303 req->error_code = error; 1304 return; 1305 } 1306 |
1307 /* Mark the request as currently being processed. */ 1308 req->state = TW_OSLI_REQ_STATE_BUSY; 1309 /* Move the request into the busy queue. */ 1310 tw_osli_req_q_insert_tail(req, TW_OSLI_BUSY_Q); 1311 1312 req->flags |= TW_OSLI_REQ_FLAGS_MAPPED; 1313 1314 if (error == EFBIG) { --- 177 unchanged lines hidden (view full) --- 1492 */ 1493 mtx_lock_spin(sc->io_lock); 1494 if (!(req->flags & TW_OSLI_REQ_FLAGS_MAPPED)) 1495 req->flags |= TW_OSLI_REQ_FLAGS_IN_PROGRESS; 1496 tw_osli_disallow_new_requests(sc, &(req->req_handle)); 1497 mtx_unlock_spin(sc->io_lock); 1498 error = 0; 1499 } else { |
1500 tw_osli_printf(sc, "error = %d", 1501 TW_CL_SEVERITY_ERROR_STRING, 1502 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1503 0x9999, 1504 "Failed to map DMA memory " 1505 "for I/O request", 1506 error); 1507 req->flags |= TW_OSLI_REQ_FLAGS_FAILED; |
1508 /* Free alignment buffer if it was used. */ 1509 if (req->flags & 1510 TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) { 1511 free(req->data, TW_OSLI_MALLOC_CLASS); 1512 /* 1513 * Restore original data pointer 1514 * and length. 1515 */ --- 205 unchanged lines hidden --- |