usb: gadget: storage: make FSG_NUM_BUFFERS variable size
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / usb / gadget / file_storage.c
index 639e14a..4b9797d 100644 (file)
@@ -69,8 +69,7 @@
  * each LUN would be settable independently as a disk drive or a CD-ROM
  * drive, but currently all LUNs have to be the same type.  The CD-ROM
  * emulation includes a single data track and no audio tracks; hence there
- * need be only one backing file per LUN.  Note also that the CD-ROM block
- * length is set to 512 rather than the more common value 2048.
+ * need be only one backing file per LUN.
  *
  * Requirements are modest; only a bulk-in and a bulk-out endpoint are
  * needed (an interrupt-out endpoint is also needed for CBI).  The memory
@@ -461,7 +460,6 @@ struct fsg_dev {
 
        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;
        struct completion       thread_notifier;
@@ -488,6 +486,8 @@ struct fsg_dev {
        unsigned int            nluns;
        struct fsg_lun          *luns;
        struct fsg_lun          *curlun;
+       /* Must be the last entry */
+       struct fsg_buffhd       buffhds[];
 };
 
 typedef void (*fsg_routine_t)(struct fsg_dev *);
@@ -1136,7 +1136,6 @@ static int do_read(struct fsg_dev *fsg)
        u32                     amount_left;
        loff_t                  file_offset, file_offset_tmp;
        unsigned int            amount;
-       unsigned int            partial_page;
        ssize_t                 nread;
 
        /* Get the starting Logical Block Address and check that it's
@@ -1158,7 +1157,7 @@ static int do_read(struct fsg_dev *fsg)
                curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
                return -EINVAL;
        }
-       file_offset = ((loff_t) lba) << 9;
+       file_offset = ((loff_t) lba) << curlun->blkbits;
 
        /* Carry out the file reads */
        amount_left = fsg->data_size_from_cmnd;
@@ -1171,17 +1170,10 @@ static int do_read(struct fsg_dev *fsg)
                 * Try to read the remaining amount.
                 * But don't read more than the buffer size.
                 * And don't try to read past the end of the file.
-                * Finally, if we're not at a page boundary, don't read past
-                *      the next page.
-                * If this means reading 0 then we were asked to read past
-                *      the end of file. */
+                */
                amount = min((unsigned int) amount_left, mod_data.buflen);
                amount = min((loff_t) amount,
                                curlun->file_length - file_offset);
-               partial_page = file_offset & (PAGE_CACHE_SIZE - 1);
-               if (partial_page > 0)
-                       amount = min(amount, (unsigned int) PAGE_CACHE_SIZE -
-                                       partial_page);
 
                /* Wait for the next buffer to become available */
                bh = fsg->next_buffhd_to_fill;
@@ -1196,7 +1188,7 @@ static int do_read(struct fsg_dev *fsg)
                if (amount == 0) {
                        curlun->sense_data =
                                        SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-                       curlun->sense_data_info = file_offset >> 9;
+                       curlun->sense_data_info = file_offset >> curlun->blkbits;
                        curlun->info_valid = 1;
                        bh->inreq->length = 0;
                        bh->state = BUF_STATE_FULL;
@@ -1221,18 +1213,23 @@ static int do_read(struct fsg_dev *fsg)
                } else if (nread < amount) {
                        LDBG(curlun, "partial file read: %d/%u\n",
                                        (int) nread, amount);
-                       nread -= (nread & 511); // Round down to a block
+                       nread = round_down(nread, curlun->blksize);
                }
                file_offset  += nread;
                amount_left  -= nread;
                fsg->residue -= nread;
+
+               /* Except at the end of the transfer, nread will be
+                * equal to the buffer size, which is divisible by the
+                * bulk-in maxpacket size.
+                */
                bh->inreq->length = nread;
                bh->state = BUF_STATE_FULL;
 
                /* If an error occurred, report it and its position */
                if (nread < amount) {
                        curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
-                       curlun->sense_data_info = file_offset >> 9;
+                       curlun->sense_data_info = file_offset >> curlun->blkbits;
                        curlun->info_valid = 1;
                        break;
                }
@@ -1262,7 +1259,6 @@ static int do_write(struct fsg_dev *fsg)
        u32                     amount_left_to_req, amount_left_to_write;
        loff_t                  usb_offset, file_offset, file_offset_tmp;
        unsigned int            amount;
-       unsigned int            partial_page;
        ssize_t                 nwritten;
        int                     rc;
 
@@ -1303,7 +1299,7 @@ static int do_write(struct fsg_dev *fsg)
 
        /* Carry out the file writes */
        get_some_more = 1;
-       file_offset = usb_offset = ((loff_t) lba) << 9;
+       file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
        amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
 
        while (amount_left_to_write > 0) {
@@ -1313,38 +1309,20 @@ static int do_write(struct fsg_dev *fsg)
                if (bh->state == BUF_STATE_EMPTY && get_some_more) {
 
                        /* Figure out how much we want to get:
-                        * Try to get the remaining amount.
-                        * But don't get more than the buffer size.
-                        * And don't try to go past the end of the file.
-                        * If we're not at a page boundary,
-                        *      don't go past the next page.
-                        * If this means getting 0, then we were asked
-                        *      to write past the end of file.
-                        * Finally, round down to a block boundary. */
+                        * Try to get the remaining amount,
+                        * but not more than the buffer size.
+                        */
                        amount = min(amount_left_to_req, mod_data.buflen);
-                       amount = min((loff_t) amount, curlun->file_length -
-                                       usb_offset);
-                       partial_page = usb_offset & (PAGE_CACHE_SIZE - 1);
-                       if (partial_page > 0)
-                               amount = min(amount,
-       (unsigned int) PAGE_CACHE_SIZE - partial_page);
-
-                       if (amount == 0) {
+
+                       /* Beyond the end of the backing file? */
+                       if (usb_offset >= curlun->file_length) {
                                get_some_more = 0;
                                curlun->sense_data =
                                        SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-                               curlun->sense_data_info = usb_offset >> 9;
+                               curlun->sense_data_info = usb_offset >> curlun->blkbits;
                                curlun->info_valid = 1;
                                continue;
                        }
-                       amount -= (amount & 511);
-                       if (amount == 0) {
-
-                               /* Why were we were asked to transfer a
-                                * partial block? */
-                               get_some_more = 0;
-                               continue;
-                       }
 
                        /* Get the next buffer */
                        usb_offset += amount;
@@ -1353,8 +1331,10 @@ static int do_write(struct fsg_dev *fsg)
                        if (amount_left_to_req == 0)
                                get_some_more = 0;
 
-                       /* amount is always divisible by 512, hence by
-                        * the bulk-out maxpacket size */
+                       /* Except at the end of the transfer, amount will be
+                        * equal to the buffer size, which is divisible by
+                        * the bulk-out maxpacket size.
+                        */
                        bh->outreq->length = bh->bulk_out_intended_length =
                                        amount;
                        bh->outreq->short_not_ok = 1;
@@ -1376,7 +1356,7 @@ static int do_write(struct fsg_dev *fsg)
                        /* Did something go wrong with the transfer? */
                        if (bh->outreq->status != 0) {
                                curlun->sense_data = SS_COMMUNICATION_FAILURE;
-                               curlun->sense_data_info = file_offset >> 9;
+                               curlun->sense_data_info = file_offset >> curlun->blkbits;
                                curlun->info_valid = 1;
                                break;
                        }
@@ -1390,6 +1370,11 @@ static int do_write(struct fsg_dev *fsg)
                                amount = curlun->file_length - file_offset;
                        }
 
+                       /* Don't write a partial block */
+                       amount = round_down(amount, curlun->blksize);
+                       if (amount == 0)
+                               goto empty_write;
+
                        /* Perform the write */
                        file_offset_tmp = file_offset;
                        nwritten = vfs_write(curlun->filp,
@@ -1408,8 +1393,7 @@ static int do_write(struct fsg_dev *fsg)
                        } else if (nwritten < amount) {
                                LDBG(curlun, "partial file write: %d/%u\n",
                                                (int) nwritten, amount);
-                               nwritten -= (nwritten & 511);
-                                               // Round down to a block
+                               nwritten = round_down(nwritten, curlun->blksize);
                        }
                        file_offset += nwritten;
                        amount_left_to_write -= nwritten;
@@ -1418,11 +1402,12 @@ static int do_write(struct fsg_dev *fsg)
                        /* If an error occurred, report it and its position */
                        if (nwritten < amount) {
                                curlun->sense_data = SS_WRITE_ERROR;
-                               curlun->sense_data_info = file_offset >> 9;
+                               curlun->sense_data_info = file_offset >> curlun->blkbits;
                                curlun->info_valid = 1;
                                break;
                        }
 
+ empty_write:
                        /* Did the host decide to stop early? */
                        if (bh->outreq->actual != bh->outreq->length) {
                                fsg->short_packet_received = 1;
@@ -1500,8 +1485,8 @@ static int do_verify(struct fsg_dev *fsg)
                return -EIO;            // No default reply
 
        /* Prepare to carry out the file verify */
-       amount_left = verification_length << 9;
-       file_offset = ((loff_t) lba) << 9;
+       amount_left = verification_length << curlun->blkbits;
+       file_offset = ((loff_t) lba) << curlun->blkbits;
 
        /* Write out all the dirty buffers before invalidating them */
        fsg_lun_fsync_sub(curlun);
@@ -1519,15 +1504,14 @@ static int do_verify(struct fsg_dev *fsg)
                 * Try to read the remaining amount, but not more than
                 * the buffer size.
                 * And don't try to read past the end of the file.
-                * If this means reading 0 then we were asked to read
-                * past the end of file. */
+                */
                amount = min((unsigned int) amount_left, mod_data.buflen);
                amount = min((loff_t) amount,
                                curlun->file_length - file_offset);
                if (amount == 0) {
                        curlun->sense_data =
                                        SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
-                       curlun->sense_data_info = file_offset >> 9;
+                       curlun->sense_data_info = file_offset >> curlun->blkbits;
                        curlun->info_valid = 1;
                        break;
                }
@@ -1550,11 +1534,11 @@ static int do_verify(struct fsg_dev *fsg)
                } else if (nread < amount) {
                        LDBG(curlun, "partial file verify: %d/%u\n",
                                        (int) nread, amount);
-                       nread -= (nread & 511); // Round down to a sector
+                       nread = round_down(nread, curlun->blksize);
                }
                if (nread == 0) {
                        curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
-                       curlun->sense_data_info = file_offset >> 9;
+                       curlun->sense_data_info = file_offset >> curlun->blkbits;
                        curlun->info_valid = 1;
                        break;
                }
@@ -1668,7 +1652,7 @@ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 
        put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
                                                /* Max logical block */
-       put_unaligned_be32(512, &buf[4]);       /* Block length */
+       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
        return 8;
 }
 
@@ -1890,7 +1874,7 @@ static int do_read_format_capacities(struct fsg_dev *fsg,
 
        put_unaligned_be32(curlun->num_sectors, &buf[0]);
                                                /* Number of blocks */
-       put_unaligned_be32(512, &buf[4]);       /* Block length */
+       put_unaligned_be32(curlun->blksize, &buf[4]);   /* Block length */
        buf[4] = 0x02;                          /* Current capacity */
        return 12;
 }
@@ -1983,8 +1967,10 @@ static int throw_away_data(struct fsg_dev *fsg)
                        amount = min(fsg->usb_amount_left,
                                        (u32) mod_data.buflen);
 
-                       /* amount is always divisible by 512, hence by
-                        * the bulk-out maxpacket size */
+                       /* Except at the end of the transfer, amount will be
+                        * equal to the buffer size, which is divisible by
+                        * the bulk-out maxpacket size.
+                        */
                        bh->outreq->length = bh->bulk_out_intended_length =
                                        amount;
                        bh->outreq->short_not_ok = 1;
@@ -2415,7 +2401,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
 
        case READ_6:
                i = fsg->cmnd[4];
-               fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
+               fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << fsg->curlun->blkbits;
                if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
                                (7<<1) | (1<<4), 1,
                                "READ(6)")) == 0)
