Lines 2867-2872
call_sim:
Link Here
|
2867 |
{ |
2867 |
{ |
2868 |
struct ccb_relsim *crs; |
2868 |
struct ccb_relsim *crs; |
2869 |
struct cam_ed *dev; |
2869 |
struct cam_ed *dev; |
|
|
2870 |
int release_device; |
2870 |
|
2871 |
|
2871 |
crs = &start_ccb->crs; |
2872 |
crs = &start_ccb->crs; |
2872 |
dev = path->device; |
2873 |
dev = path->device; |
Lines 2875-2880
call_sim:
Link Here
|
2875 |
crs->ccb_h.status = CAM_DEV_NOT_THERE; |
2876 |
crs->ccb_h.status = CAM_DEV_NOT_THERE; |
2876 |
break; |
2877 |
break; |
2877 |
} |
2878 |
} |
|
|
2879 |
release_device = 0; |
2878 |
|
2880 |
|
2879 |
if ((crs->release_flags & RELSIM_ADJUST_OPENINGS) != 0) { |
2881 |
if ((crs->release_flags & RELSIM_ADJUST_OPENINGS) != 0) { |
2880 |
|
2882 |
|
Lines 2889-2894
call_sim:
Link Here
|
2889 |
} |
2891 |
} |
2890 |
} |
2892 |
} |
2891 |
|
2893 |
|
|
|
2894 |
if ((crs->release_flags & RELSIM_RELEASE_AFTER_TIMEOUT) != 0) { |
2895 |
/* |
2896 |
* Since the callout gets a pointer to the device, |
2897 |
* acquire a reference to make sure the device can't |
2898 |
* go away until the callout finishes or is stopped. |
2899 |
* Acquire the ref now since we can't acquire |
2900 |
* bus->eb_mtx while holding devq->send_mtx. |
2901 |
*/ |
2902 |
xpt_acquire_device(dev); |
2903 |
} |
2904 |
|
2892 |
mtx_lock(&dev->sim->devq->send_mtx); |
2905 |
mtx_lock(&dev->sim->devq->send_mtx); |
2893 |
if ((crs->release_flags & RELSIM_RELEASE_AFTER_TIMEOUT) != 0) { |
2906 |
if ((crs->release_flags & RELSIM_RELEASE_AFTER_TIMEOUT) != 0) { |
2894 |
|
2907 |
|
Lines 2901-2906
call_sim:
Link Here
|
2901 |
*/ |
2914 |
*/ |
2902 |
start_ccb->ccb_h.flags &= ~CAM_DEV_QFREEZE; |
2915 |
start_ccb->ccb_h.flags &= ~CAM_DEV_QFREEZE; |
2903 |
callout_stop(&dev->callout); |
2916 |
callout_stop(&dev->callout); |
|
|
2917 |
/* |
2918 |
* If CAM_DEV_REL_TIMEOUT_PENDING is still |
2919 |
* set, then the callout is still |
2920 |
* cancelable, since we hold the callout |
2921 |
* mutex and the callout function clears the |
2922 |
* flag before it ever unlocks/relocks the |
2923 |
* mutex. Since the callout we just stopped |
2924 |
* already had a ref, we don't need another, |
2925 |
* so make sure we release the extra one. |
2926 |
*/ |
2927 |
release_device = 1; |
2904 |
} else { |
2928 |
} else { |
2905 |
|
2929 |
|
2906 |
start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; |
2930 |
start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE; |
Lines 2944-2949
call_sim:
Link Here
|
2944 |
} |
2968 |
} |
2945 |
mtx_unlock(&dev->sim->devq->send_mtx); |
2969 |
mtx_unlock(&dev->sim->devq->send_mtx); |
2946 |
|
2970 |
|
|
|
2971 |
if (release_device) |
2972 |
xpt_release_device(dev); |
2973 |
|
2947 |
if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) == 0) |
2974 |
if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) == 0) |
2948 |
xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE); |
2975 |
xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE); |
2949 |
start_ccb->crs.qfrozen_cnt = dev->ccbq.queue.qfrozen_cnt; |
2976 |
start_ccb->crs.qfrozen_cnt = dev->ccbq.queue.qfrozen_cnt; |
Lines 4308-4315
xpt_release_devq_timeout(void *arg)
Link Here
|
4308 |
CAM_DEBUG_DEV(dev, CAM_DEBUG_TRACE, ("xpt_release_devq_timeout\n")); |
4335 |
CAM_DEBUG_DEV(dev, CAM_DEBUG_TRACE, ("xpt_release_devq_timeout\n")); |
4309 |
devq = dev->sim->devq; |
4336 |
devq = dev->sim->devq; |
4310 |
mtx_assert(&devq->send_mtx, MA_OWNED); |
4337 |
mtx_assert(&devq->send_mtx, MA_OWNED); |
|
|
4338 |
dev->flags &= ~CAM_DEV_REL_TIMEOUT_PENDING; |
4311 |
if (xpt_release_devq_device(dev, /*count*/1, /*run_queue*/TRUE)) |
4339 |
if (xpt_release_devq_device(dev, /*count*/1, /*run_queue*/TRUE)) |
4312 |
xpt_run_devq(devq); |
4340 |
xpt_run_devq(devq); |
|
|
4341 |
mtx_unlock(&devq->send_mtx); |
4342 |
xpt_release_device(dev); |
4313 |
} |
4343 |
} |
4314 |
|
4344 |
|
4315 |
void |
4345 |
void |
Lines 4345-4363
xpt_release_devq_device(struct cam_ed *dev, u_int count, int run_queue)
Link Here
|
4345 |
} |
4375 |
} |
4346 |
dev->ccbq.queue.qfrozen_cnt -= count; |
4376 |
dev->ccbq.queue.qfrozen_cnt -= count; |
4347 |
if (dev->ccbq.queue.qfrozen_cnt == 0) { |
4377 |
if (dev->ccbq.queue.qfrozen_cnt == 0) { |
4348 |
/* |
4378 |
KASSERT((dev->flags & CAM_DEV_REL_ON_COMPLETE) == 0, |
4349 |
* No longer need to wait for a successful |
4379 |
("released the queue while still waiting for completion")); |
4350 |
* command completion. |
4380 |
KASSERT((dev->flags & CAM_DEV_REL_TIMEOUT_PENDING) == 0, |
4351 |
*/ |
4381 |
("released the queue while still having timeout pending")); |
4352 |
dev->flags &= ~CAM_DEV_REL_ON_COMPLETE; |
|
|
4353 |
/* |
4354 |
* Remove any timeouts that might be scheduled |
4355 |
* to release this queue. |
4356 |
*/ |
4357 |
if ((dev->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0) { |
4358 |
callout_stop(&dev->callout); |
4359 |
dev->flags &= ~CAM_DEV_REL_TIMEOUT_PENDING; |
4360 |
} |
4361 |
/* |
4382 |
/* |
4362 |
* Now that we are unfrozen schedule the |
4383 |
* Now that we are unfrozen schedule the |
4363 |
* device so any pending transactions are |
4384 |
* device so any pending transactions are |
Lines 4647-4652
xpt_destroy_device(void *context, int pending)
Link Here
|
4647 |
{ |
4668 |
{ |
4648 |
struct cam_ed *device = context; |
4669 |
struct cam_ed *device = context; |
4649 |
|
4670 |
|
|
|
4671 |
callout_drain(&device->callout); |
4672 |
|
4673 |
/* Release our slot in the devq */ |
4674 |
devq = bus->sim->devq; |
4675 |
mtx_lock(&devq->send_mtx); |
4676 |
cam_devq_resize(devq, devq->send_queue.array_size - 1); |
4677 |
KASSERT((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) == 0, |
4678 |
("destroying device while still having timeout pending")); |
4679 |
mtx_unlock(&devq->send_mtx); |
4680 |
|
4681 |
KASSERT(SLIST_EMPTY(&device->periphs), |
4682 |
("destroying device, but periphs list is not empty")); |
4683 |
KASSERT(device->devq_entry.index == CAM_UNQUEUED_INDEX, |
4684 |
("destroying device while still queued for ccbs")); |
4685 |
|
4686 |
xpt_release_target(device->target); |
4687 |
|
4688 |
cam_ccbq_fini(&device->ccbq); |
4689 |
/* |
4690 |
* Free allocated memory. free(9) does nothing if the |
4691 |
* supplied pointer is NULL, so it is safe to call without |
4692 |
* checking. |
4693 |
*/ |
4694 |
free(device->supported_vpds, M_CAMXPT); |
4695 |
free(device->device_id, M_CAMXPT); |
4696 |
free(device->ext_inq, M_CAMXPT); |
4697 |
free(device->physpath, M_CAMXPT); |
4698 |
free(device->rcap_buf, M_CAMXPT); |
4699 |
free(device->serial_num, M_CAMXPT); |
4700 |
|
4650 |
mtx_lock(&device->device_mtx); |
4701 |
mtx_lock(&device->device_mtx); |
4651 |
mtx_destroy(&device->device_mtx); |
4702 |
mtx_destroy(&device->device_mtx); |
4652 |
free(device, M_CAMDEV); |
4703 |
free(device, M_CAMDEV); |
Lines 4690-4696
xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
Link Here
|
4690 |
device->tag_saved_openings = 0; |
4741 |
device->tag_saved_openings = 0; |
4691 |
device->refcount = 1; |
4742 |
device->refcount = 1; |
4692 |
mtx_init(&device->device_mtx, "CAM device lock", NULL, MTX_DEF); |
4743 |
mtx_init(&device->device_mtx, "CAM device lock", NULL, MTX_DEF); |
4693 |
callout_init_mtx(&device->callout, &devq->send_mtx, 0); |
4744 |
callout_init_mtx(&device->callout, &devq->send_mtx, |
|
|
4745 |
CALLOUT_RETURNUNLOCKED); |
4694 |
TASK_INIT(&device->device_destroy_task, 0, xpt_destroy_device, device); |
4746 |
TASK_INIT(&device->device_destroy_task, 0, xpt_destroy_device, device); |
4695 |
/* |
4747 |
/* |
4696 |
* Hold a reference to our parent bus so it |
4748 |
* Hold a reference to our parent bus so it |
Lines 4735-4768
xpt_release_device(struct cam_ed *device)
Link Here
|
4735 |
device->target->generation++; |
4787 |
device->target->generation++; |
4736 |
mtx_unlock(&bus->eb_mtx); |
4788 |
mtx_unlock(&bus->eb_mtx); |
4737 |
|
4789 |
|
4738 |
/* Release our slot in the devq */ |
|
|
4739 |
devq = bus->sim->devq; |
4740 |
mtx_lock(&devq->send_mtx); |
4741 |
cam_devq_resize(devq, devq->send_queue.array_size - 1); |
4742 |
mtx_unlock(&devq->send_mtx); |
4743 |
|
4744 |
KASSERT(SLIST_EMPTY(&device->periphs), |
4790 |
KASSERT(SLIST_EMPTY(&device->periphs), |
4745 |
("destroying device, but periphs list is not empty")); |
4791 |
("destroying device, but periphs list is not empty")); |
4746 |
KASSERT(device->devq_entry.index == CAM_UNQUEUED_INDEX, |
4792 |
KASSERT(device->devq_entry.index == CAM_UNQUEUED_INDEX, |
4747 |
("destroying device while still queued for ccbs")); |
4793 |
("destroying device while still queued for ccbs")); |
|
|
4794 |
KASSERT((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) == 0, |
4795 |
("destroying device while still having timeout pending")); |
4748 |
|
4796 |
|
4749 |
if ((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0) |
|
|
4750 |
callout_stop(&device->callout); |
4751 |
|
4752 |
xpt_release_target(device->target); |
4753 |
|
4754 |
cam_ccbq_fini(&device->ccbq); |
4755 |
/* |
4756 |
* Free allocated memory. free(9) does nothing if the |
4757 |
* supplied pointer is NULL, so it is safe to call without |
4758 |
* checking. |
4759 |
*/ |
4760 |
free(device->supported_vpds, M_CAMXPT); |
4761 |
free(device->device_id, M_CAMXPT); |
4762 |
free(device->ext_inq, M_CAMXPT); |
4763 |
free(device->physpath, M_CAMXPT); |
4764 |
free(device->rcap_buf, M_CAMXPT); |
4765 |
free(device->serial_num, M_CAMXPT); |
4766 |
taskqueue_enqueue(xsoftc.xpt_taskq, &device->device_destroy_task); |
4797 |
taskqueue_enqueue(xsoftc.xpt_taskq, &device->device_destroy_task); |
4767 |
} |
4798 |
} |
4768 |
|
4799 |
|