CTL panic

Kenneth D. Merry ken at freebsd.org
Thu Mar 8 21:15:02 UTC 2012


On Thu, Feb 23, 2012 at 13:44:10 -0800, Chuck Tuffli wrote:
> I just tried using our targ(9) compatible driver with CTL today and
> get the below panic. Our driver didn't recognize the
> XPT_IMMEDIATE_NOTIFY and returned CAM_REQ_INVALID which ctlfedone
> doesn't handle explicitly. The following patch seems to avoid this
> problem for me, but there might be a better fix.

Sorry for the delayed response.

Here is a patch that should fix it.  Although it isn't relevant for you
now, since your driver is talking to CTL successfully, it is still needed
for the mpt(4), ahc(4), ahd(4), and firewire drivers that support the older
target mode API.

This hopefully fixes some of the issues inside CTL, and then essentially
prevents CTL from talking to target-capable SIMs that haven't been updated
to support the CCBs that CTL needs.

I'll probably tweak it some more before it goes in the tree.  I got a bug
report from someone with an mpt(4)-based FC controller.  He is running into
the same issue, so I imagine anyone else with an mpt(4) FC controller will
see it as well.

The other drivers don't enable target mode by default, and so won't trigger
this bug unless the user has enabled it in the driver.

Ken
-- 
Kenneth Merry
ken at FreeBSD.ORG
-------------- next part --------------
==== //depot/users/kenm/FreeBSD-test/sys/cam/cam_ccb.h#12 - /usr/home/kenm/perforce4/kenm/FreeBSD-test/sys/cam/cam_ccb.h ====
*** /tmp/tmp.350.95	Thu Mar  8 13:44:51 2012
--- /usr/home/kenm/perforce4/kenm/FreeBSD-test/sys/cam/cam_ccb.h	Thu Mar  8 13:24:26 2012
***************
*** 558,564 ****
  	PIT_DISCONNECT	= 0x20,	/* Disconnects supported in target mode */
  	PIT_TERM_IO	= 0x10,	/* Terminate I/O message supported in TM */
  	PIT_GRP_6	= 0x08,	/* Group 6 commands supported */
