Signed-off-by: Andrzej Pietrasiewicz <andrze...@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
---
 drivers/usb/gadget/f_mass_storage.c |   60 ++++++++++++++++++++++++++++------
 drivers/usb/gadget/f_mass_storage.h |    4 ++-
 2 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/gadget/f_mass_storage.c 
b/drivers/usb/gadget/f_mass_storage.c
index a6b3a94..0c3d817 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2068,9 +2068,22 @@ static int received_cbw(struct fsg_dev *fsg, struct 
fsg_buffhd *bh)
        if (common->data_size == 0)
                common->data_dir = DATA_DIR_NONE;
        common->lun = cbw->Lun;
-       if (common->lun >= 0 && common->lun < common->nluns)
-               common->curlun = &common->luns[common->lun];
-       else
+       if (common->lun >= 0 && common->lun < common->nluns) {
+               struct config_item *it;
+
+               mutex_lock(&common->group.cg_subsys->su_mutex);
+               list_for_each_entry(it, &common->group.cg_children, ci_entry) {
+                       struct fsg_lun *lun;
+
+                       lun = to_fsg_lun(it);
+                       if (lun->n_lun == common->lun) {
+                               common->curlun = lun;
+
+                               break;
+                       }
+               }
+               mutex_unlock(&common->group.cg_subsys->su_mutex);
+       } else
                common->curlun = NULL;
        common->tag = cbw->Tag;
        return 0;
@@ -2130,6 +2143,7 @@ static int alloc_request(struct fsg_common *common, 
struct usb_ep *ep,
 /* Reset interface setting and re-init endpoint state (toggle etc). */
 static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
 {
+       struct config_item *item;
        struct fsg_dev *fsg;
        int i, rc = 0;
 
@@ -2214,8 +2228,14 @@ reset:
        }
 
        common->running = 1;
-       for (i = 0; i < common->nluns; ++i)
-               common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
+       mutex_lock(&common->group.cg_subsys->su_mutex);
+       list_for_each_entry(item, &common->group.cg_children, ci_entry) {
+               struct fsg_lun *lun;
+
+               lun = to_fsg_lun(item);
+               lun->unit_attention_data = SS_RESET_OCCURRED;
+       }
+       mutex_unlock(&common->group.cg_subsys->su_mutex);
        return rc;
 }
 
@@ -2246,7 +2266,6 @@ static void handle_exception(struct fsg_common *common)
        int                     i;
        struct fsg_buffhd       *bh;
        enum fsg_state          old_state;
-       struct fsg_lun          *curlun;
        unsigned int            exception_req_tag;
 
        /*
@@ -2314,14 +2333,20 @@ static void handle_exception(struct fsg_common *common)
        if (old_state == FSG_STATE_ABORT_BULK_OUT)
                common->state = FSG_STATE_STATUS_PHASE;
        else {
-               for (i = 0; i < common->nluns; ++i) {
-                       curlun = &common->luns[i];
+               struct config_item *it;
+
+               mutex_lock(&common->group.cg_subsys->su_mutex);
+               list_for_each_entry(it, &common->group.cg_children, ci_entry) {
+                       struct fsg_lun *curlun;
+
+                       curlun = to_fsg_lun(it);
                        curlun->prevent_medium_removal = 0;
                        curlun->sense_data = SS_NO_SENSE;
                        curlun->unit_attention_data = SS_NO_SENSE;
                        curlun->sense_data_info = 0;
                        curlun->info_valid = 0;
                }
+               mutex_unlock(&common->group.cg_subsys->su_mutex);
                common->state = FSG_STATE_IDLE;
        }
        spin_unlock_irq(&common->lock);
@@ -2454,17 +2479,25 @@ static int fsg_main_thread(void *common_)
 
        if (!common->ops || !common->ops->thread_exits
         || common->ops->thread_exits(common) < 0) {
-               struct fsg_lun *curlun = common->luns;
-               unsigned i = common->nluns;
+               struct list_head *cursor;
 
                down_write(&common->filesem);
-               for (; i--; ++curlun) {
+
+               mutex_lock(&common->group.cg_subsys->su_mutex);
+               list_for_each_prev(cursor, &common->group.cg_children) {
+                       struct config_item *item;
+                       struct fsg_lun *curlun;
+
+                       item = list_entry(cursor, struct config_item, ci_entry);
+
+                       curlun = to_fsg_lun(item);
                        if (!fsg_lun_is_open(curlun))
                                continue;
 
                        fsg_lun_close(curlun);
                        curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
                }
+               mutex_unlock(&common->group.cg_subsys->su_mutex);
                up_write(&common->filesem);
        }
 
@@ -2626,6 +2659,7 @@ EXPORT_SYMBOL(fsg_common_init);
 static void fsg_common_release(struct kref *ref)
 {
        struct fsg_common *common = container_of(ref, struct fsg_common, ref);
+       struct config_item *item;
 
        /* If the thread isn't already dead, tell it to exit now */
        if (common->state != FSG_STATE_TERMINATED) {
@@ -2633,6 +2667,10 @@ static void fsg_common_release(struct kref *ref)
                wait_for_completion(&common->thread_notifier);
        }
 
+       list_for_each_entry(item, &common->group.cg_children, ci_entry) {
+               struct fsg_lun *lun = to_fsg_lun(item);
+               fsg_lun_close(lun);
+       }
        {
                struct fsg_buffhd *bh = common->buffhds;
                unsigned i = fsg_num_buffers;
diff --git a/drivers/usb/gadget/f_mass_storage.h 
b/drivers/usb/gadget/f_mass_storage.h
index df313e3..8c0e885 100644
--- a/drivers/usb/gadget/f_mass_storage.h
+++ b/drivers/usb/gadget/f_mass_storage.h
@@ -23,6 +23,9 @@ struct fsg_operations {
 
 /* Data shared by all the FSG instances. */
 struct fsg_common {
+       struct config_group     group;
+       enum ufg_hdr_type       type;
+
        struct usb_gadget       *gadget;
        struct usb_composite_dev *cdev;
        struct fsg_dev          *fsg, *new_fsg;
@@ -47,7 +50,6 @@ struct fsg_common {
 
        unsigned int            nluns;
        unsigned int            lun;
-       struct fsg_lun          *luns;
        struct fsg_lun          *curlun;
 
        unsigned int            bulk_out_maxpacket;
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to