1/*-
2 * Generic SCSI Target Kernel Mode Driver
3 *
4 * Copyright (c) 2002 Nate Lawson.
5 * Copyright (c) 1998, 1999, 2001, 2002 Justin T. Gibbs.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
--- 14 unchanged lines hidden (view full) ---
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_target.c 168752 2007-04-15 08:49:19Z scottl $");
32
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/kernel.h>
37#include <sys/conf.h>
38#include <sys/malloc.h>
39#include <sys/poll.h>
40#include <sys/vnode.h>
41#include <sys/lock.h>
42#include <sys/mutex.h>
43#include <sys/devicestat.h>
44#include <sys/proc.h>
45
46#include <cam/cam.h>
47#include <cam/cam_ccb.h>
48#include <cam/cam_periph.h>
49#include <cam/cam_xpt_periph.h>
50#include <cam/cam_sim.h>
51#include <cam/scsi/scsi_targetio.h>
52
53/* Transaction information attached to each CCB sent by the user */
54struct targ_cmd_descr {
55 struct cam_periph_map_info mapinfo;
56 TAILQ_ENTRY(targ_cmd_descr) tqe;
57 union ccb *user_ccb;
58 int priority;
--- 97 unchanged lines hidden (view full) ---
156{
157 targinit, "targ",
158 TAILQ_HEAD_INITIALIZER(targdriver.units), /* generation */ 0
159};
160PERIPHDRIVER_DECLARE(targ, targdriver);
161
162static MALLOC_DEFINE(M_TARG, "TARG", "TARG data");
163
164/*
165 * Create softc and initialize it. Only one proc can open each targ device.
166 * There is no locking here because a periph doesn't get created until an
167 * ioctl is issued to do so, and that can't happen until this method returns.
168 */
169static int
170targopen(struct cdev *dev, int flags, int fmt, struct thread *td)
171{
172 struct targ_softc *softc;
173
174 if (dev->si_drv1 != 0) {
175 return (EBUSY);
176 }
--- 22 unchanged lines hidden (view full) ---
199 return (0);
200}
201
202/* Disable LUN if enabled and teardown softc */
203static int
204targclose(struct cdev *dev, int flag, int fmt, struct thread *td)
205{
206 struct targ_softc *softc;
207 struct cam_periph *periph;
208 int error;
209
210 softc = (struct targ_softc *)dev->si_drv1;
211 if ((softc->periph == NULL) ||
212 (softc->state & TARG_STATE_LUN_ENABLED) == 0) {
213 destroy_dev(dev);
214 FREE(softc, M_TARG);
215 return (0);
216 }
217
218 /*
219 * Acquire a hold on the periph so that it doesn't go away before
220 * we are ready at the end of the function.
221 */
222 periph = softc->periph;
223 cam_periph_acquire(periph);
224 cam_periph_lock(periph);
225 error = targdisable(softc);
226 if (error == CAM_REQ_CMP) {
227 dev->si_drv1 = 0;
228 if (softc->periph != NULL) {
229 cam_periph_invalidate(softc->periph);
230 softc->periph = NULL;
231 }
232 destroy_dev(dev);
233 FREE(softc, M_TARG);
234 }
235 cam_periph_unlock(periph);
236 cam_periph_release(periph);
237
238 return (error);
239}
240
241/* Enable/disable LUNs, set debugging level */
242static int
243targioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
244{
245 struct targ_softc *softc;
246 cam_status status;
247
248 softc = (struct targ_softc *)dev->si_drv1;
249
250 switch (cmd) {
251 case TARGIOCENABLE:
252 {
253 struct ioc_enable_lun *new_lun;
254 struct cam_path *path;
255 struct cam_sim *sim;
256
257 new_lun = (struct ioc_enable_lun *)addr;
258 status = xpt_create_path_unlocked(&path, /*periph*/NULL,
259 new_lun->path_id,
260 new_lun->target_id,
261 new_lun->lun_id);
262 if (status != CAM_REQ_CMP) {
263 printf("Couldn't create path, status %#x\n", status);
264 break;
265 }
266 sim = xpt_path_sim(path);
267 mtx_lock(sim->mtx);
268 status = targenable(softc, path, new_lun->grp6_len,
269 new_lun->grp7_len);
270 xpt_free_path(path);
271 mtx_unlock(sim->mtx);
272 break;
273 }
274 case TARGIOCDISABLE:
275 if (softc->periph == NULL) {
276 status = CAM_DEV_NOT_THERE;
277 break;
278 }
279 cam_periph_lock(softc->periph);
280 status = targdisable(softc);
281 cam_periph_unlock(softc->periph);
282 break;
283 case TARGIOCDEBUG:
284 {
285#ifdef CAMDEBUG
286 struct ccb_debug cdbg;
287
288 /* If no periph available, disallow debugging changes */
289 if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
290 status = CAM_DEV_NOT_THERE;
291 break;
292 }
293 bzero(&cdbg, sizeof cdbg);
294 if (*((int *)addr) != 0)
295 cdbg.flags = CAM_DEBUG_PERIPH;
296 else
297 cdbg.flags = CAM_DEBUG_NONE;
298 cam_periph_lock(softc->periph);
299 xpt_setup_ccb(&cdbg.ccb_h, softc->path, /*priority*/0);
300 cdbg.ccb_h.func_code = XPT_DEBUG;
301 cdbg.ccb_h.cbfcnp = targdone;
302
303 xpt_action((union ccb *)&cdbg);
304 cam_periph_unlock(softc->periph);
305 status = cdbg.ccb_h.status & CAM_STATUS_MASK;
306#else
307 status = CAM_FUNC_NOTAVAIL;
308#endif
309 break;
310 }
311 default:
312 status = CAM_PROVIDE_FAIL;
--- 11 unchanged lines hidden (view full) ---
324 int revents;
325
326 softc = (struct targ_softc *)dev->si_drv1;
327
328 /* Poll for write() is always ok. */
329 revents = poll_events & (POLLOUT | POLLWRNORM);
330 if ((poll_events & (POLLIN | POLLRDNORM)) != 0) {
331 /* Poll for read() depends on user and abort queues. */
332 cam_periph_lock(softc->periph);
333 if (!TAILQ_EMPTY(&softc->user_ccb_queue) ||
334 !TAILQ_EMPTY(&softc->abort_queue)) {
335 revents |= poll_events & (POLLIN | POLLRDNORM);
336 }
337 cam_periph_unlock(softc->periph);
338 /* Only sleep if the user didn't poll for write. */
339 if (revents == 0)
340 selrecord(td, &softc->read_select);
341 }
342
343 return (revents);
344}
345
--- 21 unchanged lines hidden (view full) ---
367/* Notify the user's kqueue when the user queue or abort queue gets a CCB */
368static int
369targreadfilt(struct knote *kn, long hint)
370{
371 struct targ_softc *softc;
372 int retval;
373
374 softc = (struct targ_softc *)kn->kn_hook;
375 cam_periph_lock(softc->periph);
376 retval = !TAILQ_EMPTY(&softc->user_ccb_queue) ||
377 !TAILQ_EMPTY(&softc->abort_queue);
378 cam_periph_unlock(softc->periph);
379 return (retval);
380}
381
382/* Send the HBA the enable/disable message */
383static cam_status
384targendislun(struct cam_path *path, int enable, int grp6_len, int grp7_len)
385{
386 struct ccb_en_lun en_ccb;
--- 179 unchanged lines hidden (view full) ---
566 if (priority == -1) {
567 error = EINVAL;
568 break;
569 }
570 func_code = fuword32(&user_ccb->ccb_h.func_code);
571 switch (func_code) {
572 case XPT_ACCEPT_TARGET_IO:
573 case XPT_IMMED_NOTIFY:
574 cam_periph_lock(softc->periph);
575 ccb = targgetccb(softc, func_code, priority);
576 descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
577 descr->user_ccb = user_ccb;
578 descr->func_code = func_code;
579 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
580 ("Sent ATIO/INOT (%p)\n", user_ccb));
581 xpt_action(ccb);
582 TAILQ_INSERT_TAIL(&softc->pending_ccb_queue,
583 &ccb->ccb_h,
584 periph_links.tqe);
585 cam_periph_unlock(softc->periph);
586 break;
587 default:
588 cam_periph_lock(softc->periph);
589 if ((func_code & XPT_FC_QUEUED) != 0) {
590 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
591 ("Sending queued ccb %#x (%p)\n",
592 func_code, user_ccb));
593 descr = targgetdescr(softc);
594 descr->user_ccb = user_ccb;
595 descr->priority = priority;
596 descr->func_code = func_code;
--- 9 unchanged lines hidden (view full) ---
606 ccb->ccb_h.targ_descr;
607 descr->user_ccb = user_ccb;
608 descr->priority = priority;
609 descr->func_code = func_code;
610 if (targusermerge(softc, descr, ccb) != EFAULT)
611 targsendccb(softc, ccb, descr);
612 targreturnccb(softc, ccb);
613 }
614 cam_periph_unlock(softc->periph);
615 break;
616 }
617 write_len += sizeof(user_ccb);
618 }
619
620 /*
621 * If we've successfully taken in some amount of
622 * data, return success for that data first. If
--- 211 unchanged lines hidden (view full) ---
834 struct descr_queue *abort_queue;
835 struct targ_cmd_descr *user_descr;
836 struct targ_softc *softc;
837 struct ccb_queue *user_queue;
838 struct ccb_hdr *ccb_h;
839 union ccb *user_ccb;
840 int read_len, error;
841
842 error = 0;
843 read_len = 0;
844 softc = (struct targ_softc *)dev->si_drv1;
845 user_queue = &softc->user_ccb_queue;
846 abort_queue = &softc->abort_queue;
847 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"));
848
849 /* If no data is available, wait or return immediately */
850 cam_periph_lock(softc->periph);
851 ccb_h = TAILQ_FIRST(user_queue);
852 user_descr = TAILQ_FIRST(abort_queue);
853 while (ccb_h == NULL && user_descr == NULL) {
854 if ((ioflag & IO_NDELAY) == 0) {
855 error = msleep(user_queue, softc->periph->sim->mtx,
856 PRIBIO | PCATCH, "targrd", 0);
857 ccb_h = TAILQ_FIRST(user_queue);
858 user_descr = TAILQ_FIRST(abort_queue);
859 if (error != 0) {
860 if (error == ERESTART) {
861 continue;
862 } else {
863 goto read_fail;
864 }
865 }
866 } else {
867 cam_periph_unlock(softc->periph);
868 return (EAGAIN);
869 }
870 }
871
872 /* Data is available so fill the user's buffer */
873 while (ccb_h != NULL) {
874 struct targ_cmd_descr *descr;
875
876 if (uio->uio_resid < sizeof(user_ccb))
877 break;
878 TAILQ_REMOVE(user_queue, ccb_h, periph_links.tqe);
879 descr = (struct targ_cmd_descr *)ccb_h->targ_descr;
880 user_ccb = descr->user_ccb;
881 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
882 ("targread ccb %p (%p)\n", ccb_h, user_ccb));
883 error = targreturnccb(softc, (union ccb *)ccb_h);
884 if (error != 0)
885 goto read_fail;
886 cam_periph_unlock(softc->periph);
887 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
888 cam_periph_lock(softc->periph);
889 if (error != 0)
890 goto read_fail;
891 read_len += sizeof(user_ccb);
892
893 ccb_h = TAILQ_FIRST(user_queue);
894 }
895
896 /* Flush out any aborted descriptors */
897 while (user_descr != NULL) {
898 if (uio->uio_resid < sizeof(user_ccb))
899 break;
900 TAILQ_REMOVE(abort_queue, user_descr, tqe);
901 user_ccb = user_descr->user_ccb;
902 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
903 ("targread aborted descr %p (%p)\n",
904 user_descr, user_ccb));
905 suword(&user_ccb->ccb_h.status, CAM_REQ_ABORTED);
906 cam_periph_unlock(softc->periph);
907 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
908 cam_periph_lock(softc->periph);
909 if (error != 0)
910 goto read_fail;
911 read_len += sizeof(user_ccb);
912
913 user_descr = TAILQ_FIRST(abort_queue);
914 }
915
916 /*
917 * If we've successfully read some amount of data, don't report an
918 * error. If the error is persistent, it will be reported on the
919 * next read().
920 */
921 if (read_len == 0 && uio->uio_resid != 0)
922 error = ENOSPC;
923
924read_fail:
925 cam_periph_unlock(softc->periph);
926 return (error);
927}
928
929/* Copy completed ccb back to the user */
930static int
931targreturnccb(struct targ_softc *softc, union ccb *ccb)
932{
933 struct targ_cmd_descr *descr;
--- 112 unchanged lines hidden (view full) ---
1046
1047/* Cancel all pending requests and CCBs awaiting work. */
1048static void
1049abort_all_pending(struct targ_softc *softc)
1050{
1051 struct targ_cmd_descr *descr;
1052 struct ccb_abort cab;
1053 struct ccb_hdr *ccb_h;
1054 struct cam_sim *sim;
1055
1056 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("abort_all_pending\n"));
1057
1058 /* First abort the descriptors awaiting resources */
1059 while ((descr = TAILQ_FIRST(&softc->work_queue)) != NULL) {
1060 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
1061 ("Aborting descr from workq %p\n", descr));
1062 TAILQ_REMOVE(&softc->work_queue, descr, tqe);
--- 16 unchanged lines hidden (view full) ---
1079 xpt_print(cab.ccb_h.path,
1080 "Unable to abort CCB, status %#x\n",
1081 cab.ccb_h.status);
1082 }
1083 }
1084
1085 /* If we aborted at least one pending CCB ok, wait for it. */
1086 if (cab.ccb_h.status == CAM_REQ_CMP) {
1087 sim = xpt_path_sim(softc->path);
1088 msleep(&softc->pending_ccb_queue, sim->mtx,
1089 PRIBIO | PCATCH, "tgabrt", 0);
1090 }
1091
1092 /* If we aborted anything from the work queue, wakeup user. */
1093 if (!TAILQ_EMPTY(&softc->user_ccb_queue)
1094 || !TAILQ_EMPTY(&softc->abort_queue))
1095 notify_user(softc);
1096}
--- 91 unchanged lines hidden ---
2 * Generic SCSI Target Kernel Mode Driver
3 *
4 * Copyright (c) 2002 Nate Lawson.
5 * Copyright (c) 1998, 1999, 2001, 2002 Justin T. Gibbs.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
--- 14 unchanged lines hidden (view full) ---
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_target.c 168752 2007-04-15 08:49:19Z scottl $");
32
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/kernel.h>
37#include <sys/conf.h>
38#include <sys/malloc.h>
39#include <sys/poll.h>
40#include <sys/vnode.h>
41#include <sys/lock.h>
42#include <sys/mutex.h>
43#include <sys/devicestat.h>
44#include <sys/proc.h>
45
46#include <cam/cam.h>
47#include <cam/cam_ccb.h>
48#include <cam/cam_periph.h>
49#include <cam/cam_xpt_periph.h>
50#include <cam/cam_sim.h>
51#include <cam/scsi/scsi_targetio.h>
52
53/* Transaction information attached to each CCB sent by the user */
54struct targ_cmd_descr {
55 struct cam_periph_map_info mapinfo;
56 TAILQ_ENTRY(targ_cmd_descr) tqe;
57 union ccb *user_ccb;
58 int priority;
--- 97 unchanged lines hidden (view full) ---
156{
157 targinit, "targ",
158 TAILQ_HEAD_INITIALIZER(targdriver.units), /* generation */ 0
159};
160PERIPHDRIVER_DECLARE(targ, targdriver);
161
162static MALLOC_DEFINE(M_TARG, "TARG", "TARG data");
163
164/*
165 * Create softc and initialize it. Only one proc can open each targ device.
166 * There is no locking here because a periph doesn't get created until an
167 * ioctl is issued to do so, and that can't happen until this method returns.
168 */
169static int
170targopen(struct cdev *dev, int flags, int fmt, struct thread *td)
171{
172 struct targ_softc *softc;
173
174 if (dev->si_drv1 != 0) {
175 return (EBUSY);
176 }
--- 22 unchanged lines hidden (view full) ---
199 return (0);
200}
201
202/* Disable LUN if enabled and teardown softc */
203static int
204targclose(struct cdev *dev, int flag, int fmt, struct thread *td)
205{
206 struct targ_softc *softc;
207 struct cam_periph *periph;
208 int error;
209
210 softc = (struct targ_softc *)dev->si_drv1;
211 if ((softc->periph == NULL) ||
212 (softc->state & TARG_STATE_LUN_ENABLED) == 0) {
213 destroy_dev(dev);
214 FREE(softc, M_TARG);
215 return (0);
216 }
217
218 /*
219 * Acquire a hold on the periph so that it doesn't go away before
220 * we are ready at the end of the function.
221 */
222 periph = softc->periph;
223 cam_periph_acquire(periph);
224 cam_periph_lock(periph);
225 error = targdisable(softc);
226 if (error == CAM_REQ_CMP) {
227 dev->si_drv1 = 0;
228 if (softc->periph != NULL) {
229 cam_periph_invalidate(softc->periph);
230 softc->periph = NULL;
231 }
232 destroy_dev(dev);
233 FREE(softc, M_TARG);
234 }
235 cam_periph_unlock(periph);
236 cam_periph_release(periph);
237
238 return (error);
239}
240
241/* Enable/disable LUNs, set debugging level */
242static int
243targioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
244{
245 struct targ_softc *softc;
246 cam_status status;
247
248 softc = (struct targ_softc *)dev->si_drv1;
249
250 switch (cmd) {
251 case TARGIOCENABLE:
252 {
253 struct ioc_enable_lun *new_lun;
254 struct cam_path *path;
255 struct cam_sim *sim;
256
257 new_lun = (struct ioc_enable_lun *)addr;
258 status = xpt_create_path_unlocked(&path, /*periph*/NULL,
259 new_lun->path_id,
260 new_lun->target_id,
261 new_lun->lun_id);
262 if (status != CAM_REQ_CMP) {
263 printf("Couldn't create path, status %#x\n", status);
264 break;
265 }
266 sim = xpt_path_sim(path);
267 mtx_lock(sim->mtx);
268 status = targenable(softc, path, new_lun->grp6_len,
269 new_lun->grp7_len);
270 xpt_free_path(path);
271 mtx_unlock(sim->mtx);
272 break;
273 }
274 case TARGIOCDISABLE:
275 if (softc->periph == NULL) {
276 status = CAM_DEV_NOT_THERE;
277 break;
278 }
279 cam_periph_lock(softc->periph);
280 status = targdisable(softc);
281 cam_periph_unlock(softc->periph);
282 break;
283 case TARGIOCDEBUG:
284 {
285#ifdef CAMDEBUG
286 struct ccb_debug cdbg;
287
288 /* If no periph available, disallow debugging changes */
289 if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
290 status = CAM_DEV_NOT_THERE;
291 break;
292 }
293 bzero(&cdbg, sizeof cdbg);
294 if (*((int *)addr) != 0)
295 cdbg.flags = CAM_DEBUG_PERIPH;
296 else
297 cdbg.flags = CAM_DEBUG_NONE;
298 cam_periph_lock(softc->periph);
299 xpt_setup_ccb(&cdbg.ccb_h, softc->path, /*priority*/0);
300 cdbg.ccb_h.func_code = XPT_DEBUG;
301 cdbg.ccb_h.cbfcnp = targdone;
302
303 xpt_action((union ccb *)&cdbg);
304 cam_periph_unlock(softc->periph);
305 status = cdbg.ccb_h.status & CAM_STATUS_MASK;
306#else
307 status = CAM_FUNC_NOTAVAIL;
308#endif
309 break;
310 }
311 default:
312 status = CAM_PROVIDE_FAIL;
--- 11 unchanged lines hidden (view full) ---
324 int revents;
325
326 softc = (struct targ_softc *)dev->si_drv1;
327
328 /* Poll for write() is always ok. */
329 revents = poll_events & (POLLOUT | POLLWRNORM);
330 if ((poll_events & (POLLIN | POLLRDNORM)) != 0) {
331 /* Poll for read() depends on user and abort queues. */
332 cam_periph_lock(softc->periph);
333 if (!TAILQ_EMPTY(&softc->user_ccb_queue) ||
334 !TAILQ_EMPTY(&softc->abort_queue)) {
335 revents |= poll_events & (POLLIN | POLLRDNORM);
336 }
337 cam_periph_unlock(softc->periph);
338 /* Only sleep if the user didn't poll for write. */
339 if (revents == 0)
340 selrecord(td, &softc->read_select);
341 }
342
343 return (revents);
344}
345
--- 21 unchanged lines hidden (view full) ---
367/* Notify the user's kqueue when the user queue or abort queue gets a CCB */
368static int
369targreadfilt(struct knote *kn, long hint)
370{
371 struct targ_softc *softc;
372 int retval;
373
374 softc = (struct targ_softc *)kn->kn_hook;
375 cam_periph_lock(softc->periph);
376 retval = !TAILQ_EMPTY(&softc->user_ccb_queue) ||
377 !TAILQ_EMPTY(&softc->abort_queue);
378 cam_periph_unlock(softc->periph);
379 return (retval);
380}
381
382/* Send the HBA the enable/disable message */
383static cam_status
384targendislun(struct cam_path *path, int enable, int grp6_len, int grp7_len)
385{
386 struct ccb_en_lun en_ccb;
--- 179 unchanged lines hidden (view full) ---
566 if (priority == -1) {
567 error = EINVAL;
568 break;
569 }
570 func_code = fuword32(&user_ccb->ccb_h.func_code);
571 switch (func_code) {
572 case XPT_ACCEPT_TARGET_IO:
573 case XPT_IMMED_NOTIFY:
574 cam_periph_lock(softc->periph);
575 ccb = targgetccb(softc, func_code, priority);
576 descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
577 descr->user_ccb = user_ccb;
578 descr->func_code = func_code;
579 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
580 ("Sent ATIO/INOT (%p)\n", user_ccb));
581 xpt_action(ccb);
582 TAILQ_INSERT_TAIL(&softc->pending_ccb_queue,
583 &ccb->ccb_h,
584 periph_links.tqe);
585 cam_periph_unlock(softc->periph);
586 break;
587 default:
588 cam_periph_lock(softc->periph);
589 if ((func_code & XPT_FC_QUEUED) != 0) {
590 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
591 ("Sending queued ccb %#x (%p)\n",
592 func_code, user_ccb));
593 descr = targgetdescr(softc);
594 descr->user_ccb = user_ccb;
595 descr->priority = priority;
596 descr->func_code = func_code;
--- 9 unchanged lines hidden (view full) ---
606 ccb->ccb_h.targ_descr;
607 descr->user_ccb = user_ccb;
608 descr->priority = priority;
609 descr->func_code = func_code;
610 if (targusermerge(softc, descr, ccb) != EFAULT)
611 targsendccb(softc, ccb, descr);
612 targreturnccb(softc, ccb);
613 }
614 cam_periph_unlock(softc->periph);
615 break;
616 }
617 write_len += sizeof(user_ccb);
618 }
619
620 /*
621 * If we've successfully taken in some amount of
622 * data, return success for that data first. If
--- 211 unchanged lines hidden (view full) ---
834 struct descr_queue *abort_queue;
835 struct targ_cmd_descr *user_descr;
836 struct targ_softc *softc;
837 struct ccb_queue *user_queue;
838 struct ccb_hdr *ccb_h;
839 union ccb *user_ccb;
840 int read_len, error;
841
842 error = 0;
843 read_len = 0;
844 softc = (struct targ_softc *)dev->si_drv1;
845 user_queue = &softc->user_ccb_queue;
846 abort_queue = &softc->abort_queue;
847 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"));
848
849 /* If no data is available, wait or return immediately */
850 cam_periph_lock(softc->periph);
851 ccb_h = TAILQ_FIRST(user_queue);
852 user_descr = TAILQ_FIRST(abort_queue);
853 while (ccb_h == NULL && user_descr == NULL) {
854 if ((ioflag & IO_NDELAY) == 0) {
855 error = msleep(user_queue, softc->periph->sim->mtx,
856 PRIBIO | PCATCH, "targrd", 0);
857 ccb_h = TAILQ_FIRST(user_queue);
858 user_descr = TAILQ_FIRST(abort_queue);
859 if (error != 0) {
860 if (error == ERESTART) {
861 continue;
862 } else {
863 goto read_fail;
864 }
865 }
866 } else {
867 cam_periph_unlock(softc->periph);
868 return (EAGAIN);
869 }
870 }
871
872 /* Data is available so fill the user's buffer */
873 while (ccb_h != NULL) {
874 struct targ_cmd_descr *descr;
875
876 if (uio->uio_resid < sizeof(user_ccb))
877 break;
878 TAILQ_REMOVE(user_queue, ccb_h, periph_links.tqe);
879 descr = (struct targ_cmd_descr *)ccb_h->targ_descr;
880 user_ccb = descr->user_ccb;
881 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
882 ("targread ccb %p (%p)\n", ccb_h, user_ccb));
883 error = targreturnccb(softc, (union ccb *)ccb_h);
884 if (error != 0)
885 goto read_fail;
886 cam_periph_unlock(softc->periph);
887 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
888 cam_periph_lock(softc->periph);
889 if (error != 0)
890 goto read_fail;
891 read_len += sizeof(user_ccb);
892
893 ccb_h = TAILQ_FIRST(user_queue);
894 }
895
896 /* Flush out any aborted descriptors */
897 while (user_descr != NULL) {
898 if (uio->uio_resid < sizeof(user_ccb))
899 break;
900 TAILQ_REMOVE(abort_queue, user_descr, tqe);
901 user_ccb = user_descr->user_ccb;
902 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
903 ("targread aborted descr %p (%p)\n",
904 user_descr, user_ccb));
905 suword(&user_ccb->ccb_h.status, CAM_REQ_ABORTED);
906 cam_periph_unlock(softc->periph);
907 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
908 cam_periph_lock(softc->periph);
909 if (error != 0)
910 goto read_fail;
911 read_len += sizeof(user_ccb);
912
913 user_descr = TAILQ_FIRST(abort_queue);
914 }
915
916 /*
917 * If we've successfully read some amount of data, don't report an
918 * error. If the error is persistent, it will be reported on the
919 * next read().
920 */
921 if (read_len == 0 && uio->uio_resid != 0)
922 error = ENOSPC;
923
924read_fail:
925 cam_periph_unlock(softc->periph);
926 return (error);
927}
928
929/* Copy completed ccb back to the user */
930static int
931targreturnccb(struct targ_softc *softc, union ccb *ccb)
932{
933 struct targ_cmd_descr *descr;
--- 112 unchanged lines hidden (view full) ---
1046
1047/* Cancel all pending requests and CCBs awaiting work. */
1048static void
1049abort_all_pending(struct targ_softc *softc)
1050{
1051 struct targ_cmd_descr *descr;
1052 struct ccb_abort cab;
1053 struct ccb_hdr *ccb_h;
1054 struct cam_sim *sim;
1055
1056 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("abort_all_pending\n"));
1057
1058 /* First abort the descriptors awaiting resources */
1059 while ((descr = TAILQ_FIRST(&softc->work_queue)) != NULL) {
1060 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
1061 ("Aborting descr from workq %p\n", descr));
1062 TAILQ_REMOVE(&softc->work_queue, descr, tqe);
--- 16 unchanged lines hidden (view full) ---
1079 xpt_print(cab.ccb_h.path,
1080 "Unable to abort CCB, status %#x\n",
1081 cab.ccb_h.status);
1082 }
1083 }
1084
1085 /* If we aborted at least one pending CCB ok, wait for it. */
1086 if (cab.ccb_h.status == CAM_REQ_CMP) {
1087 sim = xpt_path_sim(softc->path);
1088 msleep(&softc->pending_ccb_queue, sim->mtx,
1089 PRIBIO | PCATCH, "tgabrt", 0);
1090 }
1091
1092 /* If we aborted anything from the work queue, wakeup user. */
1093 if (!TAILQ_EMPTY(&softc->user_ccb_queue)
1094 || !TAILQ_EMPTY(&softc->abort_queue))
1095 notify_user(softc);
1096}
--- 91 unchanged lines hidden ---