CAM rescanner thread?

mjacob at freebsd.org mjacob at freebsd.org
Thu Jan 4 23:18:10 PST 2007


Opinions? Seems to do what *I* want for automatically attaching devices 
for mpt or isp when they appear on the fabric. All you have to do is
alloc a ccb && a path and call xpt_rescan.

==== //depot/projects/mjexp/sys/cam/cam_xpt.c#4 - /home/FreeBSD/p4/mjexp/sys/cam/cam_xpt.c ====
@@ -46,6 +46,7 @@
  #include <sys/lock.h>
  #include <sys/mutex.h>
  #include <sys/sysctl.h>
+#include <sys/kthread.h>

  #ifdef PC98
  #include <pc98/pc98/pc98_machdep.h>	/* geometry translation */
@@ -1412,10 +1413,50 @@
  	return 0;
  }

+/* thread to handle bus rescans */
+static TAILQ_HEAD(, ccb_hdr) ccb_scanq;
+static void
+xpt_scanner_thread(void *dummy)
+{
+	mtx_lock(&Giant);
+	for (;;) {
+		union ccb *ccb;
+		tsleep(&ccb_scanq, PRIBIO, "ccb_scanq", 0);
+		while ((ccb = (union ccb *)TAILQ_FIRST(&ccb_scanq)) != NULL) {
+			TAILQ_REMOVE(&ccb_scanq, &ccb->ccb_h, sim_links.tqe);
+			ccb->ccb_h.func_code = XPT_SCAN_BUS;
+			ccb->ccb_h.cbfcnp = xptdone;
+			xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 5);
+			cam_periph_runccb(ccb, NULL, 0, 0, NULL);
+			xpt_free_path(ccb->ccb_h.path);
+			xpt_free_ccb(ccb);
+		}
+	}
+}
+
+void
+xpt_rescan(union ccb *ccb)
+{
+	struct ccb_hdr *hdr;
+	GIANT_REQUIRED;
+	/*
+	 * Don't make duplicate entries for the same paths.
+	 */
+	TAILQ_FOREACH(hdr, &ccb_scanq, sim_links.tqe) {
+		if (xpt_path_comp(hdr->path, ccb->ccb_h.path) == 0) {
+			xpt_print(ccb->ccb_h.path, "rescan already queued\n");
+			xpt_free_path(ccb->ccb_h.path);
+			xpt_free_ccb(ccb);
+			return;
+		}
+	}
+	TAILQ_INSERT_TAIL(&ccb_scanq, &ccb->ccb_h, sim_links.tqe);
+	wakeup(&ccb_scanq);
+}
+
  /* Functions accessed by the peripheral drivers */
  static void
-xpt_init(dummy)
-	void *dummy;
+xpt_init(void *dummy)
  {
  	struct cam_sim *xpt_sim;
  	struct cam_path *path;
@@ -1425,6 +1466,7 @@
  	TAILQ_INIT(&xpt_busses);
  	TAILQ_INIT(&cam_bioq);
  	SLIST_INIT(&ccb_freeq);
+	TAILQ_INIT(&ccb_scanq);
  	STAILQ_INIT(&highpowerq);

  	mtx_init(&cam_bioq_lock, "CAM BIOQ lock", NULL, MTX_DEF);
@@ -1490,6 +1532,10 @@
  		       "- failing attach\n");
  	}

+	/* fire up rescan thread */
+	if (kthread_create(xpt_scanner_thread, NULL, NULL, 0, 0, "xpt_thrd")) {
+		printf("xpt_init: failed to create rescan thread\n");
+	}
  	/* Install our software interrupt handlers */
  	swi_add(NULL, "cambio", camisr, &cam_bioq, SWI_CAMBIO, 0, &cambio_ih);
  }
@@ -4453,8 +4499,7 @@
  	bus = TAILQ_FIRST(&xpt_busses);
  retry:
  	/* Find an unoccupied pathid */
-	while (bus != NULL
-	    && bus->path_id <= pathid) {
+	while (bus != NULL && bus->path_id <= pathid) {
  		if (bus->path_id == pathid)
  			pathid++;
  		bus = TAILQ_NEXT(bus, links);
==== //depot/projects/mjexp/sys/cam/cam_xpt.h#2 - /home/FreeBSD/p4/mjexp/sys/cam/cam_xpt.h ====
@@ -72,6 +72,7 @@
  struct cam_periph	*xpt_path_periph(struct cam_path *path);
  void			xpt_async(u_int32_t async_code, struct cam_path *path,
  				  void *async_arg);
+void			xpt_rescan(union ccb *ccb);
  #endif /* _KERNEL */

  #endif /* _CAM_CAM_XPT_H */


More information about the freebsd-scsi mailing list