From patchwork Tue Jan 11 06:55:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dafna Hirschfeld X-Patchwork-Id: 12709542 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8D384C433EF for ; Tue, 11 Jan 2022 06:56:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348344AbiAKG4L (ORCPT ); Tue, 11 Jan 2022 01:56:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37536 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348346AbiAKG4I (ORCPT ); Tue, 11 Jan 2022 01:56:08 -0500 Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B92DEC061748 for ; Mon, 10 Jan 2022 22:56:07 -0800 (PST) Received: from localhost.localdomain (unknown [IPv6:2a00:c281:14a3:8100:8072:ec19:b639:c4ab]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: dafna) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id 9B4921F4409C; Tue, 11 Jan 2022 06:56:05 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1641884166; bh=j5OnR8ANVCgZqZsxw/wpEaZSyNAbRPFo6sD9S11Mreo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EBjsURxh3O4eMp+LHzEC4IgNJvfHN7F5wTBm2BVA09gNQZMwiEYmoR1GJ3InQYSAq zfaVv0xgHWFlHUMsPSCw16RC9YV2r89kKE7YhoZURNP+n6QFhb1n4UqQn93SnhkJZX hgHDyVLDr6QuQ4mxV39CnUoLt9jxcc0hAlxYV/XGGMdSyM1KuZOxxFrU4Z8C3L1+HW vkyjmtpE+UtICdPhirzAdvsW1LiX0+ODTVFf8y5R0t5OjTpgV8/BUD/A9FG23x+SV5 wBkj0z72mV2k0CCPwF7DKmlufXQd4GUQ2BJgoGK5lBQ8RHnTGl6hdflX7ij5FT5hrA 5dGykz1FXeQSw== From: Dafna Hirschfeld To: ezequiel@vanguardiasur.com.ar Cc: linux-media@vger.kernel.org, laurent.pinchart@ideasonboard.com, hverkuil@xs4all.nl, ribalda@chromium.org, tfiga@chromium.org, senozhatsky@google.com, hch@lst.de, Dafna Hirschfeld , kernel@collabora.com Subject: [PATCH 1/3] media: stk1160: fix number of buffers in case not all buffers are created Date: Tue, 11 Jan 2022 08:55:03 +0200 Message-Id: <20220111065505.6323-2-dafna.hirschfeld@collabora.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220111065505.6323-1-dafna.hirschfeld@collabora.com> References: <20220111065505.6323-1-dafna.hirschfeld@collabora.com> Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org In case we fail to allocate a transfer_buffer then we break the buffers creation loop and update the number of buffers to the number of successfully allocated which should be 'i' and not 'i - 1' Signed-off-by: Dafna Hirschfeld Reviewed-by: Ezequiel Garcia --- drivers/media/usb/stk1160/stk1160-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index 202b084f65a2..91bd6adccdd1 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -511,9 +511,9 @@ int stk1160_alloc_isoc(struct stk1160 *dev) usb_free_urb(dev->isoc_ctl.urb[i]); dev->isoc_ctl.urb[i] = NULL; - stk1160_warn("%d urbs allocated. Trying to continue...\n", i - 1); + stk1160_warn("%d urbs allocated. Trying to continue...\n", i); - dev->isoc_ctl.num_bufs = i - 1; + dev->isoc_ctl.num_bufs = i; return 0; From patchwork Tue Jan 11 06:55:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dafna Hirschfeld X-Patchwork-Id: 12709544 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0799AC433F5 for ; Tue, 11 Jan 2022 06:56:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348349AbiAKG4M (ORCPT ); Tue, 11 Jan 2022 01:56:12 -0500 Received: from bhuna.collabora.co.uk ([46.235.227.227]:45392 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348348AbiAKG4K (ORCPT ); Tue, 11 Jan 2022 01:56:10 -0500 Received: from localhost.localdomain (unknown [IPv6:2a00:c281:14a3:8100:8072:ec19:b639:c4ab]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: dafna) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id CF2B61F4409B; Tue, 11 Jan 2022 06:56:06 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1641884167; bh=8oowA17GymZEoHGk/YGso5OcG6BlTUZOleF572Qbu7U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LcIXyR8wpZofzlhrVgLTteyz2kpa57Xw9nqqCgJYzSGshx4es0y8hE+/vk/tMgQM8 eipVAxJ/kGyj2JkiA1YLLLf4Q1+O0XCRLs60ClQwP01p04gdLK7uDBmQGyyjkVyWPK s7DzdYRoZ+2rWIHrnWrDkYgKTtx6D+DX41QvEjP5bX91YLq4s12bs4VWmYRL9PbSPM 3TlNq/K4QuQb/qVE6c5mIT/6qpy2o8oUu0se6A2CO8ZZ6iIK2fqRC4ssA4QrU9yu7j zvje52rtRzaoK7xRqo3kT0mu53aCElMCNgS/5wubu1K0Qqdk5Uyok921UjtPqU1gPa ZSbqWG6+vpQ3Q== From: Dafna Hirschfeld To: ezequiel@vanguardiasur.com.ar Cc: linux-media@vger.kernel.org, laurent.pinchart@ideasonboard.com, hverkuil@xs4all.nl, ribalda@chromium.org, tfiga@chromium.org, senozhatsky@google.com, hch@lst.de, Dafna Hirschfeld , kernel@collabora.com Subject: [PATCH 2/3] media: stk1160: move transfer_buffer and urb to same struct 'stk1160_urb' Date: Tue, 11 Jan 2022 08:55:04 +0200 Message-Id: <20220111065505.6323-3-dafna.hirschfeld@collabora.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220111065505.6323-1-dafna.hirschfeld@collabora.com> References: <20220111065505.6323-1-dafna.hirschfeld@collabora.com> Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Instead of having two separated arrays, one for the urbs and one for their buffers, have one array of a struct containing both. In addition, the array is just 16 pointers, no need to dynamically allocate it. Signed-off-by: Dafna Hirschfeld --- drivers/media/usb/stk1160/stk1160-v4l.c | 2 +- drivers/media/usb/stk1160/stk1160-video.c | 50 ++++++++--------------- drivers/media/usb/stk1160/stk1160.h | 11 ++--- 3 files changed, 23 insertions(+), 40 deletions(-) diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index 6a4eb616d516..a06030451db4 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -232,7 +232,7 @@ static int stk1160_start_streaming(struct stk1160 *dev) /* submit urbs and enables IRQ */ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_KERNEL); + rc = usb_submit_urb(dev->isoc_ctl.stk1160_urb[i].urb, GFP_KERNEL); if (rc) { stk1160_err("cannot submit urb[%d] (%d)\n", i, rc); goto out_uninit; diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index 91bd6adccdd1..4194d31b53bb 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -347,7 +347,7 @@ void stk1160_cancel_isoc(struct stk1160 *dev) * We don't care for NULL pointer since * usb_kill_urb allows it. */ - usb_kill_urb(dev->isoc_ctl.urb[i]); + usb_kill_urb(dev->isoc_ctl.stk1160_urb[i].urb); } stk1160_dbg("all urbs killed\n"); @@ -366,30 +366,25 @@ void stk1160_free_isoc(struct stk1160 *dev) for (i = 0; i < num_bufs; i++) { - urb = dev->isoc_ctl.urb[i]; + urb = dev->isoc_ctl.stk1160_urb[i].urb; if (urb) { - if (dev->isoc_ctl.transfer_buffer[i]) { + if (dev->isoc_ctl.stk1160_urb[i].transfer_buffer) { #ifndef CONFIG_DMA_NONCOHERENT usb_free_coherent(dev->udev, urb->transfer_buffer_length, - dev->isoc_ctl.transfer_buffer[i], + dev->isoc_ctl.stk1160_urb[i].transfer_buffer, urb->transfer_dma); #else - kfree(dev->isoc_ctl.transfer_buffer[i]); + kfree(dev->isoc_ctl.stk1160_urb[i].transfer_buffer); #endif } usb_free_urb(urb); - dev->isoc_ctl.urb[i] = NULL; + dev->isoc_ctl.stk1160_urb[i].urb = NULL; } - dev->isoc_ctl.transfer_buffer[i] = NULL; + dev->isoc_ctl.stk1160_urb[i].transfer_buffer = NULL; } - kfree(dev->isoc_ctl.urb); - kfree(dev->isoc_ctl.transfer_buffer); - - dev->isoc_ctl.urb = NULL; - dev->isoc_ctl.transfer_buffer = NULL; dev->isoc_ctl.num_bufs = 0; stk1160_dbg("all urb buffers freed\n"); @@ -429,19 +424,6 @@ int stk1160_alloc_isoc(struct stk1160 *dev) dev->isoc_ctl.buf = NULL; dev->isoc_ctl.max_pkt_size = dev->max_pkt_size; - dev->isoc_ctl.urb = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); - if (!dev->isoc_ctl.urb) { - stk1160_err("out of memory for urb array\n"); - return -ENOMEM; - } - - dev->isoc_ctl.transfer_buffer = kcalloc(num_bufs, sizeof(void *), - GFP_KERNEL); - if (!dev->isoc_ctl.transfer_buffer) { - stk1160_err("out of memory for usb transfers\n"); - kfree(dev->isoc_ctl.urb); - return -ENOMEM; - } /* allocate urbs and transfer buffers */ for (i = 0; i < num_bufs; i++) { @@ -449,15 +431,15 @@ int stk1160_alloc_isoc(struct stk1160 *dev) urb = usb_alloc_urb(max_packets, GFP_KERNEL); if (!urb) goto free_i_bufs; - dev->isoc_ctl.urb[i] = urb; + dev->isoc_ctl.stk1160_urb[i].urb = urb; #ifndef CONFIG_DMA_NONCOHERENT - dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, - sb_size, GFP_KERNEL, &urb->transfer_dma); + dev->isoc_ctl.stk1160_urb[i].transfer_buffer = + usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL, &urb->transfer_dma); #else - dev->isoc_ctl.transfer_buffer[i] = kmalloc(sb_size, GFP_KERNEL); + dev->isoc_ctl.stk1160_urb[i].transfer_buffer = kmalloc(sb_size, GFP_KERNEL); #endif - if (!dev->isoc_ctl.transfer_buffer[i]) { + if (!dev->isoc_ctl.stk1160_urb[i].transfer_buffer) { stk1160_err("cannot alloc %d bytes for tx[%d] buffer\n", sb_size, i); @@ -466,14 +448,14 @@ int stk1160_alloc_isoc(struct stk1160 *dev) goto free_i_bufs; goto nomore_tx_bufs; } - memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); + memset(dev->isoc_ctl.stk1160_urb[i].transfer_buffer, 0, sb_size); /* * FIXME: Where can I get the endpoint? */ urb->dev = dev->udev; urb->pipe = usb_rcvisocpipe(dev->udev, STK1160_EP_VIDEO); - urb->transfer_buffer = dev->isoc_ctl.transfer_buffer[i]; + urb->transfer_buffer = dev->isoc_ctl.stk1160_urb[i].transfer_buffer; urb->transfer_buffer_length = sb_size; urb->complete = stk1160_isoc_irq; urb->context = dev; @@ -508,8 +490,8 @@ int stk1160_alloc_isoc(struct stk1160 *dev) * enough to work fine, so we just free the extra urb, * store the allocated count and keep going, fingers crossed! */ - usb_free_urb(dev->isoc_ctl.urb[i]); - dev->isoc_ctl.urb[i] = NULL; + usb_free_urb(dev->isoc_ctl.stk1160_urb[i].urb); + dev->isoc_ctl.stk1160_urb[i].urb = NULL; stk1160_warn("%d urbs allocated. Trying to continue...\n", i); diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h index a31ea1c80f25..1ffca1343d88 100644 --- a/drivers/media/usb/stk1160/stk1160.h +++ b/drivers/media/usb/stk1160/stk1160.h @@ -84,6 +84,11 @@ struct stk1160_buffer { unsigned int pos; /* current pos inside buffer */ }; +struct stk1160_urb { + struct urb *urb; + char *transfer_buffer; +}; + struct stk1160_isoc_ctl { /* max packet size of isoc transaction */ int max_pkt_size; @@ -91,11 +96,7 @@ struct stk1160_isoc_ctl { /* number of allocated urbs */ int num_bufs; - /* urb for isoc transfers */ - struct urb **urb; - - /* transfer buffers for isoc transfer */ - char **transfer_buffer; + struct stk1160_urb stk1160_urb[STK1160_NUM_BUFS]; /* current buffer */ struct stk1160_buffer *buf; From patchwork Tue Jan 11 06:55:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dafna Hirschfeld X-Patchwork-Id: 12709543 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 72046C433FE for ; Tue, 11 Jan 2022 06:56:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348346AbiAKG4L (ORCPT ); Tue, 11 Jan 2022 01:56:11 -0500 Received: from bhuna.collabora.co.uk ([46.235.227.227]:45396 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348350AbiAKG4K (ORCPT ); Tue, 11 Jan 2022 01:56:10 -0500 Received: from localhost.localdomain (unknown [IPv6:2a00:c281:14a3:8100:8072:ec19:b639:c4ab]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: dafna) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id 1E44B1F440A3; Tue, 11 Jan 2022 06:56:07 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1641884169; bh=jHqPcllJUl78adEDHwmwCcFl58cLfyU+YE5J3CQy4G4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QThwvQp6anD2sMAHC1k/dKsbPkQZ9ppkMJHwp5YYBXXu+4BBF49m6NOqxu5H5jWnl tTlA6XMC0gEo4pAf3kxMe4Xzg4A4VGtpXwBYyBMsoOnwzRXNT9gEDRZxQXYyKvIsGn X6Ozlu48NIhYxEOxaN8wnvcStSppvTwIn/JhowPVRYwUmFHtd96VJkUAjLnlZXJ+EP j2QTEfaV/ylYPvguWlB2FOxjlNufnjuW6HVoa8jgdig68vk+zv2s8MOk7mfwePkaAu Fqe/9v5fiLtotfP2+iKihq9bOB/A+0qneHdgIk3uSM7kf9Qm6thExbvw+TsIfQChHU 95aEvuxbBTcMw== From: Dafna Hirschfeld To: ezequiel@vanguardiasur.com.ar Cc: linux-media@vger.kernel.org, laurent.pinchart@ideasonboard.com, hverkuil@xs4all.nl, ribalda@chromium.org, tfiga@chromium.org, senozhatsky@google.com, hch@lst.de, Dafna Hirschfeld , kernel@collabora.com Subject: [PATCH 3/3] media: stk1160: use dma_alloc_noncontiguous API Date: Tue, 11 Jan 2022 08:55:05 +0200 Message-Id: <20220111065505.6323-4-dafna.hirschfeld@collabora.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220111065505.6323-1-dafna.hirschfeld@collabora.com> References: <20220111065505.6323-1-dafna.hirschfeld@collabora.com> Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Replace the urb buffers allocation to use the noncontiguous API. This improve performance on Arm. The noncontiguous API require handling synchronization. This commit is similar to the one sent to uvc: [1] [1] https://lkml.org/lkml/2021/3/12/1506 Signed-off-by: Dafna Hirschfeld --- drivers/media/usb/stk1160/stk1160-v4l.c | 3 + drivers/media/usb/stk1160/stk1160-video.c | 109 +++++++++++++--------- drivers/media/usb/stk1160/stk1160.h | 10 ++ 3 files changed, 79 insertions(+), 43 deletions(-) diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index a06030451db4..31c34734425b 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -232,6 +232,9 @@ static int stk1160_start_streaming(struct stk1160 *dev) /* submit urbs and enables IRQ */ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + struct stk1160_urb *stk_urb = &dev->isoc_ctl.stk1160_urb[i]; + + dma_sync_sgtable_for_device(stk1160_get_dmadev(dev), stk_urb->sgt, DMA_FROM_DEVICE); rc = usb_submit_urb(dev->isoc_ctl.stk1160_urb[i].urb, GFP_KERNEL); if (rc) { stk1160_err("cannot submit urb[%d] (%d)\n", i, rc); diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index 4194d31b53bb..fdc0de2af4c0 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -295,7 +295,8 @@ static void stk1160_process_isoc(struct stk1160 *dev, struct urb *urb) static void stk1160_isoc_irq(struct urb *urb) { int i, rc; - struct stk1160 *dev = urb->context; + struct stk1160_urb *stk_urb = urb->context; + struct stk1160 *dev = stk_urb->dev; switch (urb->status) { case 0: @@ -310,6 +311,9 @@ static void stk1160_isoc_irq(struct urb *urb) return; } + dma_sync_sgtable_for_cpu(stk1160_get_dmadev(dev), stk_urb->sgt, DMA_FROM_DEVICE); + invalidate_kernel_vmap_range(stk_urb->transfer_buffer, urb->transfer_buffer_length); + stk1160_process_isoc(dev, urb); /* Reset urb buffers */ @@ -318,6 +322,7 @@ static void stk1160_isoc_irq(struct urb *urb) urb->iso_frame_desc[i].actual_length = 0; } + dma_sync_sgtable_for_device(stk1160_get_dmadev(dev), stk_urb->sgt, DMA_FROM_DEVICE); rc = usb_submit_urb(urb, GFP_ATOMIC); if (rc) stk1160_err("urb re-submit failed (%d)\n", rc); @@ -353,37 +358,34 @@ void stk1160_cancel_isoc(struct stk1160 *dev) stk1160_dbg("all urbs killed\n"); } +static void stk_free_urb_buffer(struct stk1160 *dev, struct stk1160_urb *stk_urb) +{ + struct device *dma_dev = stk1160_get_dmadev(dev); + + dma_vunmap_noncontiguous(dma_dev, stk_urb->transfer_buffer); + dma_free_noncontiguous(dma_dev, stk_urb->urb->transfer_buffer_length, stk_urb->sgt, + DMA_FROM_DEVICE); + usb_free_urb(stk_urb->urb); + + stk_urb->transfer_buffer = NULL; + stk_urb->sgt = NULL; + stk_urb->urb = NULL; + stk_urb->dev = NULL; + stk_urb->dma = 0; +} + /* * Releases urb and transfer buffers * Obviusly, associated urb must be killed before releasing it. */ void stk1160_free_isoc(struct stk1160 *dev) { - struct urb *urb; int i, num_bufs = dev->isoc_ctl.num_bufs; stk1160_dbg("freeing %d urb buffers...\n", num_bufs); - for (i = 0; i < num_bufs; i++) { - - urb = dev->isoc_ctl.stk1160_urb[i].urb; - if (urb) { - - if (dev->isoc_ctl.stk1160_urb[i].transfer_buffer) { -#ifndef CONFIG_DMA_NONCOHERENT - usb_free_coherent(dev->udev, - urb->transfer_buffer_length, - dev->isoc_ctl.stk1160_urb[i].transfer_buffer, - urb->transfer_dma); -#else - kfree(dev->isoc_ctl.stk1160_urb[i].transfer_buffer); -#endif - } - usb_free_urb(urb); - dev->isoc_ctl.stk1160_urb[i].urb = NULL; - } - dev->isoc_ctl.stk1160_urb[i].transfer_buffer = NULL; - } + for (i = 0; i < num_bufs; i++) + stk_free_urb_buffer(dev, &dev->isoc_ctl.stk1160_urb[i]); dev->isoc_ctl.num_bufs = 0; @@ -400,6 +402,39 @@ void stk1160_uninit_isoc(struct stk1160 *dev) stk1160_free_isoc(dev); } +static int stk1160_fill_urb(struct stk1160 *dev, struct stk1160_urb *stk_urb, int sb_size, + int max_packets) +{ + struct device *dma_dev = stk1160_get_dmadev(dev); + + stk_urb->urb = usb_alloc_urb(max_packets, GFP_KERNEL); + if (!stk_urb->urb) + return -ENOMEM; + stk_urb->sgt = dma_alloc_noncontiguous(dma_dev, sb_size, DMA_FROM_DEVICE, GFP_KERNEL, 0); + + /* + * If the buffer allocation failed, we exit but return 0 since we allow driver + * working with less buffers + */ + if (!stk_urb->sgt) + goto free_urb; + + stk_urb->transfer_buffer = dma_vmap_noncontiguous(dma_dev, sb_size, stk_urb->sgt); + if (!stk_urb->transfer_buffer) + goto free_sgt; + + stk_urb->dma = stk_urb->sgt->sgl->dma_address; + stk_urb->dev = dev; + return 0; +free_sgt: + dma_free_noncontiguous(dma_dev, sb_size, stk_urb->sgt, DMA_FROM_DEVICE); + stk_urb->sgt = NULL; +free_urb: + usb_free_urb(stk_urb->urb); + stk_urb->urb = NULL; + + return 0; +} /* * Allocate URBs */ @@ -407,6 +442,7 @@ int stk1160_alloc_isoc(struct stk1160 *dev) { struct urb *urb; int i, j, k, sb_size, max_packets, num_bufs; + int ret; /* * It may be necessary to release isoc here, @@ -428,21 +464,13 @@ int stk1160_alloc_isoc(struct stk1160 *dev) /* allocate urbs and transfer buffers */ for (i = 0; i < num_bufs; i++) { - urb = usb_alloc_urb(max_packets, GFP_KERNEL); - if (!urb) + ret = stk1160_fill_urb(dev, &dev->isoc_ctl.stk1160_urb[i], sb_size, max_packets); + if (ret) goto free_i_bufs; - dev->isoc_ctl.stk1160_urb[i].urb = urb; - -#ifndef CONFIG_DMA_NONCOHERENT - dev->isoc_ctl.stk1160_urb[i].transfer_buffer = - usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL, &urb->transfer_dma); -#else - dev->isoc_ctl.stk1160_urb[i].transfer_buffer = kmalloc(sb_size, GFP_KERNEL); -#endif - if (!dev->isoc_ctl.stk1160_urb[i].transfer_buffer) { - stk1160_err("cannot alloc %d bytes for tx[%d] buffer\n", - sb_size, i); + urb = dev->isoc_ctl.stk1160_urb[i].urb; + + if (!urb) { /* Not enough transfer buffers, so just give up */ if (i < STK1160_MIN_BUFS) goto free_i_bufs; @@ -458,15 +486,12 @@ int stk1160_alloc_isoc(struct stk1160 *dev) urb->transfer_buffer = dev->isoc_ctl.stk1160_urb[i].transfer_buffer; urb->transfer_buffer_length = sb_size; urb->complete = stk1160_isoc_irq; - urb->context = dev; + urb->context = &dev->isoc_ctl.stk1160_urb[i]; urb->interval = 1; urb->start_frame = 0; urb->number_of_packets = max_packets; -#ifndef CONFIG_DMA_NONCOHERENT urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; -#else - urb->transfer_flags = URB_ISO_ASAP; -#endif + urb->transfer_dma = dev->isoc_ctl.stk1160_urb[i].dma; k = 0; for (j = 0; j < max_packets; j++) { @@ -490,8 +515,6 @@ int stk1160_alloc_isoc(struct stk1160 *dev) * enough to work fine, so we just free the extra urb, * store the allocated count and keep going, fingers crossed! */ - usb_free_urb(dev->isoc_ctl.stk1160_urb[i].urb); - dev->isoc_ctl.stk1160_urb[i].urb = NULL; stk1160_warn("%d urbs allocated. Trying to continue...\n", i); @@ -501,7 +524,7 @@ int stk1160_alloc_isoc(struct stk1160 *dev) free_i_bufs: /* Save the allocated buffers so far, so we can properly free them */ - dev->isoc_ctl.num_bufs = i+1; + dev->isoc_ctl.num_bufs = i; stk1160_free_isoc(dev); return -ENOMEM; } diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h index 1ffca1343d88..52bea7815ae5 100644 --- a/drivers/media/usb/stk1160/stk1160.h +++ b/drivers/media/usb/stk1160/stk1160.h @@ -16,6 +16,8 @@ #include #include #include +#include +#include #define STK1160_VERSION "0.9.5" #define STK1160_VERSION_NUM 0x000905 @@ -87,6 +89,9 @@ struct stk1160_buffer { struct stk1160_urb { struct urb *urb; char *transfer_buffer; + struct sg_table *sgt; + struct stk1160 *dev; + dma_addr_t dma; }; struct stk1160_isoc_ctl { @@ -190,3 +195,8 @@ void stk1160_select_input(struct stk1160 *dev); /* Provided by stk1160-ac97.c */ void stk1160_ac97_setup(struct stk1160 *dev); + +static inline struct device *stk1160_get_dmadev(struct stk1160 *dev) +{ + return bus_to_hcd(dev->udev->bus)->self.sysdev; +}