@@ -2424,7 +2410,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
 
        case READ_10:
                fsg->data_size_from_cmnd =
-                               get_unaligned_be16(&fsg->cmnd[7]) << 9;
+                               get_unaligned_be16(&fsg->cmnd[7]) << fsg->curlun->blkbits;
                if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
                                (1<<1) | (0xf<<2) | (3<<7), 1,
                                "READ(10)")) == 0)
@@ -2433,7 +2419,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
 
        case READ_12:
                fsg->data_size_from_cmnd =
-                               get_unaligned_be32(&fsg->cmnd[6]) << 9;
+                               get_unaligned_be32(&fsg->cmnd[6]) << fsg->curlun->blkbits;
                if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST,
                                (1<<1) | (0xf<<2) | (0xf<<6), 1,
                                "READ(12)")) == 0)
@@ -2519,7 +2505,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
 
        case WRITE_6:
                i = fsg->cmnd[4];
-               fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
+               fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << fsg->curlun->blkbits;
                if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
                                (7<<1) | (1<<4), 1,
                                "WRITE(6)")) == 0)
@@ -2528,7 +2514,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
 
        case WRITE_10:
                fsg->data_size_from_cmnd =
-                               get_unaligned_be16(&fsg->cmnd[7]) << 9;
+                               get_unaligned_be16(&fsg->cmnd[7]) << fsg->curlun->blkbits;
                if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
                                (1<<1) | (0xf<<2) | (3<<7), 1,
                                "WRITE(10)")) == 0)
