All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michal Nazarewicz <m.nazarewicz@samsung.com>
To: linux-usb@vger.kernel.org
Cc: David Brownell <dbrownell@users.sourceforge.net>,
	Greg KH <greg@kroah.com>,
	Kyungmin Park <kyungmin.park@samsung.com>,
	Marek Szyprowski <m.szyprowski@samsung.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCHv6 11/11] USB: gadget: f_mass_storage: added eject callback
Date: Fri, 18 Jun 2010 14:48:10 +0200	[thread overview]
Message-ID: <8988573bae7ac0365af55eb847a5e2e0ff7cda00.1276864406.git.m.nazarewicz@samsung.com> (raw)
In-Reply-To: <72a1ab93557746c55fe75d844c69bcca7f7c5121.1276864406.git.m.nazarewicz@samsung.com>

Added pre_eject() and post_eject() callbacks which are
called befor and after removable logical unit is ejected.
The first can prevent logical unit from being ejected.

This commit also changes the way callbacks are passed to
the function from gadget.  A fsg_operations structure has
been created which lists all callbacks -- this is passed
to the fsg_config.

This is important because it changes the way thread_exits()
callback is passed.

Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/usb/gadget/f_mass_storage.c |  109 ++++++++++++++++++++++------------
 drivers/usb/gadget/mass_storage.c   |    5 +-
 2 files changed, 74 insertions(+), 40 deletions(-)

diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 072cbf9..e9e45ba 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -316,6 +316,27 @@ static const char fsg_string_interface[] = "Mass Storage";
 /*-------------------------------------------------------------------------*/
 
 struct fsg_dev;
+struct fsg_common;
+
+/* FSF callback functions */
+struct fsg_operations {
+	/* Callback function to call when thread exits.  If no
+	 * callback is set or it returns value lower then zero MSF
+	 * will force eject all LUNs it operates on (including those
+	 * marked as non-removable or with prevent_medium_removal flag
+	 * set). */
+	int (*thread_exits)(struct fsg_common *common);
+
+	/* Called prior to ejection.  Negative return means error,
+	 * zero means to continue with ejection, positive means not to
+	 * eject. */
+	int (*pre_eject)(struct fsg_common *common,
+			 struct fsg_lun *lun, int num);
+	/* Called after ejection.  Negative return means error, zero
+	 * or positive is just a success. */
+	int (*post_eject)(struct fsg_common *common,
+			  struct fsg_lun *lun, int num);
+};
 
 
 /* Data shared by all the FSG instances. */
