Skip to contentSkip to conversation

My work on MemoryStick system

PATCH Superseded Maxim Levitsky 2 participants 8 messages Aug 20, 2010 – Aug 23, 2010

Subsystems (2)
lore
Share & tools
lore

Maxim Levitsky

author maintainer
#0 lore raw

PATCH 1/1 My work on MemoryStick system

Hi,

This patch series contains the work I did for memorystick subsystem.

I resend slightly cleaned up driver for my card reader in patch #2 patch #1 and #3 are new and add support for Legacy MemorySticks (<= 128MB)

Everything works and more or less tested.

Best regards,
Maxim Levitsky

author maintainer
#1 lore raw

PATCH 1/3 memstick: add few common helpers

I add here few helpers that should make memstick block driver a bit simplier.
Currently only my forthcoming ms_block.c will use them, but I plan to make mspro_blk use them too.

---
 drivers/memstick/core/memstick.c |  109 ++++++++++++++++++++++++++++++++++++++
 include/linux/memstick.h         |   22 +++++++-
 2 files changed, 130 insertions(+), 1 deletions(-)
drivers/memstick/core/memstick.c +109 -0
index c00fe82..1734ea3 100644
@@ -362,6 +362,13 @@ static int h_memstick_set_rw_addr(struct memstick_dev *card,
 	}
 }
 
