Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html