Add an xpt_rescan function and a thread that will field

rescan requests. The purpose of this is to allow a SIM
(or other entities) to request a bus rescan and have it
then fielded in a different (process) context from the
caller.

There are probably better ways to accomplish this, but
it's a very small change that helps solve a number of
problems.

Reviewed by:	Justin, Ken and Scott.
MFC after:	2 weeks
This commit is contained in:
mjacob 2007-02-23 05:47:36 +00:00
parent 17f2e510e6
commit 5688edd003
2 changed files with 50 additions and 4 deletions

View File

@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#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 @@ cam_module_event_handler(module_t mod, int what, void *arg)
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 @@ xpt_init(dummy)
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 @@ xpt_init(dummy)
"- 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 @@ xptnextfreepathid(void)
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);

View File

@ -72,6 +72,7 @@ struct cam_sim *xpt_path_sim(struct cam_path *path);
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 */