Commit a41ae418 authored by Michal Nazarewicz's avatar Michal Nazarewicz Committed by Greg Kroah-Hartman

USB: g_mass_storage: parts of fsg_dev moved to fsg_common structure

In the final version, many fsg_dev structures will (be able to)
refer to a single fsg_common structure and so it is required
to move common data to another object which can be shared.

Situation where many fsg_dev structures refer single fsg_common
structure is when a single instance of MSF is used in several
USB configurations.
Signed-off-by: default avatarMichal Nazarewicz <m.nazarewicz@samsung.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 93bcf12e
...@@ -320,14 +320,32 @@ MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk"); ...@@ -320,14 +320,32 @@ MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* Data shared by all the FSG instances. */
struct fsg_common {
/* filesem protects: backing files in use */
struct rw_semaphore filesem;
struct fsg_buffhd *next_buffhd_to_fill;
struct fsg_buffhd *next_buffhd_to_drain;
struct fsg_buffhd buffhds[FSG_NUM_BUFFERS];
int cmnd_size;
u8 cmnd[MAX_COMMAND_SIZE];
unsigned int nluns;
unsigned int lun;
struct fsg_lun *luns;
struct fsg_lun *curlun;
};
struct fsg_dev { struct fsg_dev {
/* lock protects: state, all the req_busy's, and cbbuf_cmnd */ struct fsg_common *common;
/* lock protects: state, all the req_busy's */
spinlock_t lock; spinlock_t lock;
struct usb_gadget *gadget; struct usb_gadget *gadget;
/* filesem protects: backing files in use */
struct rw_semaphore filesem;
/* reference counting: wait until all LUNs are released */ /* reference counting: wait until all LUNs are released */
struct kref ref; struct kref ref;
...@@ -356,27 +374,16 @@ struct fsg_dev { ...@@ -356,27 +374,16 @@ struct fsg_dev {
struct usb_ep *bulk_in; struct usb_ep *bulk_in;
struct usb_ep *bulk_out; struct usb_ep *bulk_out;
struct fsg_buffhd *next_buffhd_to_fill;
struct fsg_buffhd *next_buffhd_to_drain;
struct fsg_buffhd buffhds[FSG_NUM_BUFFERS];
int thread_wakeup_needed; int thread_wakeup_needed;
struct completion thread_notifier; struct completion thread_notifier;
struct task_struct *thread_task; struct task_struct *thread_task;
int cmnd_size;
u8 cmnd[MAX_COMMAND_SIZE];
enum data_direction data_dir; enum data_direction data_dir;
u32 data_size; u32 data_size;
u32 data_size_from_cmnd; u32 data_size_from_cmnd;
u32 tag; u32 tag;
unsigned int lun;
u32 residue; u32 residue;
u32 usb_amount_left; u32 usb_amount_left;
unsigned int nluns;
struct fsg_lun *luns;
struct fsg_lun *curlun;
}; };
typedef void (*fsg_routine_t)(struct fsg_dev *); typedef void (*fsg_routine_t)(struct fsg_dev *);
...@@ -674,7 +681,7 @@ static int class_setup_req(struct fsg_dev *fsg, ...@@ -674,7 +681,7 @@ static int class_setup_req(struct fsg_dev *fsg,
if (w_index != 0 || w_value != 0) if (w_index != 0 || w_value != 0)
return -EDOM; return -EDOM;
VDBG(fsg, "get max LUN\n"); VDBG(fsg, "get max LUN\n");
*(u8 *) req->buf = fsg->nluns - 1; *(u8 *) req->buf = fsg->common->nluns - 1;
return 1; return 1;
} }
...@@ -903,7 +910,7 @@ static int sleep_thread(struct fsg_dev *fsg) ...@@ -903,7 +910,7 @@ static int sleep_thread(struct fsg_dev *fsg)
static int do_read(struct fsg_dev *fsg) static int do_read(struct fsg_dev *fsg)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
u32 lba; u32 lba;
struct fsg_buffhd *bh; struct fsg_buffhd *bh;
int rc; int rc;
...@@ -915,15 +922,15 @@ static int do_read(struct fsg_dev *fsg) ...@@ -915,15 +922,15 @@ static int do_read(struct fsg_dev *fsg)
/* Get the starting Logical Block Address and check that it's /* Get the starting Logical Block Address and check that it's
* not too big */ * not too big */
if (fsg->cmnd[0] == SC_READ_6) if (fsg->common->cmnd[0] == SC_READ_6)
lba = get_unaligned_be24(&fsg->cmnd[1]); lba = get_unaligned_be24(&fsg->common->cmnd[1]);
else { else {
lba = get_unaligned_be32(&fsg->cmnd[2]); lba = get_unaligned_be32(&fsg->common->cmnd[2]);
/* We allow DPO (Disable Page Out = don't save data in the /* We allow DPO (Disable Page Out = don't save data in the
* cache) and FUA (Force Unit Access = don't read from the * cache) and FUA (Force Unit Access = don't read from the
* cache), but we don't implement them. */ * cache), but we don't implement them. */
if ((fsg->cmnd[1] & ~0x18) != 0) { if ((fsg->common->cmnd[1] & ~0x18) != 0) {
curlun->sense_data = SS_INVALID_FIELD_IN_CDB; curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL; return -EINVAL;
} }
...@@ -958,7 +965,7 @@ static int do_read(struct fsg_dev *fsg) ...@@ -958,7 +965,7 @@ static int do_read(struct fsg_dev *fsg)
partial_page); partial_page);
/* Wait for the next buffer to become available */ /* Wait for the next buffer to become available */
bh = fsg->next_buffhd_to_fill; bh = fsg->common->next_buffhd_to_fill;
while (bh->state != BUF_STATE_EMPTY) { while (bh->state != BUF_STATE_EMPTY) {
rc = sleep_thread(fsg); rc = sleep_thread(fsg);
if (rc) if (rc)
...@@ -1018,7 +1025,7 @@ static int do_read(struct fsg_dev *fsg) ...@@ -1018,7 +1025,7 @@ static int do_read(struct fsg_dev *fsg)
bh->inreq->zero = 0; bh->inreq->zero = 0;
start_transfer(fsg, fsg->bulk_in, bh->inreq, start_transfer(fsg, fsg->bulk_in, bh->inreq,
&bh->inreq_busy, &bh->state); &bh->inreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next; fsg->common->next_buffhd_to_fill = bh->next;
} }
return -EIO; // No default reply return -EIO; // No default reply
...@@ -1029,7 +1036,7 @@ static int do_read(struct fsg_dev *fsg) ...@@ -1029,7 +1036,7 @@ static int do_read(struct fsg_dev *fsg)
static int do_write(struct fsg_dev *fsg) static int do_write(struct fsg_dev *fsg)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
u32 lba; u32 lba;
struct fsg_buffhd *bh; struct fsg_buffhd *bh;
int get_some_more; int get_some_more;
...@@ -1050,20 +1057,20 @@ static int do_write(struct fsg_dev *fsg) ...@@ -1050,20 +1057,20 @@ static int do_write(struct fsg_dev *fsg)
/* Get the starting Logical Block Address and check that it's /* Get the starting Logical Block Address and check that it's
* not too big */ * not too big */
if (fsg->cmnd[0] == SC_WRITE_6) if (fsg->common->cmnd[0] == SC_WRITE_6)
lba = get_unaligned_be24(&fsg->cmnd[1]); lba = get_unaligned_be24(&fsg->common->cmnd[1]);
else { else {
lba = get_unaligned_be32(&fsg->cmnd[2]); lba = get_unaligned_be32(&fsg->common->cmnd[2]);
/* We allow DPO (Disable Page Out = don't save data in the /* We allow DPO (Disable Page Out = don't save data in the
* cache) and FUA (Force Unit Access = write directly to the * cache) and FUA (Force Unit Access = write directly to the
* medium). We don't implement DPO; we implement FUA by * medium). We don't implement DPO; we implement FUA by
* performing synchronous output. */ * performing synchronous output. */
if ((fsg->cmnd[1] & ~0x18) != 0) { if ((fsg->common->cmnd[1] & ~0x18) != 0) {
curlun->sense_data = SS_INVALID_FIELD_IN_CDB; curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL; return -EINVAL;
} }
if (fsg->cmnd[1] & 0x08) { // FUA if (fsg->common->cmnd[1] & 0x08) { // FUA
spin_lock(&curlun->filp->f_lock); spin_lock(&curlun->filp->f_lock);
curlun->filp->f_flags |= O_SYNC; curlun->filp->f_flags |= O_SYNC;
spin_unlock(&curlun->filp->f_lock); spin_unlock(&curlun->filp->f_lock);
...@@ -1082,7 +1089,7 @@ static int do_write(struct fsg_dev *fsg) ...@@ -1082,7 +1089,7 @@ static int do_write(struct fsg_dev *fsg)
while (amount_left_to_write > 0) { while (amount_left_to_write > 0) {
/* Queue a request for more data from the host */ /* Queue a request for more data from the host */
bh = fsg->next_buffhd_to_fill; bh = fsg->common->next_buffhd_to_fill;
if (bh->state == BUF_STATE_EMPTY && get_some_more) { if (bh->state == BUF_STATE_EMPTY && get_some_more) {
/* Figure out how much we want to get: /* Figure out how much we want to get:
...@@ -1133,17 +1140,17 @@ static int do_write(struct fsg_dev *fsg) ...@@ -1133,17 +1140,17 @@ static int do_write(struct fsg_dev *fsg)
bh->outreq->short_not_ok = 1; bh->outreq->short_not_ok = 1;
start_transfer(fsg, fsg->bulk_out, bh->outreq, start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state); &bh->outreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next; fsg->common->next_buffhd_to_fill = bh->next;
continue; continue;
} }
/* Write the received data to the backing file */ /* Write the received data to the backing file */
bh = fsg->next_buffhd_to_drain; bh = fsg->common->next_buffhd_to_drain;
if (bh->state == BUF_STATE_EMPTY && !get_some_more) if (bh->state == BUF_STATE_EMPTY && !get_some_more)
break; // We stopped early break; // We stopped early
if (bh->state == BUF_STATE_FULL) { if (bh->state == BUF_STATE_FULL) {
smp_rmb(); smp_rmb();
fsg->next_buffhd_to_drain = bh->next; fsg->common->next_buffhd_to_drain = bh->next;
bh->state = BUF_STATE_EMPTY; bh->state = BUF_STATE_EMPTY;
/* Did something go wrong with the transfer? */ /* Did something go wrong with the transfer? */
...@@ -1218,7 +1225,7 @@ static int do_write(struct fsg_dev *fsg) ...@@ -1218,7 +1225,7 @@ static int do_write(struct fsg_dev *fsg)
static int do_synchronize_cache(struct fsg_dev *fsg) static int do_synchronize_cache(struct fsg_dev *fsg)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
int rc; int rc;
/* We ignore the requested LBA and write out all file's /* We ignore the requested LBA and write out all file's
...@@ -1244,10 +1251,10 @@ static void invalidate_sub(struct fsg_lun *curlun) ...@@ -1244,10 +1251,10 @@ static void invalidate_sub(struct fsg_lun *curlun)
static int do_verify(struct fsg_dev *fsg) static int do_verify(struct fsg_dev *fsg)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
u32 lba; u32 lba;
u32 verification_length; u32 verification_length;
struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill;
loff_t file_offset, file_offset_tmp; loff_t file_offset, file_offset_tmp;
u32 amount_left; u32 amount_left;
unsigned int amount; unsigned int amount;
...@@ -1255,7 +1262,7 @@ static int do_verify(struct fsg_dev *fsg) ...@@ -1255,7 +1262,7 @@ static int do_verify(struct fsg_dev *fsg)
/* Get the starting Logical Block Address and check that it's /* Get the starting Logical Block Address and check that it's
* not too big */ * not too big */
lba = get_unaligned_be32(&fsg->cmnd[2]); lba = get_unaligned_be32(&fsg->common->cmnd[2]);
if (lba >= curlun->num_sectors) { if (lba >= curlun->num_sectors) {
curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
return -EINVAL; return -EINVAL;
...@@ -1263,12 +1270,12 @@ static int do_verify(struct fsg_dev *fsg) ...@@ -1263,12 +1270,12 @@ static int do_verify(struct fsg_dev *fsg)
/* We allow DPO (Disable Page Out = don't save data in the /* We allow DPO (Disable Page Out = don't save data in the
* cache) but we don't implement it. */ * cache) but we don't implement it. */
if ((fsg->cmnd[1] & ~0x10) != 0) { if ((fsg->common->cmnd[1] & ~0x10) != 0) {
curlun->sense_data = SS_INVALID_FIELD_IN_CDB; curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL; return -EINVAL;
} }
verification_length = get_unaligned_be16(&fsg->cmnd[7]); verification_length = get_unaligned_be16(&fsg->common->cmnd[7]);
if (unlikely(verification_length == 0)) if (unlikely(verification_length == 0))
return -EIO; // No default reply return -EIO; // No default reply
...@@ -1348,7 +1355,7 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) ...@@ -1348,7 +1355,7 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
static char product_disk_id[] = "File-Stor Gadget"; static char product_disk_id[] = "File-Stor Gadget";
static char product_cdrom_id[] = "File-CD Gadget "; static char product_cdrom_id[] = "File-CD Gadget ";
if (!fsg->curlun) { // Unsupported LUNs are okay if (!fsg->common->curlun) { // Unsupported LUNs are okay
fsg->bad_lun_okay = 1; fsg->bad_lun_okay = 1;
memset(buf, 0, 36); memset(buf, 0, 36);
buf[0] = 0x7f; // Unsupported, no device-type buf[0] = 0x7f; // Unsupported, no device-type
...@@ -1374,7 +1381,7 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) ...@@ -1374,7 +1381,7 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
u8 *buf = (u8 *) bh->buf; u8 *buf = (u8 *) bh->buf;
u32 sd, sdinfo; u32 sd, sdinfo;
int valid; int valid;
...@@ -1428,9 +1435,9 @@ static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) ...@@ -1428,9 +1435,9 @@ static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
u32 lba = get_unaligned_be32(&fsg->cmnd[2]); u32 lba = get_unaligned_be32(&fsg->common->cmnd[2]);
int pmi = fsg->cmnd[8]; int pmi = fsg->common->cmnd[8];
u8 *buf = (u8 *) bh->buf; u8 *buf = (u8 *) bh->buf;
/* Check the PMI and LBA fields */ /* Check the PMI and LBA fields */
...@@ -1448,12 +1455,12 @@ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) ...@@ -1448,12 +1455,12 @@ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
int msf = fsg->cmnd[1] & 0x02; int msf = fsg->common->cmnd[1] & 0x02;
u32 lba = get_unaligned_be32(&fsg->cmnd[2]); u32 lba = get_unaligned_be32(&fsg->common->cmnd[2]);
u8 *buf = (u8 *) bh->buf; u8 *buf = (u8 *) bh->buf;
if ((fsg->cmnd[1] & ~0x02) != 0) { /* Mask away MSF */ if ((fsg->common->cmnd[1] & ~0x02) != 0) { /* Mask away MSF */
curlun->sense_data = SS_INVALID_FIELD_IN_CDB; curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL; return -EINVAL;
} }
...@@ -1471,12 +1478,12 @@ static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh) ...@@ -1471,12 +1478,12 @@ static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
int msf = fsg->cmnd[1] & 0x02; int msf = fsg->common->cmnd[1] & 0x02;
int start_track = fsg->cmnd[6]; int start_track = fsg->common->cmnd[6];
u8 *buf = (u8 *) bh->buf; u8 *buf = (u8 *) bh->buf;
if ((fsg->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ if ((fsg->common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */
start_track > 1) { start_track > 1) {
curlun->sense_data = SS_INVALID_FIELD_IN_CDB; curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL; return -EINVAL;
...@@ -1499,8 +1506,8 @@ static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh) ...@@ -1499,8 +1506,8 @@ static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
int mscmnd = fsg->cmnd[0]; int mscmnd = fsg->common->cmnd[0];
u8 *buf = (u8 *) bh->buf; u8 *buf = (u8 *) bh->buf;
u8 *buf0 = buf; u8 *buf0 = buf;
int pc, page_code; int pc, page_code;
...@@ -1508,12 +1515,12 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) ...@@ -1508,12 +1515,12 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
int valid_page = 0; int valid_page = 0;
int len, limit; int len, limit;
if ((fsg->cmnd[1] & ~0x08) != 0) { // Mask away DBD if ((fsg->common->cmnd[1] & ~0x08) != 0) { // Mask away DBD
curlun->sense_data = SS_INVALID_FIELD_IN_CDB; curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL; return -EINVAL;
} }
pc = fsg->cmnd[2] >> 6; pc = fsg->common->cmnd[2] >> 6;
page_code = fsg->cmnd[2] & 0x3f; page_code = fsg->common->cmnd[2] & 0x3f;
if (pc == 3) { if (pc == 3) {
curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
return -EINVAL; return -EINVAL;
...@@ -1581,7 +1588,7 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) ...@@ -1581,7 +1588,7 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
static int do_start_stop(struct fsg_dev *fsg) static int do_start_stop(struct fsg_dev *fsg)
{ {
if (!mod_data.removable) { if (!mod_data.removable) {
fsg->curlun->sense_data = SS_INVALID_COMMAND; fsg->common->curlun->sense_data = SS_INVALID_COMMAND;
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
...@@ -1590,7 +1597,7 @@ static int do_start_stop(struct fsg_dev *fsg) ...@@ -1590,7 +1597,7 @@ static int do_start_stop(struct fsg_dev *fsg)
static int do_prevent_allow(struct fsg_dev *fsg) static int do_prevent_allow(struct fsg_dev *fsg)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
int prevent; int prevent;
if (!mod_data.removable) { if (!mod_data.removable) {
...@@ -1598,8 +1605,8 @@ static int do_prevent_allow(struct fsg_dev *fsg) ...@@ -1598,8 +1605,8 @@ static int do_prevent_allow(struct fsg_dev *fsg)
return -EINVAL; return -EINVAL;
} }
prevent = fsg->cmnd[4] & 0x01; prevent = fsg->common->cmnd[4] & 0x01;
if ((fsg->cmnd[4] & ~0x01) != 0) { // Mask away Prevent if ((fsg->common->cmnd[4] & ~0x01) != 0) { // Mask away Prevent
curlun->sense_data = SS_INVALID_FIELD_IN_CDB; curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL; return -EINVAL;
} }
...@@ -1614,7 +1621,7 @@ static int do_prevent_allow(struct fsg_dev *fsg) ...@@ -1614,7 +1621,7 @@ static int do_prevent_allow(struct fsg_dev *fsg)
static int do_read_format_capacities(struct fsg_dev *fsg, static int do_read_format_capacities(struct fsg_dev *fsg,
struct fsg_buffhd *bh) struct fsg_buffhd *bh)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
u8 *buf = (u8 *) bh->buf; u8 *buf = (u8 *) bh->buf;
buf[0] = buf[1] = buf[2] = 0; buf[0] = buf[1] = buf[2] = 0;
...@@ -1631,7 +1638,7 @@ static int do_read_format_capacities(struct fsg_dev *fsg, ...@@ -1631,7 +1638,7 @@ static int do_read_format_capacities(struct fsg_dev *fsg,
static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh) static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
/* We don't support MODE SELECT */ /* We don't support MODE SELECT */
curlun->sense_data = SS_INVALID_COMMAND; curlun->sense_data = SS_INVALID_COMMAND;
...@@ -1688,7 +1695,7 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) ...@@ -1688,7 +1695,7 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
static int pad_with_zeros(struct fsg_dev *fsg) static int pad_with_zeros(struct fsg_dev *fsg)
{ {
struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill;
u32 nkeep = bh->inreq->length; u32 nkeep = bh->inreq->length;
u32 nsend; u32 nsend;
int rc; int rc;
...@@ -1710,7 +1717,7 @@ static int pad_with_zeros(struct fsg_dev *fsg) ...@@ -1710,7 +1717,7 @@ static int pad_with_zeros(struct fsg_dev *fsg)
bh->inreq->zero = 0; bh->inreq->zero = 0;
start_transfer(fsg, fsg->bulk_in, bh->inreq, start_transfer(fsg, fsg->bulk_in, bh->inreq,
&bh->inreq_busy, &bh->state); &bh->inreq_busy, &bh->state);
bh = fsg->next_buffhd_to_fill = bh->next; bh = fsg->common->next_buffhd_to_fill = bh->next;
fsg->usb_amount_left -= nsend; fsg->usb_amount_left -= nsend;
nkeep = 0; nkeep = 0;
} }
...@@ -1723,14 +1730,15 @@ static int throw_away_data(struct fsg_dev *fsg) ...@@ -1723,14 +1730,15 @@ static int throw_away_data(struct fsg_dev *fsg)
u32 amount; u32 amount;
int rc; int rc;
while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY || for (bh = fsg->common->next_buffhd_to_drain;
fsg->usb_amount_left > 0) { bh->state != BUF_STATE_EMPTY || fsg->usb_amount_left > 0;
bh = fsg->common->next_buffhd_to_drain) {
/* Throw away the data in a filled buffer */ /* Throw away the data in a filled buffer */
if (bh->state == BUF_STATE_FULL) { if (bh->state == BUF_STATE_FULL) {
smp_rmb(); smp_rmb();
bh->state = BUF_STATE_EMPTY; bh->state = BUF_STATE_EMPTY;
fsg->next_buffhd_to_drain = bh->next; fsg->common->next_buffhd_to_drain = bh->next;
/* A short packet or an error ends everything */ /* A short packet or an error ends everything */
if (bh->outreq->actual != bh->outreq->length || if (bh->outreq->actual != bh->outreq->length ||
...@@ -1742,7 +1750,7 @@ static int throw_away_data(struct fsg_dev *fsg) ...@@ -1742,7 +1750,7 @@ static int throw_away_data(struct fsg_dev *fsg)
} }
/* Try to submit another request if we need one */ /* Try to submit another request if we need one */
bh = fsg->next_buffhd_to_fill; bh = fsg->common->next_buffhd_to_fill;
if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) { if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
amount = min(fsg->usb_amount_left, FSG_BUFLEN); amount = min(fsg->usb_amount_left, FSG_BUFLEN);
...@@ -1753,7 +1761,7 @@ static int throw_away_data(struct fsg_dev *fsg) ...@@ -1753,7 +1761,7 @@ static int throw_away_data(struct fsg_dev *fsg)
bh->outreq->short_not_ok = 1; bh->outreq->short_not_ok = 1;
start_transfer(fsg, fsg->bulk_out, bh->outreq, start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state); &bh->outreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next; fsg->common->next_buffhd_to_fill = bh->next;
fsg->usb_amount_left -= amount; fsg->usb_amount_left -= amount;
continue; continue;
} }
...@@ -1769,7 +1777,7 @@ static int throw_away_data(struct fsg_dev *fsg) ...@@ -1769,7 +1777,7 @@ static int throw_away_data(struct fsg_dev *fsg)
static int finish_reply(struct fsg_dev *fsg) static int finish_reply(struct fsg_dev *fsg)
{ {
struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill;
int rc = 0; int rc = 0;
switch (fsg->data_dir) { switch (fsg->data_dir) {
...@@ -1797,7 +1805,7 @@ static int finish_reply(struct fsg_dev *fsg) ...@@ -1797,7 +1805,7 @@ static int finish_reply(struct fsg_dev *fsg)
bh->inreq->zero = 0; bh->inreq->zero = 0;
start_transfer(fsg, fsg->bulk_in, bh->inreq, start_transfer(fsg, fsg->bulk_in, bh->inreq,
&bh->inreq_busy, &bh->state); &bh->inreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next; fsg->common->next_buffhd_to_fill = bh->next;
/* For Bulk-only, if we're allowed to stall then send the /* For Bulk-only, if we're allowed to stall then send the
* short packet and halt the bulk-in endpoint. If we can't * short packet and halt the bulk-in endpoint. If we can't
...@@ -1806,7 +1814,7 @@ static int finish_reply(struct fsg_dev *fsg) ...@@ -1806,7 +1814,7 @@ static int finish_reply(struct fsg_dev *fsg)
bh->inreq->zero = 1; bh->inreq->zero = 1;
start_transfer(fsg, fsg->bulk_in, bh->inreq, start_transfer(fsg, fsg->bulk_in, bh->inreq,
&bh->inreq_busy, &bh->state); &bh->inreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next; fsg->common->next_buffhd_to_fill = bh->next;
rc = halt_bulk_in_endpoint(fsg); rc = halt_bulk_in_endpoint(fsg);
} else { } else {
rc = pad_with_zeros(fsg); rc = pad_with_zeros(fsg);
...@@ -1851,7 +1859,7 @@ static int finish_reply(struct fsg_dev *fsg) ...@@ -1851,7 +1859,7 @@ static int finish_reply(struct fsg_dev *fsg)
static int send_status(struct fsg_dev *fsg) static int send_status(struct fsg_dev *fsg)
{ {
struct fsg_lun *curlun = fsg->curlun; struct fsg_lun *curlun = fsg->common->curlun;
struct fsg_buffhd *bh; struct fsg_buffhd *bh;
struct bulk_cs_wrap *csw; struct bulk_cs_wrap *csw;
int rc; int rc;
...@@ -1859,7 +1867,7 @@ static int send_status(struct fsg_dev *fsg) ...@@ -1859,7 +1867,7 @@ static int send_status(struct fsg_dev *fsg)
u32 sd, sdinfo = 0; u32 sd, sdinfo = 0;
/* Wait for the next buffer to become available */ /* Wait for the next buffer to become available */
bh = fsg->next_buffhd_to_fill; bh = fsg->common->next_buffhd_to_fill;
while (bh->state != BUF_STATE_EMPTY) { while (bh->state != BUF_STATE_EMPTY) {
rc = sleep_thread(fsg); rc = sleep_thread(fsg);
if (rc) if (rc)
...@@ -1900,7 +1908,7 @@ static int send_status(struct fsg_dev *fsg) ...@@ -1900,7 +1908,7 @@ static int send_status(struct fsg_dev *fsg)
start_transfer(fsg, fsg->bulk_in, bh->inreq, start_transfer(fsg, fsg->bulk_in, bh->inreq,
&bh->inreq_busy, &bh->state); &bh->inreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next; fsg->common->next_buffhd_to_fill = bh->next;
return 0; return 0;
} }
...@@ -1914,7 +1922,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, ...@@ -1914,7 +1922,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
int needs_medium, const char *name) int needs_medium, const char *name)
{ {
int i; int i;
int lun = fsg->cmnd[1] >> 5; int lun = fsg->common->cmnd[1] >> 5;
static const char dirletter[4] = {'u', 'o', 'i', 'n'}; static const char dirletter[4] = {'u', 'o', 'i', 'n'};
char hdlen[20]; char hdlen[20];
struct fsg_lun *curlun; struct fsg_lun *curlun;
...@@ -1925,7 +1933,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, ...@@ -1925,7 +1933,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
fsg->data_size); fsg->data_size);
VDBG(fsg, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", VDBG(fsg, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n",
name, cmnd_size, dirletter[(int) data_dir], name, cmnd_size, dirletter[(int) data_dir],
fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen); fsg->data_size_from_cmnd, fsg->common->cmnd_size, hdlen);
/* We can't reply at all until we know the correct data direction /* We can't reply at all until we know the correct data direction
* and size. */ * and size. */
...@@ -1954,7 +1962,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, ...@@ -1954,7 +1962,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
} }
/* Verify the length of the command itself */ /* Verify the length of the command itself */
if (cmnd_size != fsg->cmnd_size) { if (cmnd_size != fsg->common->cmnd_size) {
/* Special case workaround: There are plenty of buggy SCSI /* Special case workaround: There are plenty of buggy SCSI
* implementations. Many have issues with cbw->Length * implementations. Many have issues with cbw->Length
...@@ -1968,11 +1976,11 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, ...@@ -1968,11 +1976,11 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
* REQUEST SENSE with cbw->Length == 10 where it should * REQUEST SENSE with cbw->Length == 10 where it should
* be 6 as well. * be 6 as well.
*/ */
if (cmnd_size <= fsg->cmnd_size) { if (cmnd_size <= fsg->common->cmnd_size) {
DBG(fsg, "%s is buggy! Expected length %d " DBG(fsg, "%s is buggy! Expected length %d "
"but we got %d\n", name, "but we got %d\n", name,
cmnd_size, fsg->cmnd_size); cmnd_size, fsg->common->cmnd_size);
cmnd_size = fsg->cmnd_size; cmnd_size = fsg->common->cmnd_size;
} else { } else {
fsg->phase_error = 1; fsg->phase_error = 1;
return -EINVAL; return -EINVAL;
...@@ -1980,27 +1988,27 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, ...@@ -1980,27 +1988,27 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
} }
/* Check that the LUN values are consistent */ /* Check that the LUN values are consistent */
if (fsg->lun != lun) if (fsg->common->lun != lun)
DBG(fsg, "using LUN %d from CBW, not LUN %d from CDB\n", DBG(fsg, "using LUN %d from CBW, not LUN %d from CDB\n",
fsg->lun, lun); fsg->common->lun, lun);
/* Check the LUN */ /* Check the LUN */
if (fsg->lun >= 0 && fsg->lun < fsg->nluns) { if (fsg->common->lun >= 0 && fsg->common->lun < fsg->common->nluns) {
fsg->curlun = curlun = &fsg->luns[fsg->lun]; fsg->common->curlun = curlun = &fsg->common->luns[fsg->common->lun];
if (fsg->cmnd[0] != SC_REQUEST_SENSE) { if (fsg->common->cmnd[0] != SC_REQUEST_SENSE) {
curlun->sense_data = SS_NO_SENSE; curlun->sense_data = SS_NO_SENSE;
curlun->sense_data_info = 0; curlun->sense_data_info = 0;
curlun->info_valid = 0; curlun->info_valid = 0;
} }
} else { } else {
fsg->curlun = curlun = NULL; fsg->common->curlun = curlun = NULL;
fsg->bad_lun_okay = 0; fsg->bad_lun_okay = 0;
/* INQUIRY and REQUEST SENSE commands are explicitly allowed /* INQUIRY and REQUEST SENSE commands are explicitly allowed
* to use unsupported LUNs; all others may not. */ * to use unsupported LUNs; all others may not. */
if (fsg->cmnd[0] != SC_INQUIRY && if (fsg->common->cmnd[0] != SC_INQUIRY &&
fsg->cmnd[0] != SC_REQUEST_SENSE) { fsg->common->cmnd[0] != SC_REQUEST_SENSE) {
DBG(fsg, "unsupported LUN %d\n", fsg->lun); DBG(fsg, "unsupported LUN %d\n", fsg->common->lun);
return -EINVAL; return -EINVAL;
} }
} }
...@@ -2008,17 +2016,17 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, ...@@ -2008,17 +2016,17 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
/* If a unit attention condition exists, only INQUIRY and /* If a unit attention condition exists, only INQUIRY and
* REQUEST SENSE commands are allowed; anything else must fail. */ * REQUEST SENSE commands are allowed; anything else must fail. */
if (curlun && curlun->unit_attention_data != SS_NO_SENSE && if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
fsg->cmnd[0] != SC_INQUIRY && fsg->common->cmnd[0] != SC_INQUIRY &&
fsg->cmnd[0] != SC_REQUEST_SENSE) { fsg->common->cmnd[0] != SC_REQUEST_SENSE) {
curlun->sense_data = curlun->unit_attention_data; curlun->sense_data = curlun->unit_attention_data;
curlun->unit_attention_data = SS_NO_SENSE; curlun->unit_attention_data = SS_NO_SENSE;
return -EINVAL; return -EINVAL;
} }
/* Check that only command bytes listed in the mask are non-zero */ /* Check that only command bytes listed in the mask are non-zero */
fsg->cmnd[1] &= 0x1f; // Mask away the LUN fsg->common->cmnd[1] &= 0x1f; // Mask away the LUN
for (i = 1; i < cmnd_size; ++i) { for (i = 1; i < cmnd_size; ++i) {
if (fsg->cmnd[i] && !(mask & (1 << i))) { if (fsg->common->cmnd[i] && !(mask & (1 << i))) {
if (curlun) if (curlun)
curlun->sense_data = SS_INVALID_FIELD_IN_CDB; curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL; return -EINVAL;
...@@ -2044,10 +2052,10 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2044,10 +2052,10 @@ static int do_scsi_command(struct fsg_dev *fsg)
int i; int i;
static char unknown[16]; static char unknown[16];
dump_cdb(fsg); dump_cdb(fsg->common);
/* Wait for the next buffer to become available for data or status */ /* Wait for the next buffer to become available for data or status */
bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill; bh = fsg->common->next_buffhd_to_drain = fsg->common->next_buffhd_to_fill;
while (bh->state != BUF_STATE_EMPTY) { while (bh->state != BUF_STATE_EMPTY) {
rc = sleep_thread(fsg); rc = sleep_thread(fsg);
if (rc) if (rc)
...@@ -2056,11 +2064,11 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2056,11 +2064,11 @@ static int do_scsi_command(struct fsg_dev *fsg)
fsg->phase_error = 0; fsg->phase_error = 0;
fsg->short_packet_received = 0; fsg->short_packet_received = 0;
down_read(&fsg->filesem); // We're using the backing file down_read(&fsg->common->filesem); // We're using the backing file
switch (fsg->cmnd[0]) { switch (fsg->common->cmnd[0]) {
case SC_INQUIRY: case SC_INQUIRY:
fsg->data_size_from_cmnd = fsg->cmnd[4]; fsg->data_size_from_cmnd = fsg->common->cmnd[4];
if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
(1<<4), 0, (1<<4), 0,
"INQUIRY")) == 0) "INQUIRY")) == 0)
...@@ -2068,7 +2076,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2068,7 +2076,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
break; break;
case SC_MODE_SELECT_6: case SC_MODE_SELECT_6:
fsg->data_size_from_cmnd = fsg->cmnd[4]; fsg->data_size_from_cmnd = fsg->common->cmnd[4];
if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
(1<<1) | (1<<4), 0, (1<<1) | (1<<4), 0,
"MODE SELECT(6)")) == 0) "MODE SELECT(6)")) == 0)
...@@ -2076,7 +2084,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2076,7 +2084,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
break; break;
case SC_MODE_SELECT_10: case SC_MODE_SELECT_10:
fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->common->cmnd[7]);
if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
(1<<1) | (3<<7), 0, (1<<1) | (3<<7), 0,
"MODE SELECT(10)")) == 0) "MODE SELECT(10)")) == 0)
...@@ -2084,7 +2092,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2084,7 +2092,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
break; break;
case SC_MODE_SENSE_6: case SC_MODE_SENSE_6:
fsg->data_size_from_cmnd = fsg->cmnd[4]; fsg->data_size_from_cmnd = fsg->common->cmnd[4];
if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
(1<<1) | (1<<2) | (1<<4), 0, (1<<1) | (1<<2) | (1<<4), 0,
"MODE SENSE(6)")) == 0) "MODE SENSE(6)")) == 0)
...@@ -2092,7 +2100,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2092,7 +2100,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
break; break;
case SC_MODE_SENSE_10: case SC_MODE_SENSE_10:
fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->common->cmnd[7]);
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
(1<<1) | (1<<2) | (3<<7), 0, (1<<1) | (1<<2) | (3<<7), 0,
"MODE SENSE(10)")) == 0) "MODE SENSE(10)")) == 0)
...@@ -2108,7 +2116,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2108,7 +2116,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
break; break;
case SC_READ_6: case SC_READ_6:
i = fsg->cmnd[4]; i = fsg->common->cmnd[4];
fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
(7<<1) | (1<<4), 1, (7<<1) | (1<<4), 1,
...@@ -2118,7 +2126,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2118,7 +2126,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
case SC_READ_10: case SC_READ_10:
fsg->data_size_from_cmnd = fsg->data_size_from_cmnd =
get_unaligned_be16(&fsg->cmnd[7]) << 9; get_unaligned_be16(&fsg->common->cmnd[7]) << 9;
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
(1<<1) | (0xf<<2) | (3<<7), 1, (1<<1) | (0xf<<2) | (3<<7), 1,
"READ(10)")) == 0) "READ(10)")) == 0)
...@@ -2127,7 +2135,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2127,7 +2135,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
case SC_READ_12: case SC_READ_12:
fsg->data_size_from_cmnd = fsg->data_size_from_cmnd =
get_unaligned_be32(&fsg->cmnd[6]) << 9; get_unaligned_be32(&fsg->common->cmnd[6]) << 9;
if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST, if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST,
(1<<1) | (0xf<<2) | (0xf<<6), 1, (1<<1) | (0xf<<2) | (0xf<<6), 1,
"READ(12)")) == 0) "READ(12)")) == 0)
...@@ -2145,7 +2153,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2145,7 +2153,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
case SC_READ_HEADER: case SC_READ_HEADER:
if (!mod_data.cdrom) if (!mod_data.cdrom)
goto unknown_cmnd; goto unknown_cmnd;
fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->common->cmnd[7]);
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
(3<<7) | (0x1f<<1), 1, (3<<7) | (0x1f<<1), 1,
"READ HEADER")) == 0) "READ HEADER")) == 0)
...@@ -2155,7 +2163,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2155,7 +2163,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
case SC_READ_TOC: case SC_READ_TOC:
if (!mod_data.cdrom) if (!mod_data.cdrom)
goto unknown_cmnd; goto unknown_cmnd;
fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->common->cmnd[7]);
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
(7<<6) | (1<<1), 1, (7<<6) | (1<<1), 1,
"READ TOC")) == 0) "READ TOC")) == 0)
...@@ -2163,7 +2171,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2163,7 +2171,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
break; break;
case SC_READ_FORMAT_CAPACITIES: case SC_READ_FORMAT_CAPACITIES:
fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->common->cmnd[7]);
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
(3<<7), 1, (3<<7), 1,
"READ FORMAT CAPACITIES")) == 0) "READ FORMAT CAPACITIES")) == 0)
...@@ -2171,7 +2179,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2171,7 +2179,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
break; break;
case SC_REQUEST_SENSE: case SC_REQUEST_SENSE:
fsg->data_size_from_cmnd = fsg->cmnd[4]; fsg->data_size_from_cmnd = fsg->common->cmnd[4];
if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
(1<<4), 0, (1<<4), 0,
"REQUEST SENSE")) == 0) "REQUEST SENSE")) == 0)
...@@ -2212,7 +2220,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2212,7 +2220,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
break; break;
case SC_WRITE_6: case SC_WRITE_6:
i = fsg->cmnd[4]; i = fsg->common->cmnd[4];
fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
(7<<1) | (1<<4), 1, (7<<1) | (1<<4), 1,
...@@ -2222,7 +2230,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2222,7 +2230,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
case SC_WRITE_10: case SC_WRITE_10:
fsg->data_size_from_cmnd = fsg->data_size_from_cmnd =
get_unaligned_be16(&fsg->cmnd[7]) << 9; get_unaligned_be16(&fsg->common->cmnd[7]) << 9;
if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
(1<<1) | (0xf<<2) | (3<<7), 1, (1<<1) | (0xf<<2) | (3<<7), 1,
"WRITE(10)")) == 0) "WRITE(10)")) == 0)
...@@ -2231,7 +2239,7 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2231,7 +2239,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
case SC_WRITE_12: case SC_WRITE_12:
fsg->data_size_from_cmnd = fsg->data_size_from_cmnd =
get_unaligned_be32(&fsg->cmnd[6]) << 9; get_unaligned_be32(&fsg->common->cmnd[6]) << 9;
if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST, if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST,
(1<<1) | (0xf<<2) | (0xf<<6), 1, (1<<1) | (0xf<<2) | (0xf<<6), 1,
"WRITE(12)")) == 0) "WRITE(12)")) == 0)
...@@ -2251,15 +2259,15 @@ static int do_scsi_command(struct fsg_dev *fsg) ...@@ -2251,15 +2259,15 @@ static int do_scsi_command(struct fsg_dev *fsg)
default: default:
unknown_cmnd: unknown_cmnd:
fsg->data_size_from_cmnd = 0; fsg->data_size_from_cmnd = 0;
sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); sprintf(unknown, "Unknown x%02x", fsg->common->cmnd[0]);
if ((reply = check_command(fsg, fsg->cmnd_size, if ((reply = check_command(fsg, fsg->common->cmnd_size,
DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) { DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) {
fsg->curlun->sense_data = SS_INVALID_COMMAND; fsg->common->curlun->sense_data = SS_INVALID_COMMAND;
reply = -EINVAL; reply = -EINVAL;
} }
break; break;
} }
up_read(&fsg->filesem); up_read(&fsg->common->filesem);
if (reply == -EINTR || signal_pending(current)) if (reply == -EINTR || signal_pending(current))
return -EINTR; return -EINTR;
...@@ -2328,8 +2336,8 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) ...@@ -2328,8 +2336,8 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
} }
/* Save the command for later */ /* Save the command for later */
fsg->cmnd_size = cbw->Length; fsg->common->cmnd_size = cbw->Length;
memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size); memcpy(fsg->common->cmnd, cbw->CDB, fsg->common->cmnd_size);
if (cbw->Flags & USB_BULK_IN_FLAG) if (cbw->Flags & USB_BULK_IN_FLAG)
fsg->data_dir = DATA_DIR_TO_HOST; fsg->data_dir = DATA_DIR_TO_HOST;
else else
...@@ -2337,7 +2345,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) ...@@ -2337,7 +2345,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
fsg->data_size = le32_to_cpu(cbw->DataTransferLength); fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
if (fsg->data_size == 0) if (fsg->data_size == 0)
fsg->data_dir = DATA_DIR_NONE; fsg->data_dir = DATA_DIR_NONE;
fsg->lun = cbw->Lun; fsg->common->lun = cbw->Lun;
fsg->tag = cbw->Tag; fsg->tag = cbw->Tag;
return 0; return 0;
} }
...@@ -2349,7 +2357,7 @@ static int get_next_command(struct fsg_dev *fsg) ...@@ -2349,7 +2357,7 @@ static int get_next_command(struct fsg_dev *fsg)
int rc = 0; int rc = 0;
/* Wait for the next buffer to become available */ /* Wait for the next buffer to become available */
bh = fsg->next_buffhd_to_fill; bh = fsg->common->next_buffhd_to_fill;
while (bh->state != BUF_STATE_EMPTY) { while (bh->state != BUF_STATE_EMPTY) {
rc = sleep_thread(fsg); rc = sleep_thread(fsg);
if (rc) if (rc)
...@@ -2421,7 +2429,7 @@ static int do_set_interface(struct fsg_dev *fsg, int altsetting) ...@@ -2421,7 +2429,7 @@ static int do_set_interface(struct fsg_dev *fsg, int altsetting)
reset: reset:
/* Deallocate the requests */ /* Deallocate the requests */
for (i = 0; i < FSG_NUM_BUFFERS; ++i) { for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
struct fsg_buffhd *bh = &fsg->buffhds[i]; struct fsg_buffhd *bh = &fsg->common->buffhds[i];
if (bh->inreq) { if (bh->inreq) {
usb_ep_free_request(fsg->bulk_in, bh->inreq); usb_ep_free_request(fsg->bulk_in, bh->inreq);
...@@ -2466,7 +2474,7 @@ reset: ...@@ -2466,7 +2474,7 @@ reset:
/* Allocate the requests */ /* Allocate the requests */
for (i = 0; i < FSG_NUM_BUFFERS; ++i) { for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
struct fsg_buffhd *bh = &fsg->buffhds[i]; struct fsg_buffhd *bh = &fsg->common->buffhds[i];
if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0) if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
goto reset; goto reset;
...@@ -2479,8 +2487,8 @@ reset: ...@@ -2479,8 +2487,8 @@ reset:
} }
fsg->running = 1; fsg->running = 1;
for (i = 0; i < fsg->nluns; ++i) for (i = 0; i < fsg->common->nluns; ++i)
fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; fsg->common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
return rc; return rc;
} }
...@@ -2532,7 +2540,6 @@ static void handle_exception(struct fsg_dev *fsg) ...@@ -2532,7 +2540,6 @@ static void handle_exception(struct fsg_dev *fsg)
siginfo_t info; siginfo_t info;
int sig; int sig;
int i; int i;
int num_active;
struct fsg_buffhd *bh; struct fsg_buffhd *bh;
enum fsg_state old_state; enum fsg_state old_state;
u8 new_config; u8 new_config;
...@@ -2555,7 +2562,7 @@ static void handle_exception(struct fsg_dev *fsg) ...@@ -2555,7 +2562,7 @@ static void handle_exception(struct fsg_dev *fsg)
/* Cancel all the pending transfers */ /* Cancel all the pending transfers */
for (i = 0; i < FSG_NUM_BUFFERS; ++i) { for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
bh = &fsg->buffhds[i]; bh = &fsg->common->buffhds[i];
if (bh->inreq_busy) if (bh->inreq_busy)
usb_ep_dequeue(fsg->bulk_in, bh->inreq); usb_ep_dequeue(fsg->bulk_in, bh->inreq);
if (bh->outreq_busy) if (bh->outreq_busy)
...@@ -2564,9 +2571,9 @@ static void handle_exception(struct fsg_dev *fsg) ...@@ -2564,9 +2571,9 @@ static void handle_exception(struct fsg_dev *fsg)
/* Wait until everything is idle */ /* Wait until everything is idle */
for (;;) { for (;;) {
num_active = 0; int num_active = 0;
for (i = 0; i < FSG_NUM_BUFFERS; ++i) { for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
bh = &fsg->buffhds[i]; bh = &fsg->common->buffhds[i];
num_active += bh->inreq_busy + bh->outreq_busy; num_active += bh->inreq_busy + bh->outreq_busy;
} }
if (num_active == 0) if (num_active == 0)
...@@ -2586,11 +2593,11 @@ static void handle_exception(struct fsg_dev *fsg) ...@@ -2586,11 +2593,11 @@ static void handle_exception(struct fsg_dev *fsg)
spin_lock_irq(&fsg->lock); spin_lock_irq(&fsg->lock);
for (i = 0; i < FSG_NUM_BUFFERS; ++i) { for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
bh = &fsg->buffhds[i]; bh = &fsg->common->buffhds[i];
bh->state = BUF_STATE_EMPTY; bh->state = BUF_STATE_EMPTY;
} }
fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain = fsg->common->next_buffhd_to_fill = fsg->common->next_buffhd_to_drain =
&fsg->buffhds[0]; &fsg->common->buffhds[0];
exception_req_tag = fsg->exception_req_tag; exception_req_tag = fsg->exception_req_tag;
new_config = fsg->new_config; new_config = fsg->new_config;
...@@ -2599,8 +2606,8 @@ static void handle_exception(struct fsg_dev *fsg) ...@@ -2599,8 +2606,8 @@ static void handle_exception(struct fsg_dev *fsg)
if (old_state == FSG_STATE_ABORT_BULK_OUT) if (old_state == FSG_STATE_ABORT_BULK_OUT)
fsg->state = FSG_STATE_STATUS_PHASE; fsg->state = FSG_STATE_STATUS_PHASE;
else { else {
for (i = 0; i < fsg->nluns; ++i) { for (i = 0; i < fsg->common->nluns; ++i) {
curlun = &fsg->luns[i]; curlun = &fsg->common->luns[i];
curlun->prevent_medium_removal = 0; curlun->prevent_medium_removal = 0;
curlun->sense_data = curlun->unit_attention_data = curlun->sense_data = curlun->unit_attention_data =
SS_NO_SENSE; SS_NO_SENSE;
...@@ -2637,8 +2644,8 @@ static void handle_exception(struct fsg_dev *fsg) ...@@ -2637,8 +2644,8 @@ static void handle_exception(struct fsg_dev *fsg)
/* Technically this should go here, but it would only be /* Technically this should go here, but it would only be
* a waste of time. Ditto for the INTERFACE_CHANGE and * a waste of time. Ditto for the INTERFACE_CHANGE and
* CONFIG_CHANGE cases. */ * CONFIG_CHANGE cases. */
// for (i = 0; i < fsg->nluns; ++i) // for (i = 0; i < fsg->common->nluns; ++i)
// fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; // fsg->common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
break; break;
case FSG_STATE_INTERFACE_CHANGE: case FSG_STATE_INTERFACE_CHANGE:
...@@ -2662,8 +2669,8 @@ static void handle_exception(struct fsg_dev *fsg) ...@@ -2662,8 +2669,8 @@ static void handle_exception(struct fsg_dev *fsg)
break; break;
case FSG_STATE_DISCONNECT: case FSG_STATE_DISCONNECT:
for (i = 0; i < fsg->nluns; ++i) for (i = 0; i < fsg->common->nluns; ++i)
fsg_lun_fsync_sub(fsg->luns + i); fsg_lun_fsync_sub(&fsg->common->luns[i]);
do_set_config(fsg, 0); // Unconfigured state do_set_config(fsg, 0); // Unconfigured state
break; break;
...@@ -2760,21 +2767,14 @@ static DEVICE_ATTR(file, 0444, fsg_show_file, NULL); ...@@ -2760,21 +2767,14 @@ static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void fsg_release(struct kref *ref) static void fsg_release(struct fsg_dev *fsg)
{ {
struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref); kfree(fsg->common->luns);
kfree(fsg->luns);
kfree(fsg); kfree(fsg);
} }
static void lun_release(struct device *dev) static void lun_release(struct device *dev)
{ {
struct rw_semaphore *filesem = dev_get_drvdata(dev);
struct fsg_dev *fsg =
container_of(filesem, struct fsg_dev, filesem);
kref_put(&fsg->ref, fsg_release);
} }
static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
...@@ -2788,8 +2788,8 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) ...@@ -2788,8 +2788,8 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
clear_bit(REGISTERED, &fsg->atomic_bitflags); clear_bit(REGISTERED, &fsg->atomic_bitflags);
/* Unregister the sysfs attribute files and the LUNs */ /* Unregister the sysfs attribute files and the LUNs */
for (i = 0; i < fsg->nluns; ++i) { for (i = 0; i < fsg->common->nluns; ++i) {
curlun = &fsg->luns[i]; curlun = &fsg->common->luns[i];
if (curlun->registered) { if (curlun->registered) {
device_remove_file(&curlun->dev, &dev_attr_ro); device_remove_file(&curlun->dev, &dev_attr_ro);
device_remove_file(&curlun->dev, &dev_attr_file); device_remove_file(&curlun->dev, &dev_attr_file);
...@@ -2810,7 +2810,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) ...@@ -2810,7 +2810,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
/* Free the data buffers */ /* Free the data buffers */
for (i = 0; i < FSG_NUM_BUFFERS; ++i) for (i = 0; i < FSG_NUM_BUFFERS; ++i)
kfree(fsg->buffhds[i].buf); kfree(fsg->common->buffhds[i].buf);
/* Free the request and buffer for endpoint 0 */ /* Free the request and buffer for endpoint 0 */
if (req) { if (req) {
...@@ -2891,15 +2891,15 @@ static int __init fsg_bind(struct usb_gadget *gadget) ...@@ -2891,15 +2891,15 @@ static int __init fsg_bind(struct usb_gadget *gadget)
/* Create the LUNs, open their backing files, and register the /* Create the LUNs, open their backing files, and register the
* LUN devices in sysfs. */ * LUN devices in sysfs. */
fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL); fsg->common->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL);
if (!fsg->luns) { if (!fsg->common->luns) {
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
} }
fsg->nluns = i; fsg->common->nluns = i;
for (i = 0; i < fsg->nluns; ++i) { for (i = 0; i < fsg->common->nluns; ++i) {
curlun = &fsg->luns[i]; curlun = &fsg->common->luns[i];
curlun->cdrom = !!mod_data.cdrom; curlun->cdrom = !!mod_data.cdrom;
curlun->ro = mod_data.cdrom || mod_data.ro[i]; curlun->ro = mod_data.cdrom || mod_data.ro[i];
curlun->initially_ro = curlun->ro; curlun->initially_ro = curlun->ro;
...@@ -2907,7 +2907,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) ...@@ -2907,7 +2907,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
curlun->dev.release = lun_release; curlun->dev.release = lun_release;
curlun->dev.parent = &gadget->dev; curlun->dev.parent = &gadget->dev;
curlun->dev.driver = &fsg_driver.driver; curlun->dev.driver = &fsg_driver.driver;
dev_set_drvdata(&curlun->dev, &fsg->filesem); dev_set_drvdata(&curlun->dev, &fsg->common->filesem);
dev_set_name(&curlun->dev,"%s-lun%d", dev_set_name(&curlun->dev,"%s-lun%d",
dev_name(&gadget->dev), i); dev_name(&gadget->dev), i);
...@@ -2923,7 +2923,6 @@ static int __init fsg_bind(struct usb_gadget *gadget) ...@@ -2923,7 +2923,6 @@ static int __init fsg_bind(struct usb_gadget *gadget)
goto out; goto out;
} }
curlun->registered = 1; curlun->registered = 1;
kref_get(&fsg->ref);
if (mod_data.file[i] && *mod_data.file[i]) { if (mod_data.file[i] && *mod_data.file[i]) {
if ((rc = fsg_lun_open(curlun, if ((rc = fsg_lun_open(curlun,
...@@ -2981,7 +2980,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) ...@@ -2981,7 +2980,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
/* Allocate the data buffers */ /* Allocate the data buffers */
for (i = 0; i < FSG_NUM_BUFFERS; ++i) { for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
struct fsg_buffhd *bh = &fsg->buffhds[i]; struct fsg_buffhd *bh = &fsg->common->buffhds[i];
/* Allocate for the bulk-in endpoint. We assume that /* Allocate for the bulk-in endpoint. We assume that
* the buffer will also work with the bulk-out (and * the buffer will also work with the bulk-out (and
...@@ -2991,7 +2990,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) ...@@ -2991,7 +2990,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
goto out; goto out;
bh->next = bh + 1; bh->next = bh + 1;
} }
fsg->buffhds[FSG_NUM_BUFFERS - 1].next = &fsg->buffhds[0]; fsg->common->buffhds[FSG_NUM_BUFFERS - 1].next = &fsg->common->buffhds[0];
/* This should reflect the actual gadget power source */ /* This should reflect the actual gadget power source */
usb_gadget_set_selfpowered(gadget); usb_gadget_set_selfpowered(gadget);
...@@ -3019,11 +3018,11 @@ static int __init fsg_bind(struct usb_gadget *gadget) ...@@ -3019,11 +3018,11 @@ static int __init fsg_bind(struct usb_gadget *gadget)
} }
INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
INFO(fsg, "Number of LUNs=%d\n", fsg->nluns); INFO(fsg, "Number of LUNs=%d\n", fsg->common->nluns);
pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
for (i = 0; i < fsg->nluns; ++i) { for (i = 0; i < fsg->common->nluns; ++i) {
curlun = &fsg->luns[i]; curlun = &fsg->common->luns[i];
if (fsg_lun_is_open(curlun)) { if (fsg_lun_is_open(curlun)) {
p = NULL; p = NULL;
if (pathbuf) { if (pathbuf) {
...@@ -3092,9 +3091,15 @@ static int __init fsg_alloc(void) ...@@ -3092,9 +3091,15 @@ static int __init fsg_alloc(void)
fsg = kzalloc(sizeof *fsg, GFP_KERNEL); fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
if (!fsg) if (!fsg)
return -ENOMEM; return -ENOMEM;
fsg->common = kzalloc(sizeof *fsg->common, GFP_KERNEL);
if (!fsg->common) {
kfree(fsg);
return -ENOMEM;
}
spin_lock_init(&fsg->lock); spin_lock_init(&fsg->lock);
init_rwsem(&fsg->filesem); init_rwsem(&fsg->common->filesem);
kref_init(&fsg->ref);
init_completion(&fsg->thread_notifier); init_completion(&fsg->thread_notifier);
the_fsg = fsg; the_fsg = fsg;
...@@ -3111,7 +3116,7 @@ static int __init fsg_init(void) ...@@ -3111,7 +3116,7 @@ static int __init fsg_init(void)
return rc; return rc;
fsg = the_fsg; fsg = the_fsg;
if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
kref_put(&fsg->ref, fsg_release); fsg_release(fsg);
return rc; return rc;
} }
module_init(fsg_init); module_init(fsg_init);
...@@ -3128,6 +3133,6 @@ static void __exit fsg_cleanup(void) ...@@ -3128,6 +3133,6 @@ static void __exit fsg_cleanup(void)
/* Wait for the thread to finish up */ /* Wait for the thread to finish up */
wait_for_completion(&fsg->thread_notifier); wait_for_completion(&fsg->thread_notifier);
kref_put(&fsg->ref, fsg_release); fsg_release(fsg);
} }
module_exit(fsg_cleanup); module_exit(fsg_cleanup);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment