From owner-svn-src-head@freebsd.org Sun Feb 26 06:25:57 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 12149CEE149; Sun, 26 Feb 2017 06:25:57 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id E0AACE9C; Sun, 26 Feb 2017 06:25:56 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v1Q6PuEn055402; Sun, 26 Feb 2017 06:25:56 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v1Q6Puf2055401; Sun, 26 Feb 2017 06:25:56 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201702260625.v1Q6Puf2055401@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Sun, 26 Feb 2017 06:25:56 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r314290 - head/sys/dev/usb/storage X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 26 Feb 2017 06:25:57 -0000 Author: mav Date: Sun Feb 26 06:25:55 2017 New Revision: 314290 URL: https://svnweb.freebsd.org/changeset/base/314290 Log: Implement use of multiple transfers per I/O. This change removes limitation of single S/G list entry and limitation on maximal I/O size, using multiple data transfers per I/O if needed. Also it removes code duplication between send and receive paths, which are now completely equal. Modified: head/sys/dev/usb/storage/cfumass.c Modified: head/sys/dev/usb/storage/cfumass.c ============================================================================== --- head/sys/dev/usb/storage/cfumass.c Sun Feb 26 06:05:29 2017 (r314289) +++ head/sys/dev/usb/storage/cfumass.c Sun Feb 26 06:25:55 2017 (r314290) @@ -200,8 +200,7 @@ static device_resume_t cfumass_resume; static usb_handle_request_t cfumass_handle_request; static usb_callback_t cfumass_t_command_callback; -static usb_callback_t cfumass_t_data_out_callback; -static usb_callback_t cfumass_t_data_in_callback; +static usb_callback_t cfumass_t_data_callback; static usb_callback_t cfumass_t_status_callback; static device_method_t cfumass_methods[] = { @@ -250,7 +249,7 @@ static struct usb_config cfumass_config[ .bufsize = CFUMASS_BULK_SIZE, .flags = {.proxy_buffer = 1, .short_xfer_ok = 1, .ext_buffer = 1}, - .callback = &cfumass_t_data_out_callback, + .callback = &cfumass_t_data_callback, .usb_mode = USB_MODE_DEVICE, }, @@ -261,7 +260,7 @@ static struct usb_config cfumass_config[ .bufsize = CFUMASS_BULK_SIZE, .flags = {.proxy_buffer = 1, .short_xfer_ok = 1, .ext_buffer = 1}, - .callback = &cfumass_t_data_in_callback, + .callback = &cfumass_t_data_callback, .usb_mode = USB_MODE_DEVICE, }, @@ -712,124 +711,66 @@ tr_setup: } static void -cfumass_t_data_out_callback(struct usb_xfer *xfer, usb_error_t usb_error) +cfumass_t_data_callback(struct usb_xfer *xfer, usb_error_t usb_error) { - struct cfumass_softc *sc; - union ctl_io *io; - struct ctl_sg_entry ctl_sg_entry, *ctl_sglist; - int actlen, ctl_sg_count; - - sc = usbd_xfer_softc(xfer); - io = sc->sc_ctl_io; - - if (io->scsiio.kern_sg_entries > 0) { - ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; - ctl_sg_count = io->scsiio.kern_sg_entries; - } else { - ctl_sglist = &ctl_sg_entry; - ctl_sglist->addr = io->scsiio.kern_data_ptr; - ctl_sglist->len = io->scsiio.kern_data_len; - ctl_sg_count = 1; - } + struct cfumass_softc *sc = usbd_xfer_softc(xfer); + union ctl_io *io = sc->sc_ctl_io; + uint32_t max_bulk; + struct ctl_sg_entry sg_entry, *sglist; + int actlen, sumlen, sg_count; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: CFUMASS_DEBUG(sc, "USB_ST_TRANSFERRED"); - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - if (actlen != ctl_sglist[0].len) { - KASSERT(actlen <= ctl_sglist[0].len, - ("actlen %d > ctl_sglist.len %zd", - actlen, ctl_sglist[0].len)); - CFUMASS_DEBUG(sc, "host transferred %d bytes" - "instead of expected %zd bytes", - actlen, ctl_sglist[0].len); - } + usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); sc->sc_current_residue -= actlen; + io->scsiio.ext_data_filled += actlen; io->scsiio.kern_data_resid -= actlen; - io->scsiio.be_move_done(io); - sc->sc_ctl_io = NULL; - break; - - case USB_ST_SETUP: -tr_setup: - CFUMASS_DEBUG(sc, "USB_ST_SETUP"); - - CFUMASS_DEBUG(sc, "requested size %d, CTL segment size %zd", - sc->sc_current_transfer_length, ctl_sglist[0].len); - - usbd_xfer_set_frame_data(xfer, 0, ctl_sglist[0].addr, ctl_sglist[0].len); - usbd_transfer_submit(xfer); - break; - - default: - if (usb_error == USB_ERR_CANCELLED) { - CFUMASS_DEBUG(sc, "USB_ERR_CANCELLED"); + if (actlen < sumlen || + sc->sc_current_residue == 0 || + io->scsiio.kern_data_resid == 0) { + sc->sc_ctl_io = NULL; + io->scsiio.be_move_done(io); break; } - - CFUMASS_DEBUG(sc, "USB_ST_ERROR: %s", - usbd_errstr(usb_error)); - - goto tr_setup; - } -} - -static void -cfumass_t_data_in_callback(struct usb_xfer *xfer, usb_error_t usb_error) -{ - struct cfumass_softc *sc; - union ctl_io *io; - uint32_t max_bulk; - struct ctl_sg_entry ctl_sg_entry, *ctl_sglist; - int actlen, ctl_sg_count; - - sc = usbd_xfer_softc(xfer); - io = sc->sc_ctl_io; - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - CFUMASS_DEBUG(sc, "USB_ST_TRANSFERRED"); - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - sc->sc_current_residue -= actlen; - io->scsiio.kern_data_resid -= actlen; - io->scsiio.be_move_done(io); - sc->sc_ctl_io = NULL; - break; + /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: CFUMASS_DEBUG(sc, "USB_ST_SETUP"); if (io->scsiio.kern_sg_entries > 0) { - ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; - ctl_sg_count = io->scsiio.kern_sg_entries; + sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; + sg_count = io->scsiio.kern_sg_entries; } else { - ctl_sglist = &ctl_sg_entry; - ctl_sglist->addr = io->scsiio.kern_data_ptr; - ctl_sglist->len = io->scsiio.kern_data_len; - ctl_sg_count = 1; + sglist = &sg_entry; + sglist->addr = io->scsiio.kern_data_ptr; + sglist->len = io->scsiio.kern_data_len; + sg_count = 1; } - if (sc->sc_current_transfer_length > io->scsiio.kern_total_len) { - CFUMASS_DEBUG(sc, "initiator requested %d bytes, " - "we will send %ju and stall", - sc->sc_current_transfer_length, - (uintmax_t)io->scsiio.kern_total_len); + sumlen = io->scsiio.ext_data_filled - + io->scsiio.kern_rel_offset; + while (sumlen >= sglist->len && sg_count > 0) { + sumlen -= sglist->len; + sglist++; + sg_count--; } + KASSERT(sg_count > 0, ("Run out of S/G list entries")); max_bulk = usbd_xfer_max_len(xfer); - CFUMASS_DEBUG(sc, "max_bulk %d, requested size %d, " - "CTL segment size %zd", max_bulk, - sc->sc_current_transfer_length, ctl_sglist[0].len); - - if (max_bulk >= ctl_sglist[0].len) - max_bulk = ctl_sglist[0].len; + actlen = min(sglist->len - sumlen, max_bulk); + actlen = min(actlen, sc->sc_current_transfer_length - + io->scsiio.ext_data_filled); + CFUMASS_DEBUG(sc, "requested %d, done %d, max_bulk %d, " + "segment %zd => transfer %d", + sc->sc_current_transfer_length, io->scsiio.ext_data_filled, + max_bulk, sglist->len - sumlen, actlen); - usbd_xfer_set_frame_data(xfer, 0, ctl_sglist[0].addr, max_bulk); + usbd_xfer_set_frame_data(xfer, 0, + (uint8_t *)sglist->addr + sumlen, actlen); usbd_transfer_submit(xfer); - break; default: @@ -837,9 +778,7 @@ tr_setup: CFUMASS_DEBUG(sc, "USB_ERR_CANCELLED"); break; } - CFUMASS_DEBUG(sc, "USB_ST_ERROR: %s", usbd_errstr(usb_error)); - goto tr_setup; } }