@@ -2537,7 +2523,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
 
        case WRITE_12:
                fsg->data_size_from_cmnd =
-                               get_unaligned_be32(&fsg->cmnd[6]) << 9;
+                               get_unaligned_be32(&fsg->cmnd[6]) << fsg->curlun->blkbits;
                if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST,
                                (1<<1) | (0xf<<2) | (0xf<<6), 1,
                                "WRITE(12)")) == 0)
@@ -2752,7 +2738,7 @@ static int do_set_interface(struct fsg_dev *fsg, int altsetting)
 
 reset:
        /* 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];
 
                if (bh->inreq) {
@@ -2801,7 +2787,7 @@ reset:
        if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
                goto reset;
        fsg->bulk_out_enabled = 1;
-       fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
+       fsg->bulk_out_maxpacket = usb_endpoint_maxp(d);
        clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
 
        if (transport_is_cbi()) {
@@ -2813,7 +2799,7 @@ reset:
        }
 
        /* 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];
 
                if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
@@ -2909,7 +2895,7 @@ static void handle_exception(struct fsg_dev *fsg)
        /* Cancel all the pending transfers */
        if (fsg->intreq_busy)
                usb_ep_dequeue(fsg->intr_in, fsg->intreq);
-       for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
+       for (i = 0; i < fsg_num_buffers; ++i) {
                bh = &fsg->buffhds[i];
                if (bh->inreq_busy)
                        usb_ep_dequeue(fsg->bulk_in, bh->inreq);
@@ -2920,7 +2906,7 @@ static void handle_exception(struct fsg_dev *fsg)
        /* Wait until everything is idle */
        for (;;) {
                num_active = fsg->intreq_busy;
-               for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
+               for (i = 0; i < fsg_num_buffers; ++i) {
                        bh = &fsg->buffhds[i];
                        num_active += bh->inreq_busy + bh->outreq_busy;
                }
@@ -2942,7 +2928,7 @@ static void handle_exception(struct fsg_dev *fsg)
         * state, and the exception.  Then invoke the handler. */
        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->state = BUF_STATE_EMPTY;
        }
@@ -3172,7 +3158,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
        }
 
        /* 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);
 
        /* Free the request and buffer for endpoint 0 */
@@ -3460,7 +3446,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
        req->complete = ep0_complete;
 
        /* 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];
 
                /* Allocate for the bulk-in endpoint.  We assume that
@@ -3471,7 +3457,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
                        goto out;
                bh->next = bh + 1;
        }
-       fsg->buffhds[FSG_NUM_BUFFERS - 1].next = &fsg->buffhds[0];
+       fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0];
 
        /* This should reflect the actual gadget power source */
        usb_gadget_set_selfpowered(gadget);
@@ -3587,7 +3573,9 @@ static int __init fsg_alloc(void)
 {
        struct fsg_dev          *fsg;
 
-       fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
+       fsg = kzalloc(sizeof *fsg +
+                     fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL);
+
        if (!fsg)
                return -ENOMEM;
        spin_lock_init(&fsg->lock);
@@ -3605,6 +3593,10 @@ static int __init fsg_init(void)
        int             rc;
        struct fsg_dev  *fsg;
 
+       rc = fsg_num_buffers_validate();
+       if (rc != 0)
+               return rc;
+
        if ((rc = fsg_alloc()) != 0)
                return rc;
        fsg = the_fsg;