Clean up the xpt_sim creation to mirror how HBA drivers perform this task.

Clean up node creation in the EDT so that initialization follows member
declaration.

Sort registered paths by pathid so that we probe busses in order of
ascending pathid.  This makes hardwiring of busses without wiring
individual targets do what the user expects. (submitted by tegge@FreeBSD.org)

Fix an EDT node leak.  Target nodes would never go away.

Implement xpt_bus_deregister().
(prodded by some patches from T. Ichinoseki, but implemented differently.)
This commit is contained in:
Justin T. Gibbs 2000-01-14 23:08:46 +00:00
parent 6fc639dcd1
commit 434bbf6e63
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=55995
2 changed files with 127 additions and 74 deletions

View File

@ -623,9 +623,8 @@ static void xpt_async_bcast(struct async_list *async_head,
u_int32_t async_code,
struct cam_path *path,
void *async_arg);
static int xptnextfreebus(path_id_t startbus);
static int xptpathid(const char *sim_name, int sim_unit, int sim_bus,
path_id_t *nextpath);
static path_id_t xptnextfreepathid(void);
static path_id_t xptpathid(const char *sim_name, int sim_unit, int sim_bus);
static union ccb *xpt_get_ccb(struct cam_ed *device);
static int xpt_schedule_dev(struct camq *queue, cam_pinfo *dev_pinfo,
u_int32_t new_priority);
@ -662,6 +661,7 @@ static void xpt_config(void *arg);
static xpt_devicefunc_t xptpassannouncefunc;
static void xpt_finishconfig(struct cam_periph *periph, union ccb *ccb);
static void xptaction(struct cam_sim *sim, union ccb *work_ccb);
static void xptpoll(struct cam_sim *sim);
static swihand_t swi_camnet;
static swihand_t swi_cambio;
static void camisr(cam_isrq_t *queue);
@ -1252,7 +1252,7 @@ xpt_init(dummy)
{
struct cam_sim *xpt_sim;
struct cam_path *path;
struct cam_devq;
struct cam_devq *devq;
cam_status status;
TAILQ_INIT(&xpt_busses);
@ -1267,18 +1267,18 @@ xpt_init(dummy)
* give decent parallelism when we probe busses and
* perform other XPT functions.
*/
xpt_sim = (struct cam_sim *)malloc(sizeof(*xpt_sim),
M_DEVBUF, M_WAITOK);
xpt_sim->sim_action = xptaction;
xpt_sim->sim_name = "xpt";
xpt_sim->path_id = CAM_XPT_PATH_ID;
xpt_sim->bus_id = 0;
xpt_sim->max_tagged_dev_openings = 0;
xpt_sim->max_dev_openings = 0;
xpt_sim->devq = cam_simq_alloc(16);
devq = cam_simq_alloc(16);
xpt_sim = cam_sim_alloc(xptaction,
xptpoll,
"xpt",
/*softc*/NULL,
/*unit*/0,
/*max_dev_transactions*/0,
/*max_tagged_dev_transactions*/0,
devq);
xpt_max_ccbs = 16;
xpt_bus_register(xpt_sim, 0);
xpt_bus_register(xpt_sim, /*bus #*/0);
/*
* Looking at the XPT from the SIM layer, the XPT is
@ -3154,9 +3154,9 @@ xpt_action(union ccb *start_ccb)
csa->ccb_h.status = CAM_RESRC_UNAVAIL;
break;
}
cur_entry->event_enable = csa->event_enable;
cur_entry->callback_arg = csa->callback_arg;
cur_entry->callback = csa->callback;
cur_entry->event_enable = csa->event_enable;
SLIST_INSERT_HEAD(async_head, cur_entry, links);
csa->ccb_h.path->device->refcount++;
}
@ -4017,8 +4017,8 @@ xpt_release_ccb(union ccb *free_ccb)
int32_t
xpt_bus_register(struct cam_sim *sim, u_int32_t bus)
{
static path_id_t buscount;
struct cam_eb *new_bus;
struct cam_eb *old_bus;
struct ccb_pathinq cpi;
int s;
@ -4030,21 +4030,28 @@ xpt_bus_register(struct cam_sim *sim, u_int32_t bus)
return (CAM_RESRC_UNAVAIL);
}
bzero(new_bus, sizeof(*new_bus));
if (strcmp(sim->sim_name, "xpt") != 0) {
sim->path_id = xptpathid(sim->sim_name, sim->unit_number,
sim->bus_id, &buscount);
sim->path_id =
xptpathid(sim->sim_name, sim->unit_number, sim->bus_id);
}
TAILQ_INIT(&new_bus->et_entries);
new_bus->path_id = sim->path_id;
new_bus->sim = sim;
TAILQ_INIT(&new_bus->et_entries);
timevalclear(&new_bus->last_reset);
new_bus->flags = 0;
new_bus->refcount = 1; /* Held until a bus_deregister event */
new_bus->generation = 0;
s = splcam();
TAILQ_INSERT_TAIL(&xpt_busses, new_bus, links);
old_bus = TAILQ_FIRST(&xpt_busses);
while (old_bus != NULL
&& old_bus->path_id < new_bus->path_id)
old_bus = TAILQ_NEXT(old_bus, links);
if (old_bus != NULL)
TAILQ_INSERT_BEFORE(old_bus, new_bus, links);
else
TAILQ_INSERT_TAIL(&xpt_busses, new_bus, links);
bus_generation++;
splx(s);
@ -4063,29 +4070,66 @@ xpt_bus_register(struct cam_sim *sim, u_int32_t bus)
return (CAM_SUCCESS);
}
static int
xptnextfreebus(path_id_t startbus)
int32_t
xpt_bus_deregister(path_id_t pathid)
{
struct cam_path bus_path;
cam_status status;
status = xpt_compile_path(&bus_path, NULL, pathid,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP)
return (status);
xpt_async(AC_LOST_DEVICE, &bus_path, NULL);
xpt_async(AC_PATH_DEREGISTERED, &bus_path, NULL);
/* Release the reference count held while registered. */
xpt_release_bus(bus_path.bus);
xpt_release_path(&bus_path);
return (CAM_REQ_CMP);
}
static path_id_t
xptnextfreepathid(void)
{
struct cam_eb *bus;
path_id_t pathid;
struct cam_sim_config *sim_conf;
pathid = 0;
bus = TAILQ_FIRST(&xpt_busses);
retry:
/* Find an unoccupied pathid */
while (bus != NULL
&& bus->path_id <= pathid) {
if (bus->path_id == pathid)
pathid++;
bus = TAILQ_NEXT(bus, links);
}
/*
* Ensure that this pathid is not reserved for
* a bus that may be registered in the future.
*/
sim_conf = cam_sinit;
while (sim_conf->sim_name != NULL) {
if (IS_SPECIFIED(sim_conf->pathid)
&& (startbus == sim_conf->pathid)) {
++startbus;
&& (pathid == sim_conf->pathid)) {
++pathid;
/* Start the search over */
sim_conf = cam_sinit;
goto retry;
} else {
sim_conf++;
}
}
return (startbus);
return (pathid);
}
static int
xptpathid(const char *sim_name, int sim_unit,
int sim_bus, path_id_t *nextpath)
static path_id_t
xptpathid(const char *sim_name, int sim_unit, int sim_bus)
{
struct cam_sim_config *sim_conf;
path_id_t pathid;
@ -4121,21 +4165,11 @@ xptpathid(const char *sim_name, int sim_unit,
}
}
if (pathid == CAM_XPT_PATH_ID) {
pathid = xptnextfreebus(*nextpath);
*nextpath = pathid + 1;
}
if (pathid == CAM_XPT_PATH_ID)
pathid = xptnextfreepathid();
return (pathid);
}
int32_t
xpt_bus_deregister(path_id)
u_int8_t path_id;
{
/* XXX */
return (CAM_SUCCESS);
}
void
xpt_async(u_int32_t async_code, struct cam_path *path, void *async_arg)
{
@ -4550,16 +4584,17 @@ xpt_alloc_target(struct cam_eb *bus, target_id_t target_id)
if (target != NULL) {
struct cam_et *cur_target;
TAILQ_INIT(&target->ed_entries);
target->bus = bus;
target->target_id = target_id;
target->refcount = 1;
target->generation = 0;
timevalclear(&target->last_reset);
/*
* Hold a reference to our parent bus so it
* will not go away before we do.
*/
bus->refcount++;
TAILQ_INIT(&target->ed_entries);
timevalclear(&target->last_reset);
/* Insertion sort into our bus's target list */
cur_target = TAILQ_FIRST(&bus->et_entries);
@ -4614,45 +4649,49 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
if (device != NULL) {
struct cam_ed *cur_device;
bzero(device, sizeof(*device));
SLIST_INIT(&device->asyncs);
SLIST_INIT(&device->periphs);
callout_handle_init(&device->c_handle);
device->refcount = 1;
device->flags |= CAM_DEV_UNCONFIGURED;
/*
* Take the default quirk entry until we have inquiry
* data and can determine a better quirk to use.
*/
device->quirk = &xpt_quirk_table[xpt_quirk_table_size - 1];
cam_init_pinfo(&device->alloc_ccb_entry.pinfo);
device->alloc_ccb_entry.device = device;
cam_init_pinfo(&device->send_ccb_entry.pinfo);
device->send_ccb_entry.device = device;
device->target = target;
/*
* Hold a reference to our parent target so it
* will not go away before we do.
*/
target->refcount++;
device->lun_id = lun_id;
/* Initialize our queues */
if (camq_init(&device->drvq, 0) != 0) {
free(device, M_DEVBUF);
return (NULL);
}
if (cam_ccbq_init(&device->ccbq,
bus->sim->max_dev_openings) != 0) {
camq_fini(&device->drvq);
free(device, M_DEVBUF);
return (NULL);
}
SLIST_INIT(&device->asyncs);
SLIST_INIT(&device->periphs);
device->generation = 0;
device->owner = NULL;
/*
* Take the default quirk entry until we have inquiry
* data and can determine a better quirk to use.
*/
device->quirk = &xpt_quirk_table[xpt_quirk_table_size - 1];
bzero(&device->inq_data, sizeof(device->inq_data));
device->inq_flags = 0;
device->queue_flags = 0;
device->serial_num = NULL;
device->serial_num_len = 0;
device->qfrozen_cnt = 0;
device->flags = CAM_DEV_UNCONFIGURED;
device->tag_delay_count = 0;
device->refcount = 1;
callout_handle_init(&device->c_handle);
/*
* Hold a reference to our parent target so it
* will not go away before we do.
*/
target->refcount++;
/*
* XXX should be limited by number of CCBs this bus can
* do.
@ -4699,6 +4738,7 @@ xpt_release_device(struct cam_eb *bus, struct cam_et *target,
cam_devq_resize(devq, devq->alloc_queue.array_size - 1);
splx(s);
free(device, M_DEVBUF);
xpt_release_target(bus, target);
} else
splx(s);
}
@ -5139,7 +5179,8 @@ proberegister(struct cam_periph *periph, void *arg)
}
if (request_ccb == NULL) {
printf("proberegister: no probe CCB, can't register device\n");
printf("proberegister: no probe CCB, "
"can't register device\n");
return(CAM_REQ_CMP_ERR);
}
@ -6118,6 +6159,15 @@ xptaction(struct cam_sim *sim, union ccb *work_ccb)
}
}
/*
* The xpt as a "controller" has no interrupt sources, so polling
* is a no-op.
*/
static void
xptpoll(struct cam_sim *sim)
{
}
/*
* Should only be called by the machine interrupt dispatch routines,
* so put these prototypes here instead of in the header.
@ -6215,8 +6265,12 @@ camisr(cam_isrq_t *queue)
if (ccb_h->status & CAM_RELEASE_SIMQ) {
xpt_release_simq(ccb_h->path->bus->sim,
/*run_queue*/TRUE);
} else if ((ccb_h->flags & CAM_DEV_QFRZDIS)
&& (ccb_h->status & CAM_DEV_QFRZN)) {
ccb_h->status &= ~CAM_RELEASE_SIMQ;
runq = FALSE;
}
if ((ccb_h->flags & CAM_DEV_QFRZDIS)
&& (ccb_h->status & CAM_DEV_QFRZN)) {
xpt_release_devq(ccb_h->path, /*count*/1,
/*run_queue*/TRUE);
ccb_h->status &= ~CAM_DEV_QFRZN;
@ -6225,8 +6279,7 @@ camisr(cam_isrq_t *queue)
}
/* Call the peripheral driver's callback */
(*ccb_h->cbfcnp)(ccb_h->path->periph,
(union ccb *)ccb_h);
(*ccb_h->cbfcnp)(ccb_h->path->periph, (union ccb *)ccb_h);
/* Raise IPL for while test */
s = splcam();

View File

@ -38,7 +38,7 @@
/* Functions accessed by SIM drivers */
#ifdef _KERNEL
int32_t xpt_bus_register(struct cam_sim *sim, u_int32_t bus);
int32_t xpt_bus_deregister(u_int8_t path_id);
int32_t xpt_bus_deregister(path_id_t path_id);
u_int32_t xpt_freeze_simq(struct cam_sim *sim, u_int count);
void xpt_release_simq(struct cam_sim *sim, int run_queue);
u_int32_t xpt_freeze_devq(struct cam_path *path, u_int count);