+
+static int h_mspro_block_default_bad(struct memstick_dev *card,
+				     struct memstick_request **mrq)
+{
+	return -ENXIO;
+}
+
 /**
  * memstick_set_rw_addr - issue SET_RW_REG_ADDR request and wait for it to
  *                        complete
@@ -377,6 +384,108 @@ int memstick_set_rw_addr(struct memstick_dev *card)
 }
 EXPORT_SYMBOL(memstick_set_rw_addr);
 
+
+/**
+ * memstick_fetch_request - initialize new request to use by request handler
+ * @card - card to use
+ * @mrq - request to initialize
+ */
+void memstick_fetch_request(struct memstick_dev *card,
+					struct memstick_request **mrq)
+{
+	if (*mrq == NULL) {
+		*mrq = &card->current_mrq;
+		(*mrq)->error = 0;
+		card->state = 0;
+	}
+}
+EXPORT_SYMBOL(memstick_fetch_request);
+
+/**
+ * memstick_complete_req - signal that request is completed
+ * @card - card to use
+ * @mrq - request to use
+ * @error - result of the request
+ *
+ * Card drivers can use that function to signal end of request
+ */
+int memstick_complete_request(struct memstick_dev *card,
+			struct memstick_request *req, int error)
+{
+	if (error)
+		req->error = error;
+
+	card->state = -1;
+	card->next_request = h_mspro_block_default_bad;
+	complete(&card->mrq_complete);
+	return -EAGAIN;
+}
+EXPORT_SYMBOL(memstick_complete_request);
+
+/**
+ * ms_send_int_request - optionaly init new MS_TPC_GET_INT.
+ * if last request already contains the int flags, reuse them
+ * returns 1 if new request was initialized
+ * Will artifictially return MEMSTICK_INT_CMDNAK if this function was
+ * called more that once in 300 msecs without memstick_finish_int_request
+ * in between
+ * @card - card to use
+ * @mrq - request to use
+ */
+
+int memstick_send_int_request(struct memstick_dev *card,
+					struct memstick_request *req)
+{
+	if (!card->int_polling) {
+		card->int_poll_start_time = jiffies;
+		card->int_polling = true;
+	} else if (time_after(jiffies,
+			card->int_poll_start_time + msecs_to_jiffies(300))) {
+		req->data[0] |= MEMSTICK_INT_CMDNAK;
+		return 0;
+	}
+
+	if ((card->caps & MEMSTICK_CAP_AUTO_GET_INT) && req->need_card_int) {
+		BUG_ON(req->error);
+		req->data[0] = req->int_reg;
+		req->need_card_int = 0;
+		return 0;
+	} else {
+		memstick_init_req(req, MS_TPC_GET_INT, NULL, 1);
+		return 1;
+	}
+}
+EXPORT_SYMBOL(memstick_send_int_request);
+
+/**
+ * Signal success of int polling, and cancel timeout
+ * Use this if you use memstick_send_int_request
+ * @card - card to use
+ */
+void memstick_finish_int_request(struct memstick_dev *card)
+{
+	card->int_polling = false;
+}
+EXPORT_SYMBOL(memstick_finish_int_request);
+
+/**
+ * memstick_do_request_handler - runs state machine untill it finishes
+ * helper to be used in card drivers
+ * @card - card to use
+ * next_request - the state machine
+ */
+int memstick_do_request_handler(struct memstick_dev *card,
+	int   (*next_request)(struct memstick_dev *card,
+					struct memstick_request **mrq))
+{
+	card->next_request = next_request;
+	memstick_new_req(card->host);
+	wait_for_completion(&card->mrq_complete);
+	return card->current_mrq.error;
+}
+EXPORT_SYMBOL(memstick_do_request_handler);
+
+
 static struct memstick_dev *memstick_alloc_card(struct memstick_host *host)
 {
 	struct memstick_dev *card = kzalloc(sizeof(struct memstick_dev),
include/linux/memstick.h +21 -1
index 690c35a..3bbdb77 100644
@@ -247,7 +247,7 @@ struct memstick_request {
 		struct scatterlist sg;
 		struct {
 			unsigned char data_len;
-			unsigned char data[15];
+			unsigned char data[32];
 		};
 	};
 };
@@ -270,6 +270,12 @@ struct memstick_dev {
 	void                     (*start)(struct memstick_dev *card);
 
 	struct device            dev;
+
+	/* Private area for request processing */
+	bool			 int_polling;
+	unsigned long		 int_poll_start_time;
+	int			 state;
+	int			 caps;
 };
 
 struct memstick_host {
@@ -329,6 +335,20 @@ void memstick_new_req(struct memstick_host *host);
 
 int memstick_set_rw_addr(struct memstick_dev *card);
 
+void memstick_fetch_request(struct memstick_dev *card,
+					struct memstick_request **mrq);
+int memstick_complete_request(struct memstick_dev *card,
+			struct memstick_request *req, int error);
+
+int memstick_send_int_request(struct memstick_dev *card,
+					struct memstick_request *req);
+
+void memstick_finish_int_request(struct memstick_dev *card);
+
+int memstick_do_request_handler(struct memstick_dev *card,
+	int   (*next_request)(struct memstick_dev *card,
+				struct memstick_request **mrq));
+
 static inline void *memstick_priv(struct memstick_host *host)
 {
 	return (void *)host->private;
Signature · 1 line
1.7.0.4
author maintainer
#2 lore raw

PATCH 2/3 MEMSTICK: Add driver for Ricoh R5C592 Card reader.

In reply to Maxim Levitsky
---
 MAINTAINERS                    |    5 +
 drivers/memstick/host/Kconfig  |   13 +
 drivers/memstick/host/Makefile |    1 +
 drivers/memstick/host/r592.c   |  889 ++++++++++++++++++++++++++++++++++++++++
 drivers/memstick/host/r592.h   |  177 ++++++++
 5 files changed, 1085 insertions(+), 0 deletions(-)
 create mode 100644 drivers/memstick/host/r592.c
 create mode 100644 drivers/memstick/host/r592.h
MAINTAINERS +5 -0
index b5b8baa..e25019f 100644
@@ -4854,6 +4854,11 @@ S:	Maintained
 F:	drivers/mtd/nand/r852.c
 F:	drivers/mtd/nand/r852.h
 
+RICOH R5C592 MEMORYSTICK DRIVER
+M:	Maxim Levitsky <[email protected]>
+S:	Maintained
+F:	drivers/memstick/host/r592.*
+
 RISCOM8 DRIVER
 S:	Orphan
 F:	Documentation/serial/riscom8.txt
drivers/memstick/host/Kconfig +13 -0
index 4ce5c8d..7022a2a 100644
@@ -30,3 +30,16 @@ config MEMSTICK_JMICRON_38X
 
           To compile this driver as a module, choose M here: the
 	  module will be called jmb38x_ms.
+
+config MEMSTICK_R592
+	tristate "Ricoh R5C592 MemoryStick interface support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && PCI
+
+	help
+	  Say Y here if you want to be able to access MemoryStick cards with
+	  the Ricoh R5C592 MemoryStick card reader (which is part of 5 in one
+		multifunction reader)
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called r592.
+
drivers/memstick/host/Makefile +1 -0
index 12530e4..ad63c16 100644
@@ -8,3 +8,4 @@ endif
 
 obj-$(CONFIG_MEMSTICK_TIFM_MS)		+= tifm_ms.o
 obj-$(CONFIG_MEMSTICK_JMICRON_38X)	+= jmb38x_ms.o
+obj-$(CONFIG_MEMSTICK_R592)		+= r592.o
drivers/memstick/host/r592.c new file +889 -0

889 lines not on this page · raw message

drivers/memstick/host/r592.h new file +177 -0

178 lines not on this page · raw message

Signature · 1 line
1.7.0.4
author maintainer
#3 lore raw

PATCH 3/3 memstick: add support for Legacy memorysticks

In reply to Maxim Levitsky

Huge thanks for Alex Dubov for code that this is based on and for lot, really lot of help he gave me in understanding MemorySticks and implementing this driver.

His help made this driver possible.

As any code that works with user data this driver isn't recommened to use with valuable data.

It tries its best though to avoid data corruption and possible damage to the card.

---
 MAINTAINERS                      |    5 +
 drivers/memstick/core/Kconfig    |   13 +
 drivers/memstick/core/Makefile   |    2 +-
 drivers/memstick/core/ms_block.c | 2243 ++++++++++++++++++++++++++++++++++++++
 drivers/memstick/core/ms_block.h |  236 ++++
 drivers/memstick/host/r592.c     |    2 +-
 6 files changed, 2499 insertions(+), 2 deletions(-)
 create mode 100644 drivers/memstick/core/ms_block.c
 create mode 100644 drivers/memstick/core/ms_block.h
MAINTAINERS +5 -0
index e25019f..e7d5a84 100644
@@ -5375,6 +5375,11 @@ W:	http://tifmxx.berlios.de/
 S:	Maintained
 F:	drivers/memstick/host/tifm_ms.c
 
+SONY MEMORYSTICK STANDARD SUPPORT
+M:	Maxim Levitsky <[email protected]>
+S:	Maintained
+F:	drivers/memstick/core/ms_block.*
+
 SOUND
 M:	Jaroslav Kysela <[email protected]>
 M:	Takashi Iwai <[email protected]>
drivers/memstick/core/Kconfig +13 -0
index 95f1814..f0920c2 100644
@@ -24,3 +24,16 @@ config MSPRO_BLOCK
 	  support. This provides a block device driver, which you can use
 	  to mount the filesystem. Almost everyone wishing MemoryStick
 	  support should say Y or M here.
+
+config MS_BLOCK
+	tristate "MemoryStick Standard device driver"
+	depends on BLOCK && EXPERIMENTAL
+	help
+	  Say Y here to enable the MemoryStick Standard device driver
+	  support. This provides a block device driver, which you can use
+	  to mount the filesystem.
+	  This driver works with old (bulky) MemoryStick and MemoryStick Duo
+	  but not PRO. Say Y if you have such card.
+	  Driver is new and not yet well tested, thus it can damage your card
+	  (even permanently)
+
drivers/memstick/core/Makefile +1 -1
index 8b2b529..19d960b 100644
@@ -7,5 +7,5 @@ ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
 endif
 
 obj-$(CONFIG_MEMSTICK)		+= memstick.o
-
+obj-$(CONFIG_MS_BLOCK)		+= ms_block.o
 obj-$(CONFIG_MSPRO_BLOCK)	+= mspro_block.o
drivers/memstick/core/ms_block.c new file +2243 -0

2,243 lines not on this page · raw message

drivers/memstick/core/ms_block.h new file +236 -0

236 lines not on this page · raw message

drivers/memstick/host/r592.c +1 -1
index cf1fd1a..ec8d400 100644
@@ -639,8 +639,8 @@ static irqreturn_t r592_irq(int irq, void *data)
 		indicate that card was removed/inserted and/or present */
 	if (irq_status & (R592_REG_MSC_IRQ_INSERT | R592_REG_MSC_IRQ_REMOVE)) {
 
-		ret = IRQ_HANDLED;
 		bool card_was_added = irq_status & R592_REG_MSC_IRQ_INSERT;
+		ret = IRQ_HANDLED;
 
 		message("IRQ: card %s", card_was_added ? "added" : "removed");
 
Signature · 1 line
1.7.0.4
author maintainer
#4 lore raw
In reply to Maxim Levitsky
Quoted 4 lines · Maxim Levitsky

Hi,

This patch series contains the work I did for memorystick subsystem.

Quoted 9 lines

I resend slightly cleaned up driver for my card reader in patch #2 patch #1 and #3 are new and add support for Legacy MemorySticks (<= 128MB)

Everything works and more or less tested.

Best regards,
Maxim Levitsky

I just tested this series with Jmicron, and unfortunelly there are bugs.

* driver refuses to handle 26 byte TPC I use to read regs (sizeof(ms_registers). If I bump it to 32, it works.

* With this fix first few reads still fail.
That means that card isn't detected always because boot blocks might not be read.
Later card works fine.

* Also I found out that msproblk.c allocates memory for attributes IO using stock kmalloc, and hangs that to driver.
However if driver doesn't support such address, it will fail. I fixed that in my driver by properly calling dma_unmap_sg, and thus using SWIOTLB if necessary.
But Jmicron driver doesn't unmap its sg.
(Yet the system with Jmicron device has just one GB, so this isn't the problem I am seeing).

Best regards,
Maxim Levitsky

maintainer
#5 lore raw
Quoted 6 lines

I just tested this series with Jmicron, and unfortunelly there are bugs.

* driver refuses to handle 26 byte TPC I use to read regs (sizeof(ms_registers). If I bump it to 32, it works.

It will work with any multiply of 4 (24 and 28 work as well). It's a known "feature".

Quoted 7 lines

* With this fix first few reads still fail. That means that card isn't detected always because boot blocks might not
be read.
Later card works fine.

Quoted 5 lines

* Also I found out that msproblk.c allocates memory for attributes IO
using stock kmalloc, and hangs that to driver. However if driver doesn't support such address, it will fail.

Why would hardware do anything at all with attribute memory space?

Quoted 8 lines

I fixed that in my driver by properly calling dma_unmap_sg, and thus
using SWIOTLB if necessary.
But Jmicron driver doesn't unmap its sg.
(Yet the system with Jmicron device has just one GB, so this isn't the
problem I am seeing).

author maintainer
#6 lore raw
Quoted 9 lines · Alex Dubov
Quoted 6 lines

I just tested this series with Jmicron, and unfortunelly there are bugs.

* driver refuses to handle 26 byte TPC I use to read regs (sizeof(ms_registers). If I bump it to 32, it works.

It will work with any multiply of 4 (24 and 28 work as well). It's a known "feature".

Then I bump the size of ms_registers to 32 and leave this as is. OK?
And I add a warning about this feature of some hardwares someplace.

But what about MS_TPC_GET_INT. This asks for single byte. Hardware has to support it.

Quoted 8 lines
Quoted 8 lines

* With this fix first few reads still fail. That means that card isn't detected always because boot blocks might not
be read.
Later card works fine.

Quoted 7 lines
Quoted 5 lines

* Also I found out that msproblk.c allocates memory for attributes IO
using stock kmalloc, and hangs that to driver. However if driver doesn't support such address, it will fail.

Why would hardware do anything at all with attribute memory space?

Read it?

You allocate the memory with kmalloc, create a sg with sg_init_one and pass that to driver.
So therefore it can be from arbitrary address.

In fact swiotlb takes care of that, and I just forgot the dma_unmap_sg in my r592.c...

Quoted 5 lines
Quoted 5 lines

I fixed that in my driver by properly calling dma_unmap_sg, and thus
using SWIOTLB if necessary.
But Jmicron driver doesn't unmap its sg.

It does btw, didn't notice....

Quoted 3 lines
Quoted 3 lines

(Yet the system with Jmicron device has just one GB, so this isn't the
problem I am seeing).

I found further problems in jmicron driver:

1. Serial mode doesn't work well.
I first read the boot block, and then enable parallel mode. I do so because boot block has a flag that tells if parallel mode is supported.
It turns out that sector reads often don't finish, especially first and often second one which contain boot blocks.
If I enable parallel mode right away problem goes away.

2. the MS_TPC_WRITE_LONG_DATA fail, therefore I can't write anything to the stick.

As soon as my driver starts to write a block, first MS_TPC_WRITE_LONG_DATA succeeds, but second one timeouts. (there is no MS_TPC_GET_INT in between, because of parallel mode).

Maybe I do something wrong in my ms_block.c, but I checked it many times, and it appears to be correct, and it works fine with r592.c

Best regards,
Maxim Levitsky

maintainer
#7 lore raw
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines

I just tested this series with Jmicron, and

unfortunelly

Quoted 3 lines
Quoted 3 lines

there are bugs.

* driver refuses to handle 26 byte TPC I use to

read regs

Quoted 1 line
Quoted 1 line

(sizeof(ms_registers). If I bump it to 32, it

Quoted 8 lines

works.

Quoted 2 lines

It will work with any multiply of 4 (24 and 28 work as

well). It's a known

Quoted 1 line

"feature".

Then I bump the size of ms_registers to 32 and leave this as is.
OK?

I'd rather minimize the transfer size, than increase it.

Quoted 6 lines

And I add a warning about this feature of some hardwares someplace.

But what about MS_TPC_GET_INT. This asks for single byte. Hardware has to support it.

They've got a custom register for its value. GET_INT is implemented by different hardware than READ/WRITE_REG

Quoted 20 lines
Quoted 7 lines
Quoted 7 lines

* With this fix first few reads still fail.
That means that card isn't detected always

because boot

Quoted 5 lines
Quoted 5 lines

blocks might not
be read.
Later card works fine.

* Also I found out that msproblk.c allocates

memory for

Quoted 3 lines
Quoted 3 lines

attributes IO
using stock kmalloc, and hangs that to driver.
However if driver doesn't support such address,

it will

Quoted 2 lines
Quoted 1 line

fail.

Quoted 8 lines
Quoted 1 line

Why would hardware do anything at all with attribute

memory space?
Read it?

You allocate the memory with kmalloc, create a sg with sg_init_one and
pass that to driver.
So therefore it can be from arbitrary address.

Yes, indeed.

Quoted 4 lines

I found further problems in jmicron driver:

Quoted 10 lines

1. Serial mode doesn't work well.
I first read the boot block, and then enable parallel mode.
I do so because boot block has a flag that tells if parallel mode is
supported.
It turns out that sector reads often don't finish, especially first and
often second one which contain boot blocks.
If I enable parallel mode right away problem goes away.

They have really weird dependency between clock setup and operation mode. Try to use the clock setup values from the errata I've sent you. The order of register initialization and reset timing seems to affect the operation as well.

To summarize my opinion about it: if I had to design a card reader, I won't even look at anything, but TI chips. :-)

Quoted 23 lines

2. the MS_TPC_WRITE_LONG_DATA fail, therefore I can't write anything to
the stick.

As soon as my driver starts to write a block,  first MS_TPC_WRITE_LONG_DATA succeeds, but second one timeouts. (there is no MS_TPC_GET_INT in between, because of parallel mode).

Maybe I do something wrong in my ms_block.c, but I checked it many
times, and it appears to be correct, and it works fine with r592.c

Best regards,
Maxim Levitsky