1/*- 2 * FreeBSD/CAM specific routines for LSI '909 FC adapters. 3 * FreeBSD Version. 4 * 5 * Copyright (c) 2000, 2001 by Greg Ansley 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 80 unchanged lines hidden (view full) --- 89 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 90 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 91 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 92 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 93 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 94 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 95 */ 96#include <sys/cdefs.h> |
97__FBSDID("$FreeBSD: head/sys/dev/mpt/mpt_cam.c 169293 2007-05-05 20:18:24Z mjacob $"); |
98 99#include <dev/mpt/mpt.h> 100#include <dev/mpt/mpt_cam.h> 101#include <dev/mpt/mpt_raid.h> 102 103#include "dev/mpt/mpilib/mpi_ioc.h" /* XXX Fix Event Handling!!! */ 104#include "dev/mpt/mpilib/mpi_init.h" 105#include "dev/mpt/mpilib/mpi_targ.h" --- 106 unchanged lines hidden (view full) --- 212int 213mpt_cam_attach(struct mpt_softc *mpt) 214{ 215 struct cam_devq *devq; 216 mpt_handler_t handler; 217 int maxq; 218 int error; 219 |
220 MPT_LOCK(mpt); |
221 TAILQ_INIT(&mpt->request_timeout_list); 222 maxq = (mpt->ioc_facts.GlobalCredits < MPT_MAX_REQUESTS(mpt))? 223 mpt->ioc_facts.GlobalCredits : MPT_MAX_REQUESTS(mpt); 224 225 handler.reply_handler = mpt_scsi_reply_handler; 226 error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, 227 &scsi_io_handler_id); 228 if (error != 0) { |
229 MPT_UNLOCK(mpt); 230 goto cleanup; |
231 } 232 233 handler.reply_handler = mpt_scsi_tmf_reply_handler; 234 error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, 235 &scsi_tmf_handler_id); 236 if (error != 0) { |
237 MPT_UNLOCK(mpt); 238 goto cleanup; |
239 } 240 241 /* 242 * If we're fibre channel and could support target mode, we register 243 * an ELS reply handler and give it resources. 244 */ 245 if (mpt->is_fc && (mpt->role & MPT_ROLE_TARGET) != 0) { 246 handler.reply_handler = mpt_fc_els_reply_handler; 247 error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, 248 &fc_els_handler_id); 249 if (error != 0) { |
250 MPT_UNLOCK(mpt); 251 goto cleanup; |
252 } 253 if (mpt_add_els_buffers(mpt) == FALSE) { 254 error = ENOMEM; |
255 MPT_UNLOCK(mpt); 256 goto cleanup; |
257 } 258 maxq -= mpt->els_cmds_allocated; 259 } 260 261 /* 262 * If we support target mode, we register a reply handler for it, 263 * but don't add command resources until we actually enable target 264 * mode. 265 */ 266 if (mpt->is_fc && (mpt->role & MPT_ROLE_TARGET) != 0) { 267 handler.reply_handler = mpt_scsi_tgt_reply_handler; 268 error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, 269 &mpt->scsi_tgt_handler_id); 270 if (error != 0) { |
271 MPT_UNLOCK(mpt); 272 goto cleanup; |
273 } 274 } 275 276 /* 277 * We keep one request reserved for timeout TMF requests. 278 */ 279 mpt->tmf_req = mpt_get_request(mpt, FALSE); 280 if (mpt->tmf_req == NULL) { 281 mpt_prt(mpt, "Unable to allocate dedicated TMF request!\n"); 282 error = ENOMEM; |
283 MPT_UNLOCK(mpt); 284 goto cleanup; |
285 } 286 287 /* 288 * Mark the request as free even though not on the free list. 289 * There is only one TMF request allowed to be outstanding at 290 * a time and the TMF routines perform their own allocation 291 * tracking using the standard state flags. 292 */ 293 mpt->tmf_req->state = REQ_STATE_FREE; 294 maxq--; 295 |
296 /* 297 * The rest of this is CAM foo, for which we need to drop our lock 298 */ 299 MPT_UNLOCK(mpt); 300 |
301 if (mpt_spawn_recovery_thread(mpt) != 0) { 302 mpt_prt(mpt, "Unable to spawn recovery thread!\n"); 303 error = ENOMEM; |
304 goto cleanup; |
305 } 306 307 /* |
308 * Create the device queue for our SIM(s). 309 */ 310 devq = cam_simq_alloc(maxq); 311 if (devq == NULL) { 312 mpt_prt(mpt, "Unable to allocate CAM SIMQ!\n"); 313 error = ENOMEM; 314 goto cleanup; 315 } 316 317 /* 318 * Construct our SIM entry. 319 */ |
320 mpt->sim = 321 mpt_sim_alloc(mpt_action, mpt_poll, "mpt", mpt, 1, maxq, devq); |
322 if (mpt->sim == NULL) { 323 mpt_prt(mpt, "Unable to allocate CAM SIM!\n"); 324 cam_simq_free(devq); 325 error = ENOMEM; 326 goto cleanup; 327 } 328 329 /* 330 * Register exactly this bus. 331 */ |
332 MPT_LOCK(mpt); |
333 if (xpt_bus_register(mpt->sim, 0) != CAM_SUCCESS) { 334 mpt_prt(mpt, "Bus registration Failed!\n"); 335 error = ENOMEM; |
336 MPT_UNLOCK(mpt); |
337 goto cleanup; 338 } 339 340 if (xpt_create_path(&mpt->path, NULL, cam_sim_path(mpt->sim), 341 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 342 mpt_prt(mpt, "Unable to allocate Path!\n"); 343 error = ENOMEM; |
344 MPT_UNLOCK(mpt); |
345 goto cleanup; 346 } |
347 MPT_UNLOCK(mpt); |
348 349 /* 350 * Only register a second bus for RAID physical 351 * devices if the controller supports RAID. 352 */ 353 if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) { |
354 return (0); 355 } 356 357 /* 358 * Create a "bus" to export all hidden disks to CAM. 359 */ |
360 mpt->phydisk_sim = 361 mpt_sim_alloc(mpt_action, mpt_poll, "mpt", mpt, 1, maxq, devq); |
362 if (mpt->phydisk_sim == NULL) { 363 mpt_prt(mpt, "Unable to allocate Physical Disk CAM SIM!\n"); 364 error = ENOMEM; 365 goto cleanup; 366 } 367 368 /* 369 * Register this bus. 370 */ |
371 MPT_LOCK(mpt); |
372 if (xpt_bus_register(mpt->phydisk_sim, 1) != CAM_SUCCESS) { 373 mpt_prt(mpt, "Physical Disk Bus registration Failed!\n"); 374 error = ENOMEM; |
375 MPT_UNLOCK(mpt); |
376 goto cleanup; 377 } 378 379 if (xpt_create_path(&mpt->phydisk_path, NULL, 380 cam_sim_path(mpt->phydisk_sim), 381 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 382 mpt_prt(mpt, "Unable to allocate Physical Disk Path!\n"); 383 error = ENOMEM; |
384 MPT_UNLOCK(mpt); |
385 goto cleanup; 386 } |
387 MPT_UNLOCK(mpt); |
388 mpt_lprt(mpt, MPT_PRT_DEBUG, "attached cam\n"); 389 return (0); 390 391cleanup: |
392 mpt_cam_detach(mpt); 393 return (error); 394} 395 396/* 397 * Read FC configuration information 398 */ 399static int --- 51 unchanged lines hidden (view full) --- 451 "FC Port Page 0: Topology <%s> WWNN 0x%08x%08x WWPN 0x%08x%08x " 452 "Speed %u-Gbit\n", topology, 453 mpt->mpt_fcport_page0.WWNN.High, 454 mpt->mpt_fcport_page0.WWNN.Low, 455 mpt->mpt_fcport_page0.WWPN.High, 456 mpt->mpt_fcport_page0.WWPN.Low, 457 mpt->mpt_fcport_speed); 458#if __FreeBSD_version >= 500000 |
459 MPT_UNLOCK(mpt); |
460 { 461 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(mpt->dev); 462 struct sysctl_oid *tree = device_get_sysctl_tree(mpt->dev); 463 464 snprintf(mpt->scinfo.fc.wwnn, 465 sizeof (mpt->scinfo.fc.wwnn), "0x%08x%08x", 466 mpt->mpt_fcport_page0.WWNN.High, 467 mpt->mpt_fcport_page0.WWNN.Low); --- 7 unchanged lines hidden (view full) --- 475 "wwnn", CTLFLAG_RD, mpt->scinfo.fc.wwnn, 0, 476 "World Wide Node Name"); 477 478 SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 479 "wwpn", CTLFLAG_RD, mpt->scinfo.fc.wwpn, 0, 480 "World Wide Port Name"); 481 482 } |
483 MPT_LOCK(mpt); |
484#endif 485 return (0); 486} 487 488/* 489 * Set FC configuration information. 490 */ 491static int --- 316 unchanged lines hidden (view full) --- 808 } 809 } 810 return (0); 811} 812 813int 814mpt_cam_enable(struct mpt_softc *mpt) 815{ |
816 int error; 817 818 MPT_LOCK(mpt); 819 820 error = EIO; |
821 if (mpt->is_fc) { 822 if (mpt_read_config_info_fc(mpt)) { |
823 goto out; |
824 } 825 if (mpt_set_initial_config_fc(mpt)) { |
826 goto out; |
827 } 828 } else if (mpt->is_sas) { 829 if (mpt_read_config_info_sas(mpt)) { |
830 goto out; |
831 } 832 if (mpt_set_initial_config_sas(mpt)) { |
833 goto out; |
834 } 835 } else if (mpt->is_spi) { 836 if (mpt_read_config_info_spi(mpt)) { |
837 goto out; |
838 } 839 if (mpt_set_initial_config_spi(mpt)) { |
840 goto out; |
841 } 842 } |
843 error = 0; 844 845out: 846 MPT_UNLOCK(mpt); 847 return (error); |
848} 849 850void 851mpt_cam_ready(struct mpt_softc *mpt) 852{ 853 /* 854 * If we're in target mode, hang out resources now 855 * so we don't cause the world to hang talking to us. --- 11 unchanged lines hidden (view full) --- 867 mpt->ready = 1; 868} 869 870void 871mpt_cam_detach(struct mpt_softc *mpt) 872{ 873 mpt_handler_t handler; 874 |
875 MPT_LOCK(mpt); |
876 mpt->ready = 0; 877 mpt_terminate_recovery_thread(mpt); 878 879 handler.reply_handler = mpt_scsi_reply_handler; 880 mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler, 881 scsi_io_handler_id); 882 handler.reply_handler = mpt_scsi_tmf_reply_handler; 883 mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler, --- 5 unchanged lines hidden (view full) --- 889 mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler, 890 mpt->scsi_tgt_handler_id); 891 892 if (mpt->tmf_req != NULL) { 893 mpt->tmf_req->state = REQ_STATE_ALLOCATED; 894 mpt_free_request(mpt, mpt->tmf_req); 895 mpt->tmf_req = NULL; 896 } |
897 MPT_UNLOCK(mpt); |
898 899 if (mpt->sim != NULL) { |
900 xpt_free_path(mpt->path); 901 xpt_bus_deregister(cam_sim_path(mpt->sim)); 902 cam_sim_free(mpt->sim, TRUE); 903 mpt->sim = NULL; |
904 } 905 906 if (mpt->phydisk_sim != NULL) { |
907 xpt_free_path(mpt->phydisk_path); 908 xpt_bus_deregister(cam_sim_path(mpt->phydisk_sim)); 909 cam_sim_free(mpt->phydisk_sim, TRUE); 910 mpt->phydisk_sim = NULL; |
911 } 912} 913 914/* This routine is used after a system crash to dump core onto the swap device. 915 */ 916static void 917mpt_poll(struct cam_sim *sim) 918{ 919 struct mpt_softc *mpt; 920 921 mpt = (struct mpt_softc *)cam_sim_softc(sim); |
922 mpt_intr(mpt); |
923} 924 925/* 926 * Watchdog timeout routine for SCSI requests. 927 */ 928static void 929mpt_timeout(void *arg) 930{ --- 389 unchanged lines hidden (view full) --- 1320 CAMLOCK_2_MPTLOCK(mpt); 1321 mpt_free_request(mpt, req); 1322 MPTLOCK_2_CAMLOCK(mpt); 1323 return; 1324 } 1325 1326 ccb->ccb_h.status |= CAM_SIM_QUEUED; 1327 if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { |
1328 mpt_req_timeout(req, (ccb->ccb_h.timeout * hz) / 1000, 1329 mpt_timeout, ccb); |
1330 } else { |
1331 mpt_req_timeout_init(req); |
1332 } 1333 if (mpt->verbose > MPT_PRT_DEBUG) { 1334 int nc = 0; 1335 mpt_print_request(req->req_vbuf); 1336 for (trq = req->chain; trq; trq = trq->chain) { 1337 printf(" Additional Chain Area %d\n", nc++); 1338 mpt_dump_sgl(trq->req_vbuf, 0); 1339 } --- 381 unchanged lines hidden (view full) --- 1721 CAMLOCK_2_MPTLOCK(mpt); 1722 mpt_free_request(mpt, req); 1723 MPTLOCK_2_CAMLOCK(mpt); 1724 return; 1725 } 1726 1727 ccb->ccb_h.status |= CAM_SIM_QUEUED; 1728 if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { |
1729 mpt_req_timeout(req, (ccb->ccb_h.timeout * hz) / 1000, 1730 mpt_timeout, ccb); |
1731 } else { |
1732 mpt_req_timeout_init(req); |
1733 } 1734 if (mpt->verbose > MPT_PRT_DEBUG) { 1735 int nc = 0; 1736 mpt_print_request(req->req_vbuf); 1737 for (trq = req->chain; trq; trq = trq->chain) { 1738 printf(" Additional Chain Area %d\n", nc++); 1739 mpt_dump_sgl(trq->req_vbuf, 0); 1740 } --- 551 unchanged lines hidden (view full) --- 2292 ccb = req->ccb; 2293 if (ccb == NULL) { 2294 mpt_prt(mpt, "mpt_scsi_reply_handler: req %p:%u with no ccb\n", 2295 req, req->serno); 2296 return (TRUE); 2297 } 2298 2299 tgt = scsi_req->TargetID; |
2300 mpt_req_untimeout(req, mpt_timeout, ccb); |
2301 ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 2302 2303 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 2304 bus_dmasync_op_t op; 2305 2306 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 2307 op = BUS_DMASYNC_POSTREAD; 2308 else --- 606 unchanged lines hidden (view full) --- 2915 struct ccb_trans_settings *cts; 2916 target_id_t tgt; 2917 lun_id_t lun; 2918 int raid_passthru; 2919 2920 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mpt_action\n")); 2921 2922 mpt = (struct mpt_softc *)cam_sim_softc(sim); |
2923 raid_passthru = (sim == mpt->phydisk_sim); |
2924 MPT_LOCK_ASSERT(mpt); |
2925 2926 tgt = ccb->ccb_h.target_id; 2927 lun = ccb->ccb_h.target_lun; 2928 if (raid_passthru && 2929 ccb->ccb_h.func_code != XPT_PATH_INQ && 2930 ccb->ccb_h.func_code != XPT_RESET_BUS && 2931 ccb->ccb_h.func_code != XPT_RESET_DEV) { 2932 CAMLOCK_2_MPTLOCK(mpt); --- 730 unchanged lines hidden (view full) --- 3663 mpt_sleep(mpt, &mpt->recovery_thread, PUSER, "thtrm", 0); 3664} 3665 3666static void 3667mpt_recovery_thread(void *arg) 3668{ 3669 struct mpt_softc *mpt; 3670 |
3671 mpt = (struct mpt_softc *)arg; 3672 MPT_LOCK(mpt); 3673 for (;;) { 3674 if (TAILQ_EMPTY(&mpt->request_timeout_list) != 0) { 3675 if (mpt->shutdwn_recovery == 0) { 3676 mpt_sleep(mpt, mpt, PUSER, "idle", 0); 3677 } 3678 } 3679 if (mpt->shutdwn_recovery != 0) { 3680 break; 3681 } 3682 mpt_recover_commands(mpt); 3683 } 3684 mpt->recovery_thread = NULL; 3685 wakeup(&mpt->recovery_thread); 3686 MPT_UNLOCK(mpt); |
3687 kthread_exit(0); 3688} 3689 3690static int 3691mpt_scsi_send_tmf(struct mpt_softc *mpt, u_int type, u_int flags, 3692 u_int channel, u_int target, u_int lun, u_int abort_ctx, int sleep_ok) 3693{ 3694 MSG_SCSI_TASK_MGMT *tmf_req; --- 923 unchanged lines hidden (view full) --- 4618 } 4619 4620 mpt_lprt(mpt, MPT_PRT_DEBUG, 4621 "STATUS_CCB %p (wit%s sense) tag %x req %p:%u resid %u\n", 4622 ccb, sense_data?"h" : "hout", ccb? ccb->csio.tag_id : -1, req, 4623 req->serno, tgt->resid); 4624 if (ccb) { 4625 ccb->ccb_h.status = CAM_SIM_QUEUED | CAM_REQ_INPROG; |
4626 mpt_req_timeout(req, 60 * hz, mpt_timeout, ccb); |
4627 } 4628 mpt_send_cmd(mpt, req); 4629} 4630 4631static void 4632mpt_scsi_tgt_tsk_mgmt(struct mpt_softc *mpt, request_t *req, mpt_task_mgmt_t fc, 4633 tgt_resource_t *trtp, int init_id) 4634{ --- 398 unchanged lines hidden (view full) --- 5033 mpt_free_request(mpt, tgt->req); 5034 tgt->req = NULL; 5035 mpt_scsi_tgt_status(mpt, NULL, req, 5036 0, NULL); 5037 return (TRUE); 5038 } 5039 tgt->ccb = NULL; 5040 tgt->nxfers++; |
5041 mpt_req_untimeout(req, mpt_timeout, ccb); |
5042 mpt_lprt(mpt, MPT_PRT_DEBUG, 5043 "TARGET_ASSIST %p (req %p:%u) done tag 0x%x\n", 5044 ccb, tgt->req, tgt->req->serno, ccb->csio.tag_id); 5045 /* 5046 * Free the Target Assist Request 5047 */ 5048 KASSERT(tgt->req->ccb == ccb, 5049 ("tgt->req %p:%u tgt->req->ccb %p", tgt->req, --- 48 unchanged lines hidden (view full) --- 5098 } 5099 5100 if (ccb) { 5101 tgt->ccb = NULL; 5102 if (tgt->state == 5103 TGT_STATE_MOVING_DATA_AND_STATUS) { 5104 tgt->nxfers++; 5105 } |
5106 mpt_req_untimeout(req, mpt_timeout, ccb); |
5107 if (ccb->ccb_h.flags & CAM_SEND_SENSE) { 5108 ccb->ccb_h.status |= CAM_SENT_SENSE; 5109 } 5110 mpt_lprt(mpt, MPT_PRT_DEBUG, 5111 "TARGET_STATUS tag %x sts %x flgs %x req " 5112 "%p\n", ccb->csio.tag_id, ccb->ccb_h.status, 5113 ccb->ccb_h.flags, tgt->req); 5114 /* --- 127 unchanged lines hidden --- |