linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1] usb: storage: sddr09: move write buffers into info struct
@ 2025-08-31 19:22 Alex Tran
  2025-09-01  5:37 ` Greg KH
  2025-09-01  8:10 ` Oliver Neukum
  0 siblings, 2 replies; 3+ messages in thread
From: Alex Tran @ 2025-08-31 19:22 UTC (permalink / raw)
  To: stern; +Cc: gregkh, linux-usb, usb-storage, linux-kernel, Alex Tran

Changelog:
- Moved allocation of buffers ('blockbuffer', 'buffer') in 
  'sddr09_write_data' into info struct and freeing into 
  'sddr09_card_info_destructor' so that the operations are only 
  performed once.
- 'buffer' length is now size of a full block instead of being 
  dependent on sectors.

Signed-off-by: Alex Tran <alex.t.tran@gmail.com>
---
 drivers/usb/storage/sddr09.c | 100 ++++++++++++++++++-----------------
 1 file changed, 51 insertions(+), 49 deletions(-)

diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index e66b920e9..27c318266 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -255,6 +255,8 @@ struct sddr09_card_info {
 	int		*pba_to_lba;	/* physical to logical map */
 	int		lbact;		/* number of available pages */
 	int		flags;
+	unsigned char	*buffer; /* staging buffer */
+	unsigned char	*blockbuffer; /* bounce buffer */
 #define	SDDR09_WP	1		/* write protected */
 };
 
@@ -847,11 +849,9 @@ sddr09_find_unused_pba(struct sddr09_card_info *info, unsigned int lba) {
 	return 0;
 }
 