! 	PIT_GRP_7	= 0x04	/* Group 7 commands supported */
  } pi_tmflag;
  
  typedef enum {
--- 558,565 ----
  	PIT_DISCONNECT	= 0x20,	/* Disconnects supported in target mode */
  	PIT_TERM_IO	= 0x10,	/* Terminate I/O message supported in TM */
  	PIT_GRP_6	= 0x08,	/* Group 6 commands supported */
! 	PIT_GRP_7	= 0x04,	/* Group 7 commands supported */
! 	PIT_PROC_CTL 	= 0x02	/* Target mode processor (CTL compatible) */
  } pi_tmflag;
  
  typedef enum {
==== //depot/users/kenm/FreeBSD-test/sys/cam/ctl/scsi_ctl.c#3 - /usr/home/kenm/perforce4/kenm/FreeBSD-test/sys/cam/ctl/scsi_ctl.c ====
*** /tmp/tmp.350.168	Thu Mar  8 13:44:51 2012
--- /usr/home/kenm/perforce4/kenm/FreeBSD-test/sys/cam/ctl/scsi_ctl.c	Thu Mar  8 12:45:29 2012
***************
*** 304,312 ****
  		cpi = (struct ccb_pathinq *)arg;
  
  		/* Don't attach if it doesn't support target mode */
! 		if ((cpi->target_sprt & PIT_PROCESSOR) == 0) {
  #ifdef CTLFEDEBUG
! 			printf("%s: SIM %s%d doesn't support target mode\n",
  			       __func__, cpi->dev_name, cpi->unit_number);
  #endif
  			break;
--- 304,313 ----
  		cpi = (struct ccb_pathinq *)arg;
  
  		/* Don't attach if it doesn't support target mode */
! 		if ((cpi->target_sprt & PIT_PROC_CTL) == 0) {
  #ifdef CTLFEDEBUG
! 			printf("%s: SIM %s%d doesn't support CTL-compatible "
! 			       "target mode API\n",
  			       __func__, cpi->dev_name, cpi->unit_number);
  #endif
  			break;
***************
*** 628,639 ****
  		xpt_action(new_ccb);
  		softc->inots_sent++;
  		status = new_ccb->ccb_h.status;
! 		if (status != CAM_REQ_INPROG) {
! 			free(new_ccb, M_CTLFE);
  			break;
  		}
  	}
! 	if (i == 0) {
  		xpt_print(periph->path, "%s: could not allocate immediate "
  			  "notify CCBs, status 0x%x\n", __func__, status);
  		return (CAM_REQ_CMP_ERR);
--- 629,650 ----
  		xpt_action(new_ccb);
  		softc->inots_sent++;
  		status = new_ccb->ccb_h.status;
! 		if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
! 			/*
! 			 * Note that we don't free the CCB here.  If the
! 			 * status is not CAM_REQ_INPROG, then we're
! 			 * probably talking to a SIM that says it is
! 			 * target-capable but doesn't support the 
! 			 * XPT_IMMEDIATE_NOTIFY CCB.  i.e. it supports the
! 			 * older API.  In that case, it'll call xpt_done()
! 			 * on the CCB, and we need to free it in our done
! 			 * routine as a result.
! 			 */
  			break;
  		}
  	}
! 	if ((i == 0)
! 	 || (status != CAM_REQ_INPROG)) {
  		xpt_print(periph->path, "%s: could not allocate immediate "
  			  "notify CCBs, status 0x%x\n", __func__, status);
  		return (CAM_REQ_CMP_ERR);
***************
*** 1460,1471 ****
  				 */
  				send_ctl_io = 0;
  				break;
  			default:
! 				xpt_print(periph->path, "%s: "
! 					  "unsupported CAM status 0x%x\n", 
! 					  __func__, status);
! 				send_ctl_io = 0;
! 				break;
  			}
  			if (send_ctl_io != 0) {
  				ctl_queue(io);
--- 1471,1499 ----
  				 */
  				send_ctl_io = 0;
  				break;
+ 			case CAM_REQ_INVALID:
+ 			case CAM_PROVIDE_FAIL:
  			default:
! 				/*
! 				 * We should only get here if we're talking
! 				 * to a talking to a SIM that is target
! 				 * capable but supports the old API.  In
! 				 * that case, we need to just free the CCB.
! 				 * If we actually send a notify acknowledge,
! 				 * it will send that back with an error as
! 				 * well.
! 				 */
! 
! 				if ((status != CAM_REQ_INVALID)
! 				 && (status != CAM_PROVIDE_FAIL))
! 					xpt_print(periph->path, "%s: "
! 						  "unsupported CAM status "
! 						  "0x%x\n", __func__, status);
! 
! 				ctl_free_io(io);
! 				ctlfe_free_ccb(periph, done_ccb);
! 
! 				return;
  			}
  			if (send_ctl_io != 0) {
  				ctl_queue(io);
==== //depot/users/kenm/FreeBSD-test/sys/dev/isp/isp_freebsd.c#6 - /usr/home/kenm/perforce4/kenm/FreeBSD-test/sys/dev/isp/isp_freebsd.c ====
*** /tmp/tmp.350.194	Thu Mar  8 13:44:51 2012
--- /usr/home/kenm/perforce4/kenm/FreeBSD-test/sys/dev/isp/isp_freebsd.c	Thu Mar  8 12:46:00 2012
***************
*** 4849,4854 ****
--- 4849,4855 ----
  		cpi->version_num = 1;
  #ifdef	ISP_TARGET_MODE
  		cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
+ 		cpi->target_sprt |= PIT_PROC_CTL;
  #else
  		cpi->target_sprt = 0;
  #endif


More information about the freebsd-scsi mailing list