View | Details | Raw Unified | Return to bug 204298 | Differences between
and this patch

Collapse All | Expand All

(-)w/sys/cam/cam_xpt.c (-37 / +68 lines)
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

Return to bug 204298