-static int
-sddr09_write_lba(struct us_data *us, unsigned int lba,
-		 unsigned int page, unsigned int pages,
-		 unsigned char *ptr, unsigned char *blockbuffer) {
-
+static int sddr09_write_lba(struct us_data *us, unsigned int lba,
+			    unsigned int page, unsigned int pages)
+{
 	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
 	unsigned long address;
 	unsigned int pba, lbap;
@@ -890,13 +890,13 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
 	/* read old contents */
 	address = (pba << (info->pageshift + info->blockshift));
 	result = sddr09_read22(us, address>>1, info->blocksize,
-			       info->pageshift, blockbuffer, 0);
+			       info->pageshift, info->blockbuffer, 0);
 	if (result)
 		return result;
 
 	/* check old contents and fill lba */
 	for (i = 0; i < info->blocksize; i++) {
-		bptr = blockbuffer + i*pagelen;
+		bptr = info->blockbuffer + i * pagelen;
 		cptr = bptr + info->pagesize;
 		nand_compute_ecc(bptr, ecc);
 		if (!nand_compare_ecc(cptr+13, ecc)) {
@@ -915,9 +915,9 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
 	}
 
 	/* copy in new stuff and compute ECC */
-	xptr = ptr;
+	xptr = info->buffer;
 	for (i = page; i < page+pages; i++) {
-		bptr = blockbuffer + i*pagelen;
+		bptr = info->blockbuffer + i * pagelen;
 		cptr = bptr + info->pagesize;
 		memcpy(bptr, xptr, info->pagesize);
 		xptr += info->pagesize;
@@ -930,7 +930,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
 	usb_stor_dbg(us, "Rewrite PBA %d (LBA %d)\n", pba, lba);
 
 	result = sddr09_write_inplace(us, address>>1, info->blocksize,
-				      info->pageshift, blockbuffer, 0);
+				      info->pageshift, info->blockbuffer, 0);
 
 	usb_stor_dbg(us, "sddr09_write_inplace returns %d\n", result);
 
@@ -961,9 +961,6 @@ sddr09_write_data(struct us_data *us,
 
 	struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
 	unsigned int lba, maxlba, page, pages;
-	unsigned int pagelen, blocklen;
-	unsigned char *blockbuffer;
-	unsigned char *buffer;
 	unsigned int len, offset;
 	struct scatterlist *sg;
 	int result;
@@ -975,35 +972,6 @@ sddr09_write_data(struct us_data *us,
 	if (lba >= maxlba)
 		return -EIO;
 
-	/*
-	 * blockbuffer is used for reading in the old data, overwriting
-	 * with the new data, and performing ECC calculations
-	 */
-
-	/*
-	 * TODO: instead of doing kmalloc/kfree for each write,
-	 * add a bufferpointer to the info structure
-	 */
-
-	pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT);
-	blocklen = (pagelen << info->blockshift);
-	blockbuffer = kmalloc(blocklen, GFP_NOIO);
-	if (!blockbuffer)
-		return -ENOMEM;
-
-	/*
-	 * Since we don't write the user data directly to the device,
-	 * we have to create a bounce buffer and move the data a piece
-	 * at a time between the bounce buffer and the actual transfer buffer.
-	 */
-
-	len = min_t(unsigned int, sectors, info->blocksize) * info->pagesize;
-	buffer = kmalloc(len, GFP_NOIO);
-	if (!buffer) {
-		kfree(blockbuffer);
-		return -ENOMEM;
-	}
-
 	result = 0;
 	offset = 0;
 	sg = NULL;
@@ -1024,11 +992,10 @@ sddr09_write_data(struct us_data *us,
 		}
 
 		/* Get the data from the transfer buffer */
-		usb_stor_access_xfer_buf(buffer, len, us->srb,
-				&sg, &offset, FROM_XFER_BUF);
+		usb_stor_access_xfer_buf(info->buffer, len, us->srb, &sg,
+					 &offset, FROM_XFER_BUF);
 
-		result = sddr09_write_lba(us, lba, page, pages,
-				buffer, blockbuffer);
+		result = sddr09_write_lba(us, lba, page, pages);
 		if (result)
 			break;
 
@@ -1037,9 +1004,6 @@ sddr09_write_data(struct us_data *us,
 		sectors -= pages;
 	}
 
-	kfree(buffer);
-	kfree(blockbuffer);
-
 	return result;
 }
 
@@ -1193,6 +1157,36 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) {
 	return cardinfo;
 }
 
+static int sddr09_init_card_buffers(struct us_data *us)
+{
+	struct sddr09_card_info *info = (struct sddr09_card_info *)us->extra;
+	unsigned int pagelen, blocklen, len;
+
+	/*
+	 * blockbuffer is used for reading in the old data, overwriting
+	 * with the new data, and performing ECC calculations
+	 */
+	pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT);
+	blocklen = (pagelen << info->blockshift);
+	info->blockbuffer = kmalloc(blocklen, GFP_NOIO);
+	if (!info->blockbuffer)
+		return -ENOMEM;
+
+	/*
+	 * Since we don't write the user data directly to the device,
+	 * we have to create a bounce buffer and move the data a piece
+	 * at a time between the bounce buffer and the actual transfer buffer.
+	 */
+	len = info->blocksize * info->pagesize;
+	info->buffer = kmalloc(len, GFP_NOIO);
+	if (!info->buffer) {
+		kfree(info->blockbuffer);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
 static int
 sddr09_read_map(struct us_data *us) {
 
@@ -1403,6 +1397,8 @@ sddr09_card_info_destructor(void *extra) {
 	if (!info)
 		return;
 
+	kfree(info->buffer);
+	kfree(info->blockbuffer);
 	kfree(info->lba_to_pba);
 	kfree(info->pba_to_lba);
 }
@@ -1592,6 +1588,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
 		if (!cardinfo) {
 			/* probably no media */
 		init_error:
+			kfree(info->buffer);
+			kfree(info->blockbuffer);
 			sensekey = 0x02;	/* not ready */
 			sensecode = 0x3a;	/* medium not present */
 			return USB_STOR_TRANSPORT_FAILED;
@@ -1604,6 +1602,10 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
 		info->blocksize = (1 << info->blockshift);
 		info->blockmask = info->blocksize - 1;
 
+		if (sddr09_init_card_buffers(us)) {
+			goto init_error;
+		}
+
 		// map initialization, must follow get_cardinfo()
 		if (sddr09_read_map(us)) {
 			/* probably out of memory */
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v1] usb: storage: sddr09: move write buffers into info struct
  2025-08-31 19:22 [PATCH v1] usb: storage: sddr09: move write buffers into info struct Alex Tran
@ 2025-09-01  5:37 ` Greg KH
  2025-09-01  8:10 ` Oliver Neukum
  1 sibling, 0 replies; 3+ messages in thread
From: Greg KH @ 2025-09-01  5:37 UTC (permalink / raw)
  To: Alex Tran; +Cc: stern, linux-usb, usb-storage, linux-kernel

On Sun, Aug 31, 2025 at 12:22:47PM -0700, Alex Tran wrote:
> Changelog:

No need for that line here, right?

> - Moved allocation of buffers ('blockbuffer', 'buffer') in 
>   'sddr09_write_data' into info struct and freeing into 
>   'sddr09_card_info_destructor' so that the operations are only 
>   performed once.

Trailing spaces :(

> - 'buffer' length is now size of a full block instead of being 
>   dependent on sectors.

But why are you doing any of this?

Please take a look at the kernel documentation for how to write a good
changelog text.

And do you have this device to test that your changes here work
properly?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v1] usb: storage: sddr09: move write buffers into info struct
  2025-08-31 19:22 [PATCH v1] usb: storage: sddr09: move write buffers into info struct Alex Tran
  2025-09-01  5:37 ` Greg KH
@ 2025-09-01  8:10 ` Oliver Neukum
  1 sibling, 0 replies; 3+ messages in thread
From: Oliver Neukum @ 2025-09-01  8:10 UTC (permalink / raw)
  To: Alex Tran, stern; +Cc: gregkh, linux-usb, usb-storage, linux-kernel

Hi,

On 8/31/25 21:22, Alex Tran wrote:
> +static int sddr09_init_card_buffers(struct us_data *us)
> +{
> +	struct sddr09_card_info *info = (struct sddr09_card_info *)us->extra;
> +	unsigned int pagelen, blocklen, len;
> +
> +	/*
> +	 * blockbuffer is used for reading in the old data, overwriting
> +	 * with the new data, and performing ECC calculations
> +	 */
> +	pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT);
> +	blocklen = (pagelen << info->blockshift);
> +	info->blockbuffer = kmalloc(blocklen, GFP_NOIO);

there is no reason for GFP_NOIO under these circumstances. Please
use GFP_KERNEL.

	Regards
		Oliver


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2025-09-01  8:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-31 19:22 [PATCH v1] usb: storage: sddr09: move write buffers into info struct Alex Tran
2025-09-01  5:37 ` Greg KH
2025-09-01  8:10 ` Oliver Neukum

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).