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