diff options
author | simokawa <simokawa@FreeBSD.org> | 2003-05-05 14:50:24 +0000 |
---|---|---|
committer | simokawa <simokawa@FreeBSD.org> | 2003-05-05 14:50:24 +0000 |
commit | d6a0f92ee34493f8f6ed063509b8436ce6d81cc1 (patch) | |
tree | 647e743d2ee5296917ba7d2b6605c7197024398f | |
parent | c0fd079086a2a7e180efec292360922ca8af5851 (diff) | |
download | FreeBSD-src-d6a0f92ee34493f8f6ed063509b8436ce6d81cc1.zip FreeBSD-src-d6a0f92ee34493f8f6ed063509b8436ce6d81cc1.tar.gz |
Write to RESET_START register if TARGET_RESET ORB doesn't work for timeout.
-rw-r--r-- | sys/dev/firewire/sbp.c | 190 |
1 files changed, 138 insertions, 52 deletions
diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c index 5848e59..7a780f9 100644 --- a/sys/dev/firewire/sbp.c +++ b/sys/dev/firewire/sbp.c @@ -258,8 +258,8 @@ struct sbp_cmd_status{ struct sbp_dev{ #define SBP_DEV_RESET 0 /* accept login */ -#if 0 #define SBP_DEV_LOGIN 1 /* to login */ +#if 0 #define SBP_DEV_RECONN 2 /* to reconnect */ #endif #define SBP_DEV_TOATTACH 3 /* to attach */ @@ -268,8 +268,7 @@ struct sbp_dev{ #define SBP_DEV_DEAD 6 /* unavailable unit */ #define SBP_DEV_RETRY 7 /* unavailable unit */ u_int8_t status:4, -#define SBP_DEV_TIMEOUT 1 - flags:4; + timeout:4; u_int8_t type; u_int16_t lun_id; int freeze; @@ -314,7 +313,7 @@ struct sbp_softc { }; static void sbp_post_explore __P((void *)); static void sbp_recv __P((struct fw_xfer *)); -static void sbp_login_callback __P((struct fw_xfer *)); +static void sbp_mgm_callback __P((struct fw_xfer *)); static void sbp_cmd_callback __P((struct fw_xfer *)); static void sbp_orb_pointer __P((struct sbp_dev *, struct sbp_ocb *)); static void sbp_execute_ocb __P((void *, bus_dma_segment_t *, int, int)); @@ -326,6 +325,7 @@ static struct sbp_ocb * sbp_get_ocb __P((struct sbp_dev *)); static struct sbp_ocb * sbp_enqueue_ocb __P((struct sbp_dev *, struct sbp_ocb *)); static struct sbp_ocb * sbp_dequeue_ocb __P((struct sbp_dev *, struct sbp_status *)); static void sbp_cam_detach_target __P((struct sbp_target *)); +static void sbp_mgm_timeout __P((void *arg)); static void sbp_timeout __P((void *arg)); static void sbp_mgm_orb __P((struct sbp_dev *, int, struct sbp_ocb *)); #define sbp_login(sdev) \ @@ -854,15 +854,65 @@ sbp_xfer_free(struct fw_xfer *xfer) } static void -sbp_login_callback(struct fw_xfer *xfer) +sbp_reset_start_callback(struct fw_xfer *xfer) +{ + struct sbp_dev *tsdev, *sdev = (struct sbp_dev *)xfer->sc; + struct sbp_target *target = sdev->target; + int i; + + if (xfer->resp != 0) { + sbp_show_sdev_info(sdev, 2); + printf("sbp_reset_start failed: resp=%d\n", xfer->resp); + } + + for (i = 0; i < target->num_lun; i++) { + tsdev = &target->luns[i]; + if (tsdev->status == SBP_DEV_LOGIN) + sbp_login(sdev); + } +} + +static void +sbp_reset_start(struct sbp_dev *sdev) +{ + struct fw_xfer *xfer; + struct fw_pkt *fp; + +SBP_DEBUG(0) + sbp_show_sdev_info(sdev, 2); + printf("sbp_reset_start\n"); +END_DEBUG + + xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); + xfer->act.hand = sbp_reset_start_callback; + fp = (struct fw_pkt *)xfer->send.buf; + fp->mode.wreqq.dest_hi = 0xffff; + fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START; + fp->mode.wreqq.data = htonl(0xf); + fw_asyreq(xfer->fc, -1, xfer); +} + +static void +sbp_mgm_callback(struct fw_xfer *xfer) { -SBP_DEBUG(1) struct sbp_dev *sdev; + int resp; + sdev = (struct sbp_dev *)xfer->sc; + +SBP_DEBUG(1) sbp_show_sdev_info(sdev, 2); - printf("sbp_login_callback\n"); + printf("sbp_mgm_callback\n"); END_DEBUG + resp = xfer->resp; sbp_xfer_free(xfer); +#if 0 + if (resp != 0) { + sbp_show_sdev_info(sdev, 2); + printf("management ORB failed(%d) ... RESET_START\n", resp); + sbp_reset_start(sdev); + } +#endif return; } @@ -1015,6 +1065,11 @@ SBP_DEBUG(1) sbp_show_sdev_info(sdev, 2); printf("sbp_cmd_callback\n"); END_DEBUG + if (xfer->resp != 0) { + sbp_show_sdev_info(sdev, 2); + printf("sbp_cmd_callback resp=%d\n", xfer->resp); + } + sbp_xfer_free(xfer); if (sdev->path) { xpt_release_devq(sdev->path, sdev->freeze, TRUE); @@ -1078,28 +1133,6 @@ END_DEBUG fw_asyreq(xfer->fc, -1, xfer); } -#if 0 -static void -sbp_reset_start(struct sbp_dev *sdev) -{ - struct fw_xfer *xfer; - struct fw_pkt *fp; - -SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); - printf("sbp_reset_start\n"); -END_DEBUG - xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); - - xfer->act.hand = sbp_busy_timeout; - fp = (struct fw_pkt *)xfer->send.buf; - fp->mode.wreqq.dest_hi = 0xffff; - fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START; - fp->mode.wreqq.data = htonl(0xf); - fw_asyreq(xfer->fc, -1, xfer); -} -#endif - static void sbp_orb_pointer(struct sbp_dev *sdev, struct sbp_ocb *ocb) { @@ -1281,12 +1314,12 @@ start: splx(s); callout_reset(&target->mgm_ocb_timeout, 5*hz, - sbp_timeout, (caddr_t)ocb); + sbp_mgm_timeout, (caddr_t)ocb); xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0); if(xfer == NULL){ return; } - xfer->act.hand = sbp_login_callback; + xfer->act.hand = sbp_mgm_callback; fp = (struct fw_pkt *)xfer->send.buf; fp->mode.wreqb.dest_hi = sdev->target->mgm_hi; @@ -1610,8 +1643,6 @@ END_DEBUG if (ocb == NULL) goto done; - sdev->flags &= ~SBP_DEV_TIMEOUT; - switch(ntohl(ocb->orb[4]) & ORB_FMT_MSK){ case ORB_FMT_NOP: break; @@ -1686,6 +1717,7 @@ END_DEBUG sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); break; case OCB_ACT_CMD: + sdev->timeout = 0; if(ocb->ccb != NULL){ union ccb *ccb; /* @@ -1995,6 +2027,58 @@ END_DEBUG } static void +sbp_target_reset(struct sbp_dev *sdev, int method) +{ + int i; + struct sbp_target *target = sdev->target; + struct sbp_dev *tsdev; + + for (i = 0; i < target->num_lun; i++) { + tsdev = &target->luns[i]; + if (tsdev->status == SBP_DEV_DEAD) + continue; + if (tsdev->status == SBP_DEV_RESET) + continue; + xpt_freeze_devq(tsdev->path, 1); + tsdev->freeze ++; + sbp_abort_all_ocbs(tsdev, CAM_CMD_TIMEOUT); + if (method == 2) + tsdev->status = SBP_DEV_LOGIN; + } + switch(method) { + case 1: + printf("target reset\n"); + sbp_mgm_orb(sdev, ORB_FUN_RST, NULL); + break; + case 2: + printf("reset start\n"); + sbp_reset_start(sdev); + break; + } + +} + +static void +sbp_mgm_timeout(void *arg) +{ + struct sbp_ocb *ocb = (struct sbp_ocb *)arg; + struct sbp_dev *sdev = ocb->sdev; + struct sbp_target *target = sdev->target; + + sbp_show_sdev_info(sdev, 2); + printf("management ORB timeout\n"); + target->mgm_ocb_cur = NULL; + sbp_free_ocb(sdev, ocb); +#if 0 + /* XXX */ + sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); +#endif +#if 0 + sbp_reset_start(sdev); +#endif +} + +static void sbp_timeout(void *arg) { struct sbp_ocb *ocb = (struct sbp_ocb *)arg; @@ -2003,28 +2087,30 @@ sbp_timeout(void *arg) sbp_show_sdev_info(sdev, 2); printf("request timeout ... "); - if (ocb->flags == OCB_ACT_MGM) { - printf("management ORB\n"); - /* XXX just ignore for now */ - sdev->target->mgm_ocb_cur = NULL; - sbp_free_ocb(sdev, ocb); - sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); - return; - } - - xpt_freeze_devq(sdev->path, 1); - sdev->freeze ++; - sbp_abort_all_ocbs(sdev, CAM_CMD_TIMEOUT); - if (sdev->flags & SBP_DEV_TIMEOUT) { - printf("target reset\n"); - sbp_mgm_orb(sdev, ORB_FUN_RST, NULL); - sdev->flags &= ~SBP_DEV_TIMEOUT; - } else { + sdev->timeout ++; + switch(sdev->timeout) { + case 1: printf("agent reset\n"); - sdev->flags |= SBP_DEV_TIMEOUT; + xpt_freeze_devq(sdev->path, 1); + sdev->freeze ++; + sbp_abort_all_ocbs(sdev, CAM_CMD_TIMEOUT); sbp_agent_reset(sdev); + break; + case 2: + case 3: + sbp_target_reset(sdev, sdev->timeout - 1); + break; +#if 0 + default: + /* XXX give up */ + sbp_cam_detach_target(target); + if (target->luns != NULL) + free(target->luns, M_SBP); + target->num_lun = 0;; + target->luns = NULL; + target->fwdev = NULL; +#endif } - return; } static void |