From nobody Fri Dec 19 19:20:51 2025 Received: from smtp113.iad3b.emailsrvr.com (smtp113.iad3b.emailsrvr.com [146.20.161.113]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 01D2B2951B2 for ; Tue, 15 Apr 2025 11:57:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=146.20.161.113 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744718224; cv=none; b=IxyHy+k+XMPQnO2ttZQnzkf6AZAYSJgT6ccKzT6IepVHMA7zVAmXL+SUnWnbXL7yML9hgN2hDIdhydEZis7IYH9Lrapm9Rmu9XzJ6KLF01OmyhEpnPztK2fQls8hwZhaZig4Yld81hNTVSq2fDaqrJ/BWV5Gcgj+9UR8kF7w7b4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744718224; c=relaxed/simple; bh=/D1SoD2BbzdR3rFVdil+XzeMl7EfIP2+LAtsJUKDewA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OCjHhd3L8LHquI+niAGGwzCOKA8CDa8e7hfuPtbyeNX2xE+kcxqyOjTVEXCwJy1IwpafOSzb/JZ0kWp24sEmK4knDRQ37BaFvZFnAC2SphHm6ntUzz1f7QZUf/CHVQsymguQjChSFNovHdLzEnMMeuzyh4ipFTNulckDMTRJfas= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=mev.co.uk; spf=pass smtp.mailfrom=mev.co.uk; dkim=pass (1024-bit key) header.d=mev.co.uk header.i=@mev.co.uk header.b=WQnDvJfl; arc=none smtp.client-ip=146.20.161.113 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=mev.co.uk Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mev.co.uk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mev.co.uk header.i=@mev.co.uk header.b="WQnDvJfl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mev.co.uk; s=20221208-6x11dpa4; t=1744717225; bh=/D1SoD2BbzdR3rFVdil+XzeMl7EfIP2+LAtsJUKDewA=; h=From:To:Subject:Date:From; b=WQnDvJflYaNy6TH/SRnQJe/Nau1YNulSU7wxo/gh9nNt5f6hpnR/WPZtEpjy3DfZM kgDhJAg/lV4J1SOGH+nertflMfMF2GYPx4cgPZ9lByeqjVvTDLRWkUm7PEdm4i1F1e 5uJIOvAZlMPOs5o894A4VfvcTQcXTOHgd13KEJTI= X-Auth-ID: abbotti@mev.co.uk Received: by smtp15.relay.iad3b.emailsrvr.com (Authenticated sender: abbotti-AT-mev.co.uk) with ESMTPSA id D62EFC034F; Tue, 15 Apr 2025 07:40:24 -0400 (EDT) From: Ian Abbott To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , Ian Abbott , H Hartley Sweeten , Christoph Hellwig Subject: [PATCH 1/4] comedi: ni_pcidio: Do not bother filling buffer with 0xaa byte values Date: Tue, 15 Apr 2025 12:35:56 +0100 Message-ID: <20250415114008.5977-2-abbotti@mev.co.uk> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250415114008.5977-1-abbotti@mev.co.uk> References: <20250415114008.5977-1-abbotti@mev.co.uk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Classification-ID: 8a53f2c5-5989-413b-be2c-df2839710a9a-2-1 Content-Type: text/plain; charset="utf-8" On buffer change, the driver informs the mite module about the buffer change and then it fills the buffer with byte value `0xaa` using `memset()`. Do not bother filling the buffer. None of the other Comedi drivers do this. The aim is to get rid of the `prealloc_buf` member of `struct comedi_async` (which is from a `vmap()` covering the whole buffer in those Comedi drivers that do not use DMA), and use the per-buffer-page addresses from the `virt_addr` member of `struct comedi_buf_page` to access the buffer contents instead. (If necessary, we could add a `comedi_buf_memset()` function to fill the buffer with a byte value, but it's not worth it in this case.) Signed-off-by: Ian Abbott --- drivers/comedi/drivers/ni_pcidio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/comedi/drivers/ni_pcidio.c b/drivers/comedi/drivers/ni= _pcidio.c index 2d58e83420e8..2c7bb9c1ea5b 100644 --- a/drivers/comedi/drivers/ni_pcidio.c +++ b/drivers/comedi/drivers/ni_pcidio.c @@ -747,8 +747,6 @@ static int ni_pcidio_change(struct comedi_device *dev, if (ret < 0) return ret; =20 - memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz); - return 0; } =20 --=20 2.47.2 From nobody Fri Dec 19 19:20:51 2025 Received: from smtp116.iad3b.emailsrvr.com (smtp116.iad3b.emailsrvr.com [146.20.161.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 10FC51C3C14 for ; Tue, 15 Apr 2025 12:17:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=146.20.161.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744719424; cv=none; b=dcsOJQ+84cFqXobY5GK4pBb1eol5qVXCd2LTObcPLOMFMjlaxJrRoq8B/uZof9zh9mqGQzSwm8yVrm49z1P+Q1BSferyL04PKVsNQZYf7ZW3FL3pRaKpABoZ2rKeN6stKzO/eXKHhAuDxseRbfmIRWUY7a+q1XTODrlmvEhpyVM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744719424; c=relaxed/simple; bh=PDFIyW+VOmfUskU1Q17kqtKDh1pfCHaTHLfgFXLzF9Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UsycteGB5yNCHz5WVgcjr/4BMIoAWddKn+hGuEmRQ4LhgGtZJTJY4c45Yd4nchARs/LjMY2Lr7gJcKSkfDLFKTk14uIRAWSZPbPSlkRuce20Cey4fKtkAeZPP9fOHRSNYtoygVyzO5+4uIhGoBNUvH3bzQAahzuGNPLY5QnjzJ8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=mev.co.uk; spf=pass smtp.mailfrom=mev.co.uk; dkim=pass (1024-bit key) header.d=mev.co.uk header.i=@mev.co.uk header.b=mvKdXaeD; arc=none smtp.client-ip=146.20.161.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=mev.co.uk Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mev.co.uk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mev.co.uk header.i=@mev.co.uk header.b="mvKdXaeD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mev.co.uk; s=20221208-6x11dpa4; t=1744717226; bh=PDFIyW+VOmfUskU1Q17kqtKDh1pfCHaTHLfgFXLzF9Y=; h=From:To:Subject:Date:From; b=mvKdXaeDP7AnyFASPensLDncbfyVTrg8RCqd5RSBu3lSD8RkxaMeS+fLhVnQaBTzY 6AbXTcNVYOVKk17SeoJOhw5gufeqatwmcm8NsebMij1BrMeIHcx7gxTU8h+tuUCGh8 YORqBnvwmRPn7ztVAihKXSQwp476Rr1B7lppcWXc= X-Auth-ID: abbotti@mev.co.uk Received: by smtp15.relay.iad3b.emailsrvr.com (Authenticated sender: abbotti-AT-mev.co.uk) with ESMTPSA id E0A28C0355; Tue, 15 Apr 2025 07:40:25 -0400 (EDT) From: Ian Abbott To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , Ian Abbott , H Hartley Sweeten , Christoph Hellwig Subject: [PATCH 2/4] comedi: access buffer data page-by-page Date: Tue, 15 Apr 2025 12:35:57 +0100 Message-ID: <20250415114008.5977-3-abbotti@mev.co.uk> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250415114008.5977-1-abbotti@mev.co.uk> References: <20250415114008.5977-1-abbotti@mev.co.uk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Classification-ID: 8a53f2c5-5989-413b-be2c-df2839710a9a-3-1 Content-Type: text/plain; charset="utf-8" The aim is to get rid of the `prealloc_buf` member of `struct comedi_async` and access the buffer contents on a page-by-page basis using the addresses in the `virt_addr` member of `struct comedi_buf_page`. This will allow us to eliminate a `vmap()` that maps the whole buffer. Since the buffer pages have non-consecutive `virt_addr` addresses in virtual memory (except for drivers using DMA), change the loops that access buffer data to access it page-by-page. Signed-off-by: Ian Abbott --- drivers/comedi/comedi_buf.c | 67 +++++++++++++++++-------------- drivers/comedi/comedi_fops.c | 77 +++++++++++++++++++++++++++--------- 2 files changed, 96 insertions(+), 48 deletions(-) diff --git a/drivers/comedi/comedi_buf.c b/drivers/comedi/comedi_buf.c index 393966c09740..0d956dd40a2b 100644 --- a/drivers/comedi/comedi_buf.c +++ b/drivers/comedi/comedi_buf.c @@ -365,6 +365,7 @@ static unsigned int comedi_buf_munge(struct comedi_subd= evice *s, unsigned int num_bytes) { struct comedi_async *async =3D s->async; + struct comedi_buf_page *buf_page_list =3D async->buf_map->page_list; unsigned int count =3D 0; const unsigned int num_sample_bytes =3D comedi_bytes_per_sample(s); =20 @@ -376,15 +377,16 @@ static unsigned int comedi_buf_munge(struct comedi_su= bdevice *s, /* don't munge partial samples */ num_bytes -=3D num_bytes % num_sample_bytes; while (count < num_bytes) { - int block_size =3D num_bytes - count; - unsigned int buf_end; - - buf_end =3D async->prealloc_bufsz - async->munge_ptr; - if (block_size > buf_end) - block_size =3D buf_end; + /* + * Do not munge beyond page boundary. + * Note: prealloc_bufsz is a multiple of PAGE_SIZE. + */ + unsigned int page =3D async->munge_ptr >> PAGE_SHIFT; + unsigned int offset =3D offset_in_page(async->munge_ptr); + unsigned int block_size =3D + min(num_bytes - count, PAGE_SIZE - offset); =20 - s->munge(s->device, s, - async->prealloc_buf + async->munge_ptr, + s->munge(s->device, s, buf_page_list[page].virt_addr + offset, block_size, async->munge_chan); =20 /* @@ -397,7 +399,8 @@ static unsigned int comedi_buf_munge(struct comedi_subd= evice *s, async->munge_chan %=3D async->cmd.chanlist_len; async->munge_count +=3D block_size; async->munge_ptr +=3D block_size; - async->munge_ptr %=3D async->prealloc_bufsz; + if (async->munge_ptr =3D=3D async->prealloc_bufsz) + async->munge_ptr =3D 0; count +=3D block_size; } =20 @@ -558,46 +561,52 @@ static void comedi_buf_memcpy_to(struct comedi_subdev= ice *s, const void *data, unsigned int num_bytes) { struct comedi_async *async =3D s->async; + struct comedi_buf_page *buf_page_list =3D async->buf_map->page_list; unsigned int write_ptr =3D async->buf_write_ptr; =20 while (num_bytes) { - unsigned int block_size; - - if (write_ptr + num_bytes > async->prealloc_bufsz) - block_size =3D async->prealloc_bufsz - write_ptr; - else - block_size =3D num_bytes; + /* + * Do not copy beyond page boundary. + * Note: prealloc_bufsz is a multiple of PAGE_SIZE. + */ + unsigned int page =3D write_ptr >> PAGE_SHIFT; + unsigned int offset =3D offset_in_page(write_ptr); + unsigned int block_size =3D min(num_bytes, PAGE_SIZE - offset); =20 - memcpy(async->prealloc_buf + write_ptr, data, block_size); + memcpy(buf_page_list[page].virt_addr + offset, + data, block_size); =20 data +=3D block_size; num_bytes -=3D block_size; - - write_ptr =3D 0; + write_ptr +=3D block_size; + if (write_ptr =3D=3D async->prealloc_bufsz) + write_ptr =3D 0; } } =20 static void comedi_buf_memcpy_from(struct comedi_subdevice *s, void *dest, unsigned int nbytes) { - void *src; struct comedi_async *async =3D s->async; + struct comedi_buf_page *buf_page_list =3D async->buf_map->page_list; unsigned int read_ptr =3D async->buf_read_ptr; =20 while (nbytes) { - unsigned int block_size; - - src =3D async->prealloc_buf + read_ptr; - - if (nbytes >=3D async->prealloc_bufsz - read_ptr) - block_size =3D async->prealloc_bufsz - read_ptr; - else - block_size =3D nbytes; + /* + * Do not copy beyond page boundary. + * Note: prealloc_bufsz is a multiple of PAGE_SIZE. + */ + unsigned int page =3D read_ptr >> PAGE_SHIFT; + unsigned int offset =3D offset_in_page(read_ptr); + unsigned int block_size =3D min(nbytes, PAGE_SIZE - offset); =20 - memcpy(dest, src, block_size); + memcpy(dest, buf_page_list[page].virt_addr + offset, + block_size); nbytes -=3D block_size; dest +=3D block_size; - read_ptr =3D 0; + read_ptr +=3D block_size; + if (read_ptr =3D=3D async->prealloc_bufsz) + read_ptr =3D 0; } } =20 diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c index b9df9b19d4bd..37cfef36c1ad 100644 --- a/drivers/comedi/comedi_fops.c +++ b/drivers/comedi/comedi_fops.c @@ -2475,6 +2475,62 @@ static __poll_t comedi_poll(struct file *file, poll_= table *wait) return mask; } =20 +static unsigned int comedi_buf_copy_to_user(struct comedi_subdevice *s, + void __user *dest, unsigned int src_offset, unsigned int n) +{ + struct comedi_buf_map *bm =3D s->async->buf_map; + struct comedi_buf_page *buf_page_list =3D bm->page_list; + unsigned int page =3D src_offset >> PAGE_SHIFT; + unsigned int offset =3D offset_in_page(src_offset); + + while (n) { + unsigned int copy_amount =3D min(n, PAGE_SIZE - offset); + unsigned int uncopied; + + uncopied =3D copy_to_user(dest, buf_page_list[page].virt_addr + + offset, copy_amount); + copy_amount -=3D uncopied; + n -=3D copy_amount; + if (uncopied) + break; + + dest +=3D copy_amount; + page++; + if (page =3D=3D bm->n_pages) + page =3D 0; /* buffer wraparound */ + offset =3D 0; + } + return n; +} + +static unsigned int comedi_buf_copy_from_user(struct comedi_subdevice *s, + unsigned int dst_offset, const void __user *src, unsigned int n) +{ + struct comedi_buf_map *bm =3D s->async->buf_map; + struct comedi_buf_page *buf_page_list =3D bm->page_list; + unsigned int page =3D dst_offset >> PAGE_SHIFT; + unsigned int offset =3D offset_in_page(dst_offset); + + while (n) { + unsigned int copy_amount =3D min(n, PAGE_SIZE - offset); + unsigned int uncopied; + + uncopied =3D copy_from_user(buf_page_list[page].virt_addr + + offset, src, copy_amount); + copy_amount -=3D uncopied; + n -=3D copy_amount; + if (uncopied) + break; + + src +=3D copy_amount; + page++; + if (page =3D=3D bm->n_pages) + page =3D 0; /* buffer wraparound */ + offset =3D 0; + } + return n; +} + static ssize_t comedi_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *offset) { @@ -2516,7 +2572,6 @@ static ssize_t comedi_write(struct file *file, const = char __user *buf, add_wait_queue(&async->wait_head, &wait); while (count =3D=3D 0 && !retval) { unsigned int runflags; - unsigned int wp, n1, n2; =20 set_current_state(TASK_INTERRUPTIBLE); =20 @@ -2555,14 +2610,7 @@ static ssize_t comedi_write(struct file *file, const= char __user *buf, } =20 set_current_state(TASK_RUNNING); - wp =3D async->buf_write_ptr; - n1 =3D min(n, async->prealloc_bufsz - wp); - n2 =3D n - n1; - m =3D copy_from_user(async->prealloc_buf + wp, buf, n1); - if (m) - m +=3D n2; - else if (n2) - m =3D copy_from_user(async->prealloc_buf, buf + n1, n2); + m =3D comedi_buf_copy_from_user(s, async->buf_write_ptr, buf, n); if (m) { n -=3D m; retval =3D -EFAULT; @@ -2651,8 +2699,6 @@ static ssize_t comedi_read(struct file *file, char __= user *buf, size_t nbytes, =20 add_wait_queue(&async->wait_head, &wait); while (count =3D=3D 0 && !retval) { - unsigned int rp, n1, n2; - set_current_state(TASK_INTERRUPTIBLE); =20 m =3D comedi_buf_read_n_available(s); @@ -2689,14 +2735,7 @@ static ssize_t comedi_read(struct file *file, char _= _user *buf, size_t nbytes, } =20 set_current_state(TASK_RUNNING); - rp =3D async->buf_read_ptr; - n1 =3D min(n, async->prealloc_bufsz - rp); - n2 =3D n - n1; - m =3D copy_to_user(buf, async->prealloc_buf + rp, n1); - if (m) - m +=3D n2; - else if (n2) - m =3D copy_to_user(buf + n1, async->prealloc_buf, n2); + m =3D comedi_buf_copy_to_user(s, buf, async->buf_read_ptr, n); if (m) { n -=3D m; retval =3D -EFAULT; --=20 2.47.2 From nobody Fri Dec 19 19:20:51 2025 Received: from smtp117.iad3b.emailsrvr.com (smtp117.iad3b.emailsrvr.com [146.20.161.117]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9CD771DE2D6 for ; Tue, 15 Apr 2025 11:47:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=146.20.161.117 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744717632; cv=none; b=d/qj+xuwggVOc21YURSJxZ3MVNe7dE9qU2tKkaBjAjAXVXY2GZV0riRB0M8rNsIfwvvWGHn78zLSfuoajnfSp6VOr1+I18MBq4xOhhT+Q+XizG1xzmWJHBBcFzA0ZySQNpPZIE8VXadsWB40uewpLc9n6cMnH5G8qqnM0ov2RKQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744717632; c=relaxed/simple; bh=F5RCZgD7o87oQZUpFxCLl9/2kHwyCIEn26RkRT2gcpU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ug2Hs6YIe00teD9ejN6n76h3WNBU7q4TvCYbqgwjLn6DlX6yNcDsOffRPa2yAcI3P9SfGg/wjWlwpSjiyQ2JV2epQJFSH6n11DqnKD4CBf37WqMEMdtlxWTlI8Q/IgAFKW4xzdFGWxftKwgIybHsqFoGfZD8KYU84uWtiRPiFpE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=mev.co.uk; spf=pass smtp.mailfrom=mev.co.uk; dkim=pass (1024-bit key) header.d=mev.co.uk header.i=@mev.co.uk header.b=EvE5I9QM; arc=none smtp.client-ip=146.20.161.117 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=mev.co.uk Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mev.co.uk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mev.co.uk header.i=@mev.co.uk header.b="EvE5I9QM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mev.co.uk; s=20221208-6x11dpa4; t=1744717227; bh=F5RCZgD7o87oQZUpFxCLl9/2kHwyCIEn26RkRT2gcpU=; h=From:To:Subject:Date:From; b=EvE5I9QMZJnxGhZE5GJhiKxLpzmdgwhVsyyhrxhRbw4L7Ky9RlhDswd54/KsJdich kTXfYpexUSbqGh4gwe/DChFW99n55JnVhaD6/Czcm5IRFQiQM43WKLnnlYCsbeTQqY yAUSTw5/HNzrI5wqghUosFtDWx3MQsHFchHgVvkU= X-Auth-ID: abbotti@mev.co.uk Received: by smtp15.relay.iad3b.emailsrvr.com (Authenticated sender: abbotti-AT-mev.co.uk) with ESMTPSA id DB58BC0356; Tue, 15 Apr 2025 07:40:26 -0400 (EDT) From: Ian Abbott To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , Ian Abbott , H Hartley Sweeten , Christoph Hellwig Subject: [PATCH 3/4] comedi: remove the mapping of the Comedi buffer in vmalloc address space Date: Tue, 15 Apr 2025 12:35:58 +0100 Message-ID: <20250415114008.5977-4-abbotti@mev.co.uk> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250415114008.5977-1-abbotti@mev.co.uk> References: <20250415114008.5977-1-abbotti@mev.co.uk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Classification-ID: 8a53f2c5-5989-413b-be2c-df2839710a9a-4-1 Content-Type: text/plain; charset="utf-8" Now that all the code that accesses the Comedi buffer data does so page-by-page, using the `virt_addr` member of `struct comedi_buf_page` to point to the data of each page, do not linearly map the buffer into vmalloc address space (pointed to by the `prealloc_buf` member of `struct comedi_async`). That was only done for convenience, but was not done for those drivers that need a DMA coherent buffer, which is allocated in a single chunk. Remove the `prealloc_buf` member as it is no longer used. Signed-off-by: Ian Abbott --- drivers/comedi/comedi_buf.c | 45 +++----------------------------- include/linux/comedi/comedidev.h | 10 ++----- 2 files changed, 6 insertions(+), 49 deletions(-) diff --git a/drivers/comedi/comedi_buf.c b/drivers/comedi/comedi_buf.c index 0d956dd40a2b..5807007bb3dd 100644 --- a/drivers/comedi/comedi_buf.c +++ b/drivers/comedi/comedi_buf.c @@ -56,13 +56,7 @@ static void __comedi_buf_free(struct comedi_device *dev, struct comedi_buf_map *bm; unsigned long flags; =20 - if (async->prealloc_buf) { - if (s->async_dma_dir =3D=3D DMA_NONE) - vunmap(async->prealloc_buf); - async->prealloc_buf =3D NULL; - async->prealloc_bufsz =3D 0; - } - + async->prealloc_bufsz =3D 0; spin_lock_irqsave(&s->spin_lock, flags); bm =3D async->buf_map; async->buf_map =3D NULL; @@ -141,11 +135,8 @@ static void __comedi_buf_alloc(struct comedi_device *d= ev, unsigned int n_pages) { struct comedi_async *async =3D s->async; - struct page **pages =3D NULL; struct comedi_buf_map *bm; - struct comedi_buf_page *buf; unsigned long flags; - unsigned int i; =20 if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir !=3D DMA_NONE) { dev_err(dev->class_dev, @@ -160,30 +151,7 @@ static void __comedi_buf_alloc(struct comedi_device *d= ev, spin_lock_irqsave(&s->spin_lock, flags); async->buf_map =3D bm; spin_unlock_irqrestore(&s->spin_lock, flags); - - if (bm->dma_dir !=3D DMA_NONE) { - /* - * DMA buffer was allocated as a single block. - * Address is in page_list[0]. - */ - buf =3D &bm->page_list[0]; - async->prealloc_buf =3D buf->virt_addr; - } else { - pages =3D vmalloc(sizeof(struct page *) * n_pages); - if (!pages) - return; - - for (i =3D 0; i < n_pages; i++) { - buf =3D &bm->page_list[i]; - pages[i] =3D virt_to_page(buf->virt_addr); - } - - /* vmap the pages to prealloc_buf */ - async->prealloc_buf =3D vmap(pages, n_pages, VM_MAP, - COMEDI_PAGE_PROTECTION); - - vfree(pages); - } + async->prealloc_bufsz =3D n_pages << PAGE_SHIFT; } =20 void comedi_buf_map_get(struct comedi_buf_map *bm) @@ -264,7 +232,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct = comedi_subdevice *s, new_size =3D (new_size + PAGE_SIZE - 1) & PAGE_MASK; =20 /* if no change is required, do nothing */ - if (async->prealloc_buf && async->prealloc_bufsz =3D=3D new_size) + if (async->prealloc_bufsz =3D=3D new_size) return 0; =20 /* deallocate old buffer */ @@ -275,14 +243,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct= comedi_subdevice *s, unsigned int n_pages =3D new_size >> PAGE_SHIFT; =20 __comedi_buf_alloc(dev, s, n_pages); - - if (!async->prealloc_buf) { - /* allocation failed */ - __comedi_buf_free(dev, s); + if (!async->prealloc_bufsz) return -ENOMEM; - } } - async->prealloc_bufsz =3D new_size; =20 return 0; } diff --git a/include/linux/comedi/comedidev.h b/include/linux/comedi/comedi= dev.h index c08416a7364b..4cb0400ad616 100644 --- a/include/linux/comedi/comedidev.h +++ b/include/linux/comedi/comedidev.h @@ -234,16 +234,12 @@ struct comedi_buf_page { * * A COMEDI data buffer is allocated as individual pages, either in * conventional memory or DMA coherent memory, depending on the attached, - * low-level hardware device. (The buffer pages also get mapped into the - * kernel's contiguous virtual address space pointed to by the 'prealloc_b= uf' - * member of &struct comedi_async.) + * low-level hardware device. * * The buffer is normally freed when the COMEDI device is detached from the * low-level driver (which may happen due to device removal), but if it ha= ppens * to be mmapped at the time, the pages cannot be freed until the buffer h= as - * been munmapped. That is what the reference counter is for. (The virtu= al - * address space pointed by 'prealloc_buf' is freed when the COMEDI device= is - * detached.) + * been munmapped. That is what the reference counter is for. */ struct comedi_buf_map { struct device *dma_hw_dev; @@ -255,7 +251,6 @@ struct comedi_buf_map { =20 /** * struct comedi_async - Control data for asynchronous COMEDI commands - * @prealloc_buf: Kernel virtual address of allocated acquisition buffer. * @prealloc_bufsz: Buffer size (in bytes). * @buf_map: Map of buffer pages. * @max_bufsize: Maximum allowed buffer size (in bytes). @@ -344,7 +339,6 @@ struct comedi_buf_map { * less than or equal to UINT_MAX). */ struct comedi_async { - void *prealloc_buf; unsigned int prealloc_bufsz; struct comedi_buf_map *buf_map; unsigned int max_bufsize; --=20 2.47.2 From nobody Fri Dec 19 19:20:51 2025 Received: from smtp117.iad3b.emailsrvr.com (smtp117.iad3b.emailsrvr.com [146.20.161.117]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9CDC91EBFF0 for ; Tue, 15 Apr 2025 11:47:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=146.20.161.117 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744717631; cv=none; b=preHevnHcec7M5zBM8FMvoD3kFWM8UTMaqL2Xf42GXGOp7vBiQennQajaNO8n9RVNqoEiXbQ8iuSOWlug2f2fZhRgWnvuyO0aSKEwhO+udVP8s+YgFG9Be2zspoa9BhL5K0n7Zo1FV+UupDLhrcGWyXJslAllt5GTl2AgGWNZG8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744717631; c=relaxed/simple; bh=3XiA9Jo1cTtKj6ZYQ9r0yPn+Uqy5Q+V6czZhQJzNfR4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=coub3C9LUKnXrMFKIi4lYR1FiB+Su7eaJVglCzEzFyPA0OtX6NOQINxLSsU6GBJEA6v/kOJCWnU6rD7Ilu8a0yTmrwLePBzDrRRB55jBHSNuZv1aMNNxof+C9sEqaMV1MVGRT8OFIX6jZdSSFDsEA4poau58XZu2VfBe2/1I+GU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=mev.co.uk; spf=pass smtp.mailfrom=mev.co.uk; dkim=pass (1024-bit key) header.d=mev.co.uk header.i=@mev.co.uk header.b=sLZClKJq; arc=none smtp.client-ip=146.20.161.117 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=mev.co.uk Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mev.co.uk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=mev.co.uk header.i=@mev.co.uk header.b="sLZClKJq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mev.co.uk; s=20221208-6x11dpa4; t=1744717228; bh=3XiA9Jo1cTtKj6ZYQ9r0yPn+Uqy5Q+V6czZhQJzNfR4=; h=From:To:Subject:Date:From; b=sLZClKJq62fu4SXZx1J3XZxvCIgdXFVHjgUNyQU78p7t5x3dxx6rxjUaMNypuoKXc 2e2VOn6XBO1gpN6MOH2oPYOB1lT24hjGjre8IRDBuXGwwIGMuUPdZ7Xv1qMc3sJVGV VgiBRBOZEe+xGl7whf+pNYimndGNchhttPUNsbvQ= X-Auth-ID: abbotti@mev.co.uk Received: by smtp15.relay.iad3b.emailsrvr.com (Authenticated sender: abbotti-AT-mev.co.uk) with ESMTPSA id D79BAC0358; Tue, 15 Apr 2025 07:40:27 -0400 (EDT) From: Ian Abbott To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , Ian Abbott , H Hartley Sweeten , Christoph Hellwig Subject: [PATCH 4/4] comedi: allocate DMA coherent buffer as individual pages Date: Tue, 15 Apr 2025 12:35:59 +0100 Message-ID: <20250415114008.5977-5-abbotti@mev.co.uk> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250415114008.5977-1-abbotti@mev.co.uk> References: <20250415114008.5977-1-abbotti@mev.co.uk> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Classification-ID: 8a53f2c5-5989-413b-be2c-df2839710a9a-5-1 Content-Type: text/plain; charset="utf-8" Depending on the driver, the acquisition buffer is allocated either from normal memory, or from DMA coherent memory. For normal memory, the buffer is allocated as individual pages, but for DMA coherent memory, it is allocated as a single block. Prior to commit e36472145aa7 ("staging: comedi: use dma_mmap_coherent for DMA-able buffer mmap"), the buffer was allocated as individual pages for DMA coherent memory too, but that was changed to allocate it as a single block to allow `dma_mmap_coherent()` to be used to mmap it, because that requires the pages being mmap'ed to be contiguous. This patch allocates the buffer from DMA coherent memory a page at a time again, and works around the limitation of `dma_mmap_coherent()` by calling it in a loop for each page, with temporarily modified `vm_start` and `vm_end` values in the VMA. (The `vm_pgoff` value is 0.) Cc: Christoph Hellwig Signed-off-by: Ian Abbott --- drivers/comedi/comedi_buf.c | 43 ++++++++++++------------------------ drivers/comedi/comedi_fops.c | 43 +++++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/drivers/comedi/comedi_buf.c b/drivers/comedi/comedi_buf.c index 5807007bb3dd..002c0e76baff 100644 --- a/drivers/comedi/comedi_buf.c +++ b/drivers/comedi/comedi_buf.c @@ -27,14 +27,12 @@ static void comedi_buf_map_kref_release(struct kref *kr= ef) =20 if (bm->page_list) { if (bm->dma_dir !=3D DMA_NONE) { - /* - * DMA buffer was allocated as a single block. - * Address is in page_list[0]. - */ - buf =3D &bm->page_list[0]; - dma_free_coherent(bm->dma_hw_dev, - PAGE_SIZE * bm->n_pages, - buf->virt_addr, buf->dma_addr); + for (i =3D 0; i < bm->n_pages; i++) { + buf =3D &bm->page_list[i]; + dma_free_coherent(bm->dma_hw_dev, PAGE_SIZE, + buf->virt_addr, + buf->dma_addr); + } } else { for (i =3D 0; i < bm->n_pages; i++) { buf =3D &bm->page_list[i]; @@ -88,26 +86,14 @@ comedi_buf_map_alloc(struct comedi_device *dev, enum dm= a_data_direction dma_dir, goto err; =20 if (bm->dma_dir !=3D DMA_NONE) { - void *virt_addr; - dma_addr_t dma_addr; - - /* - * Currently, the DMA buffer needs to be allocated as a - * single block so that it can be mmap()'ed. - */ - virt_addr =3D dma_alloc_coherent(bm->dma_hw_dev, - PAGE_SIZE * n_pages, &dma_addr, - GFP_KERNEL); - if (!virt_addr) - goto err; - for (i =3D 0; i < n_pages; i++) { buf =3D &bm->page_list[i]; - buf->virt_addr =3D virt_addr + (i << PAGE_SHIFT); - buf->dma_addr =3D dma_addr + (i << PAGE_SHIFT); + buf->virt_addr =3D + dma_alloc_coherent(bm->dma_hw_dev, PAGE_SIZE, + &buf->dma_addr, GFP_KERNEL); + if (!buf->virt_addr) + break; } - - bm->n_pages =3D i; } else { for (i =3D 0; i < n_pages; i++) { buf =3D &bm->page_list[i]; @@ -117,11 +103,10 @@ comedi_buf_map_alloc(struct comedi_device *dev, enum = dma_data_direction dma_dir, =20 SetPageReserved(virt_to_page(buf->virt_addr)); } - - bm->n_pages =3D i; - if (i < n_pages) - goto err; } + bm->n_pages =3D i; + if (i < n_pages) + goto err; =20 return bm; =20 diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c index 37cfef36c1ad..3383a7ce27ff 100644 --- a/drivers/comedi/comedi_fops.c +++ b/drivers/comedi/comedi_fops.c @@ -2387,13 +2387,27 @@ static int comedi_mmap(struct file *file, struct vm= _area_struct *vma) goto done; } if (bm->dma_dir !=3D DMA_NONE) { + unsigned long vm_start =3D vma->vm_start; + unsigned long vm_end =3D vma->vm_end; + /* - * DMA buffer was allocated as a single block. - * Address is in page_list[0]. + * Buffer pages are not contiguous, so temporarily modify VMA + * start and end addresses for each buffer page. */ - buf =3D &bm->page_list[0]; - retval =3D dma_mmap_coherent(bm->dma_hw_dev, vma, buf->virt_addr, - buf->dma_addr, n_pages * PAGE_SIZE); + for (i =3D 0; i < n_pages; ++i) { + buf =3D &bm->page_list[i]; + vma->vm_start =3D start; + vma->vm_end =3D start + PAGE_SIZE; + retval =3D dma_mmap_coherent(bm->dma_hw_dev, vma, + buf->virt_addr, + buf->dma_addr, PAGE_SIZE); + if (retval) + break; + + start +=3D PAGE_SIZE; + } + vma->vm_start =3D vm_start; + vma->vm_end =3D vm_end; } else { for (i =3D 0; i < n_pages; ++i) { unsigned long pfn; @@ -2407,19 +2421,18 @@ static int comedi_mmap(struct file *file, struct vm= _area_struct *vma) =20 start +=3D PAGE_SIZE; } + } =20 #ifdef CONFIG_MMU - /* - * Leaving behind a partial mapping of a buffer we're about to - * drop is unsafe, see remap_pfn_range_notrack(). - * We need to zap the range here ourselves instead of relying - * on the automatic zapping in remap_pfn_range() because we call - * remap_pfn_range() in a loop. - */ - if (retval) - zap_vma_ptes(vma, vma->vm_start, size); + /* + * Leaving behind a partial mapping of a buffer we're about to drop is + * unsafe, see remap_pfn_range_notrack(). We need to zap the range + * here ourselves instead of relying on the automatic zapping in + * remap_pfn_range() because we call remap_pfn_range() in a loop. + */ + if (retval) + zap_vma_ptes(vma, vma->vm_start, size); #endif - } =20 if (retval =3D=3D 0) { vma->vm_ops =3D &comedi_vm_ops; --=20 2.47.2