From owner-freebsd-current@FreeBSD.ORG Thu Feb 27 05:26:34 2014 Return-Path: Delivered-To: freebsd-current@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 85821A7F for ; Thu, 27 Feb 2014 05:26:34 +0000 (UTC) Received: from smtp.mei.co.jp (smtp.mei.co.jp [133.183.100.20]) by mx1.freebsd.org (Postfix) with ESMTP id 390101790 for ; Thu, 27 Feb 2014 05:26:33 +0000 (UTC) Received: from mail-gw.jp.panasonic.com ([157.8.1.157]) by smtp.mei.co.jp (8.12.11.20060614/3.7W/kc-maile11) with ESMTP id s1R5QW0i010714 for ; Thu, 27 Feb 2014 14:26:32 +0900 (JST) Received: from epochmail.jp.panasonic.com ([157.8.1.130]) by mail.jp.panasonic.com (8.11.6p2/3.7W/kc-maili15) with ESMTP id s1R5QWB05102 for ; Thu, 27 Feb 2014 14:26:32 +0900 Received: by epochmail.jp.panasonic.com (8.12.11.20060308/3.7W/lomi11) id s1R5QWKk004198; Thu, 27 Feb 2014 14:26:32 +0900 Received: from localhost by lomi11.jp.panasonic.com (8.12.11.20060308/3.7W) with ESMTP id s1R5QVRm004154; Thu, 27 Feb 2014 14:26:31 +0900 Date: Thu, 27 Feb 2014 14:26:15 +0900 (JST) Message-Id: <20140227.142615.924807465819500067.okuno.kohji@jp.panasonic.com> To: freebsd-current@FreeBSD.org Subject: kqueue for usb_dev From: Kohji Okuno Organization: Panasonic Corporation X-Mailer: Mew version 6.5 on Emacs 24.3 / Mule 6.0 (HANACHIRUSATO) Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="--Next_Part(Thu_Feb_27_14_26_15_2014_503)--" Content-Transfer-Encoding: 7bit Cc: okuno.kohji@jp.panasonic.com X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Feb 2014 05:26:34 -0000 ----Next_Part(Thu_Feb_27_14_26_15_2014_503)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Hi, I tried add kqueue I/F to usb_dev.c. I attached my patch. What do you think about my patch? Best regards, Kohji Okuno ----Next_Part(Thu_Feb_27_14_26_15_2014_503)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="usb_dev_kqueue.patch" diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c index f086a3c..4334be7 100644 --- a/sys/dev/usb/usb_dev.c +++ b/sys/dev/usb/usb_dev.c @@ -120,6 +120,9 @@ static d_ioctl_t usb_ioctl; static d_read_t usb_read; static d_write_t usb_write; static d_poll_t usb_poll; +#if 1 +static d_kqfilter_t usb_kqfilter; +#endif static d_ioctl_t usb_static_ioctl; @@ -138,6 +141,10 @@ struct cdevsw usb_devsw = { .d_read = usb_read, .d_write = usb_write, .d_poll = usb_poll +#if 1 + , + .d_kqfilter = usb_kqfilter +#endif }; static struct cdev* usb_dev = NULL; @@ -505,6 +512,9 @@ usb_fifo_create(struct usb_cdev_privdata *cpd, f->fifo_index = n + USB_FIFO_TX; f->dev_ep_index = e; f->priv_mtx = &udev->device_mtx; +#if 1 + knlist_init_mtx(&f->selinfo.si_note, f->priv_mtx); +#endif f->priv_sc0 = ep; f->methods = &usb_ugen_methods; f->iface_index = ep->iface_index; @@ -532,6 +542,9 @@ usb_fifo_create(struct usb_cdev_privdata *cpd, f->fifo_index = n + USB_FIFO_RX; f->dev_ep_index = e; f->priv_mtx = &udev->device_mtx; +#if 1 + knlist_init_mtx(&f->selinfo.si_note, f->priv_mtx); +#endif f->priv_sc0 = ep; f->methods = &usb_ugen_methods; f->iface_index = ep->iface_index; @@ -712,6 +725,11 @@ usb_fifo_open(struct usb_cdev_privdata *cpd, /* reset select flag */ f->flag_isselect = 0; +#if 1 + /* reset kevent flag */ + f->flag_iskevent = 0; +#endif + /* reset flushing flag */ f->flag_flushing = 0; @@ -772,6 +790,13 @@ usb_fifo_close(struct usb_fifo *f, int fflags) /* clear current cdev private data pointer */ f->curr_cpd = NULL; +#if 1 + /* check if we are watched by kevent */ + if (f->flag_iskevent) { + KNOTE_LOCKED(&f->selinfo.si_note, 0); + f->flag_iskevent = 0; + } +#endif /* check if we are selected */ if (f->flag_isselect) { selwakeup(&f->selinfo); @@ -1113,6 +1138,179 @@ done: return (err); } +#if 1 +static void +usb_filter_detach(struct knote *kn) +{ + struct usb_fifo *f = kn->kn_hook; + knlist_remove(&f->selinfo.si_note, kn, 0); +} + +static int +usb_filter_write(struct knote *kn, long hint) +{ + struct usb_cdev_privdata* cpd; + struct usb_fifo *f; + struct usb_mbuf *m; + int is_usbfs = 0; + + f = kn->kn_hook; + cpd = f->curr_cpd; + if (cpd == NULL) { + return (1); + } + + if (f->fs_ep_max != 0) { + is_usbfs = 1; + } + + if (!is_usbfs) { + if (f->flag_iserror) { + /* we got an error */ + m = (void *)1; + } else { + if (f->queue_data == NULL) { + /* + * start write transfer, if not + * already started + */ + (f->methods->f_start_write) (f); + } + /* check if any packets are available */ + USB_IF_POLL(&f->free_q, m); + } + } else { + if (f->flag_iscomplete) { + m = (void *)1; + } else { + m = NULL; + } + } + + if (m) { + return (1); + } else { + return (0); + } +} + +static int +usb_filter_read(struct knote *kn, long hint) +{ + struct usb_cdev_privdata* cpd; + struct usb_fifo *f; + struct usb_mbuf *m; + int is_usbfs = 0; + + f = kn->kn_hook; + cpd = f->curr_cpd; + if (cpd == NULL) { + return (1); + } + + if (f->fs_ep_max != 0) { + is_usbfs = 1; + } + + if (!is_usbfs) { + if (f->flag_iserror) { + /* we have and error */ + m = (void *)1; + } else { + if (f->queue_data == NULL) { + /* + * start read transfer, if not + * already started + */ + (f->methods->f_start_read) (f); + } + /* check if any packets are available */ + USB_IF_POLL(&f->used_q, m); + } + } else { + if (f->flag_iscomplete) { + m = (void *)1; + } else { + m = NULL; + } + } + + if (m) { + return (1); + } else { + if (!is_usbfs) { + /* start reading data */ + (f->methods->f_start_read) (f); + } + return (0); + } +} + +static struct filterops usb_filtops_write = +{ + .f_isfd = 1, + .f_detach = usb_filter_detach, + .f_event = usb_filter_write, +}; + +static struct filterops usb_filtops_read = +{ + .f_isfd = 1, + .f_detach = usb_filter_detach, + .f_event = usb_filter_read, +}; + + +/* ARGSUSED */ +static int +usb_kqfilter(struct cdev* dev, struct knote *kn) +{ + struct usb_cdev_refdata refs; + struct usb_cdev_privdata* cpd; + struct usb_fifo *f; + int fflags; + int err = EINVAL; + + if (devfs_get_cdevpriv((void **)&cpd) != 0 || + usb_ref_device(cpd, &refs, 0) != 0) + return (ENXIO); + + fflags = cpd->fflags; + + /* Figure out who needs service */ + switch (kn->kn_filter) { + case EVFILT_WRITE: + if (fflags & FWRITE) { + f = refs.txfifo; + kn->kn_fop = &usb_filtops_write; + err = 0; + } + break; + case EVFILT_READ: + if (fflags & FREAD) { + f = refs.rxfifo; + kn->kn_fop = &usb_filtops_read; + err = 0; + } + break; + default: + err = EOPNOTSUPP; + break; + } + + if (err == 0) { + kn->kn_hook = f; + mtx_lock(f->priv_mtx); + knlist_add(&f->selinfo.si_note, kn, 1); + f->flag_iskevent = 1; + mtx_unlock(f->priv_mtx); + } + + usb_unref_device(cpd, &refs); + return (err); +} +#endif + /* ARGSUSED */ static int usb_poll(struct cdev* dev, int events, struct thread* td) @@ -1577,6 +1775,12 @@ usb_fifo_wakeup(struct usb_fifo *f) { usb_fifo_signal(f); +#if 1 + if (f->flag_iskevent) { + KNOTE_LOCKED(&f->selinfo.si_note, 0); + /* f->flag_iskevent = 0 */ + } +#endif if (f->flag_isselect) { selwakeup(&f->selinfo); f->flag_isselect = 0; @@ -1705,6 +1909,9 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc, f_tx->fifo_index = n + USB_FIFO_TX; f_tx->dev_ep_index = -1; f_tx->priv_mtx = priv_mtx; +#if 1 + knlist_init_mtx(&f_tx->selinfo.si_note, f_rx->priv_mtx); +#endif f_tx->priv_sc0 = priv_sc; f_tx->methods = pm; f_tx->iface_index = iface_index; @@ -1713,6 +1920,9 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc, f_rx->fifo_index = n + USB_FIFO_RX; f_rx->dev_ep_index = -1; f_rx->priv_mtx = priv_mtx; +#if 1 + knlist_init_mtx(&f_rx->selinfo.si_note, f_rx->priv_mtx); +#endif f_rx->priv_sc0 = priv_sc; f_rx->methods = pm; f_rx->iface_index = iface_index; diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h index 9a7cf21..334c5f9 100644 --- a/sys/dev/usb/usb_dev.h +++ b/sys/dev/usb/usb_dev.h @@ -127,6 +127,9 @@ struct usb_fifo { uint8_t flag_iscomplete; /* set if a USB transfer is complete */ uint8_t flag_iserror; /* set if FIFO error happened */ uint8_t flag_isselect; /* set if FIFO is selected */ +#if 1 + uint8_t flag_iskevent; /* set if FIFO is watched by kevent */ +#endif uint8_t flag_flushing; /* set if FIFO is flushing data */ uint8_t flag_short; /* set if short_ok or force_short * transfer flags should be set */ ----Next_Part(Thu_Feb_27_14_26_15_2014_503)----