Signed-off-by: Andrzej Pietrasiewicz <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
---
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html