@@ -370,8 +391,8 @@ struct fsg_common {
 	struct completion	thread_notifier;
 	struct task_struct	*thread_task;
 
-	/* Callback function to call when thread exits. */
-	int			(*thread_exits)(struct fsg_common *common);
+	/* Callback functions. */
+	const struct fsg_operations	*ops;
 	/* Gadget's private data. */
 	void			*private_data;
 
@@ -395,12 +416,8 @@ struct fsg_config {
 	const char		*lun_name_format;
 	const char		*thread_name;
 
-	/* Callback function to call when thread exits.  If no
-	 * callback is set or it returns value lower then zero MSF
-	 * will force eject all LUNs it operates on (including those
-	 * marked as non-removable or with prevent_medium_removal flag
-	 * set). */
-	int			(*thread_exits)(struct fsg_common *common);
+	/* Callback functions. */
+	const struct fsg_operations	*ops;
 	/* Gadget's private data. */
 	void			*private_data;
 
@@ -436,6 +453,7 @@ static inline int __fsg_is_set(struct fsg_common *common,
 	if (common->fsg)
 		return 1;
 	ERROR(common, "common->fsg is NULL in %s at %u\n", func, line);
+	WARN_ON(1);
 	return 0;
 }
 
@@ -1396,43 +1414,55 @@ static int do_start_stop(struct fsg_common *common)
 	} else if (!curlun->removable) {
 		curlun->sense_data = SS_INVALID_COMMAND;
 		return -EINVAL;
-	}
-
-	loej = common->cmnd[4] & 0x02;
-	start = common->cmnd[4] & 0x01;
-
-	/* eject code from file_storage.c:do_start_stop() */
-
-	if ((common->cmnd[1] & ~0x01) != 0 ||	  /* Mask away Immed */
-		(common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */
+	} else if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away Immed */
+		   (common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */
 		curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 		return -EINVAL;
 	}
 
-	if (!start) {
-		/* Are we allowed to unload the media? */
-		if (curlun->prevent_medium_removal) {
-			LDBG(curlun, "unload attempt prevented\n");
-			curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
-			return -EINVAL;
-		}
-		if (loej) {	/* Simulate an unload/eject */
-			up_read(&common->filesem);
-			down_write(&common->filesem);
-			fsg_lun_close(curlun);
-			up_write(&common->filesem);
-			down_read(&common->filesem);
-		}
-	} else {
+	loej  = common->cmnd[4] & 0x02;
+	start = common->cmnd[4] & 0x01;
 
-		/* Our emulation doesn't support mounting; the medium is
-		 * available for use as soon as it is loaded. */
+	/* Our emulation doesn't support mounting; the medium is
+	 * available for use as soon as it is loaded. */
+	if (start) {
 		if (!fsg_lun_is_open(curlun)) {
 			curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
 			return -EINVAL;
 		}
+		return 0;
 	}
-	return 0;
+
+	/* Are we allowed to unload the media? */
+	if (curlun->prevent_medium_removal) {
+		LDBG(curlun, "unload attempt prevented\n");
+		curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
+		return -EINVAL;
+	}
+
+	if (!loej)
+		return 0;
+
+	/* Simulate an unload/eject */
+	if (common->ops && common->ops->pre_eject) {
+		int r = common->ops->pre_eject(common, curlun,
+					       curlun - common->luns);
+		if (unlikely(r < 0))
+			return r;
+		else if (r)
+			return 0;
+	}
+
+	up_read(&common->filesem);
+	down_write(&common->filesem);
+	fsg_lun_close(curlun);
+	up_write(&common->filesem);
+	down_read(&common->filesem);
+
+	return common->ops && common->ops->post_eject
+		? min(0, common->ops->post_eject(common, curlun,
+						 curlun - common->luns))
+		: 0;
 }
 
 
@@ -2657,7 +2687,8 @@ static int fsg_main_thread(void *common_)
 	common->thread_task = NULL;
 	spin_unlock_irq(&common->lock);
 
-	if (!common->thread_exits || common->thread_exits(common) < 0) {
+	if (!common->ops || !common->ops->thread_exits
+	 || common->ops->thread_exits(common) < 0) {
 		struct fsg_lun *curlun = common->luns;
 		unsigned i = common->nluns;
 
@@ -2733,6 +2764,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
 		common->free_storage_on_release = 0;
 	}
 
+	common->ops = cfg->ops;
 	common->private_data = cfg->private_data;
 
 	common->gadget = gadget;
@@ -2854,7 +2886,6 @@ buffhds_first_it:
 
 
 	/* Tell the thread to start working */
-	common->thread_exits = cfg->thread_exits;
 	common->thread_task =
 		kthread_create(fsg_main_thread, common,
 			       OR(cfg->thread_name, "file-storage"));
@@ -3151,8 +3182,8 @@ fsg_config_from_params(struct fsg_config *cfg,
 	cfg->product_name = 0;
 	cfg->release = 0xffff;
 
-	cfg->thread_exits = 0;
-	cfg->private_data = 0;
+	cfg->ops = NULL;
+	cfg->private_data = NULL;
 
 	/* Finalise */
 	cfg->can_stall = params->stall;
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index 2b11e20..306098f 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -143,6 +143,9 @@ static int msg_thread_exits(struct fsg_common *common)
 
 static int __init msg_do_config(struct usb_configuration *c)
 {
+	static const struct fsg_operations ops = {
+		.thread_exits = msg_thread_exits,
+	};
 	static struct fsg_common common;
 
 	struct fsg_common *retp;
@@ -155,7 +158,7 @@ static int __init msg_do_config(struct usb_configuration *c)
 	}
 
 	fsg_config_from_params(&config, &mod_data);
-	config.thread_exits = msg_thread_exits;
+	config.ops = &ops;
 
 	retp = fsg_common_init(&common, c->cdev, &config);
 	if (IS_ERR(retp))
-- 
1.7.1


  reply	other threads:[~2010-06-18 12:47 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-07 12:39 [PATCHv4 00/13] USB improvements and cleanpus, g_multi install mode Michal Nazarewicz
2010-06-07 12:39 ` [PATCHv4 01/13] USB: gadget: g_mass_storage: static data instead of dynamic allocation Michal Nazarewicz
2010-06-07 12:39   ` [PATCHv4 02/13] USB: gadget: f_mass_storage: fsg_add() renamed to fsg_bind_config() Michal Nazarewicz
2010-06-07 12:39     ` [PATCHv4 03/13] USB: gadget: f_fs: functionfs_add() renamed to functionfs_bind_config() Michal Nazarewicz
2010-06-07 12:39       ` [PATCHv4 04/13] USB: gadget: composite: usb_string_ids_*() functions added Michal Nazarewicz
2010-06-07 12:39         ` [PATCHv4 05/13] USB: gadget: f_fs: use usb_string_ids_n() Michal Nazarewicz
2010-06-07 12:39           ` [PATCHv4 06/13] USB: gadget: g_multi: code clean up and refactoring Michal Nazarewicz
2010-06-07 12:39             ` [PATCHv4 07/13] USB: gadget: g_ether: updated INF file Michal Nazarewicz
2010-06-07 12:39               ` [PATCHv4 08/13] USB: gadget: g_serial: INF file updated Michal Nazarewicz
2010-06-07 12:39                 ` [PATCHv4 09/13] USB: gadget: g_multi: added documentation and INF files Michal Nazarewicz
2010-06-07 12:39                   ` [PATCHv4 10/13] USB: gadget: g_multi: more configurable Michal Nazarewicz
2010-06-07 12:39                     ` [PATCHv4 11/13] USB: gadget: composite: addad disconnect callback Michal Nazarewicz
2010-06-07 12:39                       ` [PATCHv4 12/13] USB: gadget: f_mass_storage: added eject callback Michal Nazarewicz
2010-06-07 12:40                         ` [PATCHv4 13/13] USB: gadget: g_multi: Install Mode added Michal Nazarewicz
2010-06-14  8:43                         ` [PATCHv4.1 12/13] USB: gadget: f_mass_storage: added eject callback Michal Nazarewicz
2010-06-08 14:02                       ` [PATCHv4 11/13] USB: gadget: composite: addad disconnect callback David Brownell
2010-06-08 13:37                     ` [PATCHv4 10/13] USB: gadget: g_multi: more configurable David Brownell
2010-06-09 10:15                       ` Michał Nazarewicz
2010-06-08 13:13                 ` [PATCHv4 08/13] USB: gadget: g_serial: INF file updated David Brownell
2010-06-08 13:20                   ` Xiaofan Chen
2010-06-09  8:55                   ` Michał Nazarewicz
2010-06-09  9:29                     ` Xiaofan Chen
2010-06-09 10:01                       ` Michał Nazarewicz
2010-06-09 14:59                         ` Greg KH
2010-06-09 15:22                           ` Michał Nazarewicz
2010-06-09 15:33                             ` Greg KH
2010-06-09 15:53                               ` Michał Nazarewicz
2010-06-08 12:57               ` [PATCHv4 07/13] USB: gadget: g_ether: updated INF file David Brownell
2010-06-08 13:17                 ` Xiaofan Chen
2010-06-14  8:43               ` [PATCHv4.1 " Michal Nazarewicz
2010-06-14 11:32                 ` Xiaofan Chen
2010-06-14 19:42                   ` David Brownell
2010-06-14 20:04                     ` Michał Nazarewicz
2010-06-14  8:43         ` [PATCH] USB: gadget: g_fs: code cleanup and bug fixes Michal Nazarewicz
2010-06-14  8:43   ` [PATCHv4.1 01/13] USB: gadget: g_mass_storage: static data instead of dynamic allocation Michal Nazarewicz
2010-06-15 18:55 ` [PATCHv4 00/13] USB improvements and cleanpus, g_multi install mode Greg KH
2010-06-16 10:07   ` [PATCHv5 00/11] g_multi & other improvements and cleanpus Michal Nazarewicz
2010-06-16 10:07     ` [PATCHv5 01/11] USB: gadget: g_mass_storage: static data instead of dynamic allocation Michal Nazarewicz
2010-06-16 10:07       ` [PATCHv5 02/11] USB: gadget: f_mass_storage: fsg_add() renamed to fsg_bind_config() Michal Nazarewicz
2010-06-16 10:07         ` [PATCHv5 03/11] USB: gadget: f_fs: functionfs_add() renamed to functionfs_bind_config() Michal Nazarewicz
2010-06-16 10:07           ` [PATCHv5 04/11] USB: gadget: composite: usb_string_ids_*() functions added Michal Nazarewicz
2010-06-16 10:08             ` [PATCHv5 05/11] USB: gadget: f_fs: use usb_string_ids_n() Michal Nazarewicz
2010-06-16 10:08               ` [PATCHv5 06/11] USB: gadget: g_multi: code clean up and refactoring Michal Nazarewicz
2010-06-16 10:08                 ` [PATCHv5 07/11] USB: gadget: g_ether: updated INF file Michal Nazarewicz
2010-06-16 10:08                   ` [PATCHv5 08/11] USB: gadget: g_serial: INF file updated Michal Nazarewicz
2010-06-16 10:08                     ` [PATCHv5 09/11] USB: gadget: g_multi: added documentation and INF files Michal Nazarewicz
2010-06-16 10:08                       ` [PATCHv5 10/11] USB: gadget: composite: addad disconnect callback Michal Nazarewicz
2010-06-16 10:08                         ` [PATCHv5 11/11] USB: gadget: f_mass_storage: added eject callback Michal Nazarewicz
2010-06-17 11:04                         ` [PATCHv5 10/11] USB: gadget: composite: addad disconnect callback Sergei Shtylyov
2010-06-18 14:19                           ` Sergei Shtylyov
2010-06-16 13:56                     ` [PATCHv5 08/11] USB: gadget: g_serial: INF file updated David Brownell
2010-06-16 14:12                   ` [PATCHv5 07/11] USB: gadget: g_ether: updated INF file David Brownell
2010-06-16 14:41                     ` [PATCHv5.1 " Michal Nazarewicz
2010-06-17 17:51                 ` [PATCHv5 06/11] USB: gadget: g_multi: code clean up and refactoring Greg KH
2010-06-18 10:31                   ` Michał Nazarewicz
2010-06-18 14:39                     ` Greg KH
2010-06-17 17:52     ` [PATCHv5 00/11] g_multi & other improvements and cleanpus Greg KH
2010-06-18 10:31       ` Michał Nazarewicz
     [not found]       ` <2809a031d19ac6ef793d7fe343e225b8d80099c3.1276864406.git.m.nazarewicz@samsung.com>
2010-06-18 12:48         ` [PATCHv6 07/11] USB: gadget: g_ether: updated INF file Michal Nazarewicz
2010-06-18 12:48           ` [PATCHv6 08/11] USB: gadget: g_serial: INF file updated Michal Nazarewicz
2010-06-18 12:48             ` [PATCHv6 09/11] USB: gadget: g_multi: added documentation and INF files Michal Nazarewicz
2010-06-18 12:48               ` [PATCHv6 10/11] USB: gadget: composite: added disconnect callback Michal Nazarewicz
2010-06-18 12:48                 ` Michal Nazarewicz [this message]
2010-06-18 13:07               ` [PATCHv6.1 09/11] USB: gadget: g_multi: added documentation and INF files Michal Nazarewicz
2010-06-18 15:52                 ` Greg KH
2010-06-18 16:14                   ` Michał Nazarewicz
2010-06-18 15:04       ` [PATCHv6.1 06/11] USB: gadget: g_multi: code clean up and refactoring Michal Nazarewicz
2010-06-18 21:25         ` Sergei Shtylyov
2010-06-21  8:43           ` Michał Nazarewicz
2010-06-14  8:43 [PATCH] USB: gadget: g_fs: possible invalid pointer reference bug fixed Michal Nazarewicz
2010-06-15 10:10 ` Sergei Shtylyov
2010-06-16  9:30   ` Michał Nazarewicz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8988573bae7ac0365af55eb847a5e2e0ff7cda00.1276864406.git.m.nazarewicz@samsung.com \
    --to=m.nazarewicz@samsung.com \
    --cc=dbrownell@users.sourceforge.net \
    --cc=greg@kroah.com \
    --cc=kyungmin.park@samsung.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.