X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=drivers%2Fusb%2Fgadget%2Ff_mass_storage.c;h=f30b4f812e6d4b8495e8b08fc0c59bb84e9ce851;hb=6549d5c30e3bd88244ac5c0ca187cead62ff4f8a;hp=45bc132aef6729827594dcf1a373c7e49510114f;hpb=f6664ba4bcc484a2b924ecfa1052bb729def6685;p=karo-tx-uboot.git diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 45bc132aef..f30b4f812e 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -6,38 +6,9 @@ * Author: Michal Nazarewicz * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any - * later version. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause */ - /* * The Mass Storage Function acts as a USB Mass Storage device, * appearing to the host as a disk drive or as a CD-ROM drive. In @@ -181,7 +152,6 @@ * . */ - /* * Driver Design * @@ -273,6 +243,8 @@ #include #include #include +#include +#include #include #include @@ -284,6 +256,7 @@ #include #include #include +#include /*------------------------------------------------------------------------*/ @@ -292,7 +265,6 @@ static const char fsg_string_interface[] = "Mass Storage"; - #define FSG_NO_INTR_EP 1 #define FSG_NO_DEVICE_STRINGS 1 #define FSG_NO_OTG 1 @@ -472,7 +444,7 @@ static void set_bulk_out_req_length(struct fsg_common *common, /*-------------------------------------------------------------------------*/ -struct ums_board_info *ums_info; +struct ums *ums; struct fsg_common *the_fsg_common; static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) @@ -577,9 +549,9 @@ static int fsg_setup(struct usb_function *f, { struct fsg_dev *fsg = fsg_from_func(f); struct usb_request *req = fsg->common->ep0req; - u16 w_index = le16_to_cpu(ctrl->wIndex); - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 w_length = le16_to_cpu(ctrl->wLength); + u16 w_index = get_unaligned_le16(&ctrl->wIndex); + u16 w_value = get_unaligned_le16(&ctrl->wValue); + u16 w_length = get_unaligned_le16(&ctrl->wLength); if (!fsg_is_set(fsg->common)) return -EOPNOTSUPP; @@ -617,7 +589,7 @@ static int fsg_setup(struct usb_function *f, "unknown class-specific control req " "%02x.%02x v%04x i%04x l%u\n", ctrl->bRequestType, ctrl->bRequest, - le16_to_cpu(ctrl->wValue), w_index, w_length); + get_unaligned_le16(&ctrl->wValue), w_index, w_length); return -EOPNOTSUPP; } @@ -700,13 +672,27 @@ static int sleep_thread(struct fsg_common *common) if (common->thread_wakeup_needed) break; - if (++i == 50000) { + if (++i == 20000) { busy_indicator(); i = 0; k++; } - usb_gadget_handle_interrupts(); + if (k == 10) { + /* Handle CTRL+C */ + if (ctrlc()) + return -EPIPE; + + WATCHDOG_RESET(); + + /* Check cable connection */ + if (!g_dnl_board_usb_cable_connected()) + return -EIO; + + k = 0; + } + + usb_gadget_handle_interrupts(0); } common->thread_wakeup_needed = 0; return rc; @@ -788,14 +774,14 @@ static int do_read(struct fsg_common *common) } /* Perform the read */ - nread = 0; - rc = ums_info->read_sector(&(ums_info->ums_dev), - file_offset / SECTOR_SIZE, - amount / SECTOR_SIZE, - (char __user *)bh->buf); - if (rc) + rc = ums->read_sector(ums, + file_offset / SECTOR_SIZE, + amount / SECTOR_SIZE, + (char __user *)bh->buf); + if (!rc) return -EIO; - nread = amount; + + nread = rc * SECTOR_SIZE; VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, (unsigned long long) file_offset, @@ -962,13 +948,13 @@ static int do_write(struct fsg_common *common) amount = bh->outreq->actual; /* Perform the write */ - rc = ums_info->write_sector(&(ums_info->ums_dev), + rc = ums->write_sector(ums, file_offset / SECTOR_SIZE, amount / SECTOR_SIZE, (char __user *)bh->buf); - if (rc) + if (!rc) return -EIO; - nwritten = amount; + nwritten = rc * SECTOR_SIZE; VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, (unsigned long long) file_offset, @@ -990,6 +976,8 @@ static int do_write(struct fsg_common *common) /* If an error occurred, report it and its position */ if (nwritten < amount) { + printf("nwritten:%zd amount:%u\n", nwritten, + amount); curlun->sense_data = SS_WRITE_ERROR; curlun->info_valid = 1; break; @@ -1076,14 +1064,13 @@ static int do_verify(struct fsg_common *common) } /* Perform the read */ - nread = 0; - rc = ums_info->read_sector(&(ums_info->ums_dev), - file_offset / SECTOR_SIZE, - amount / SECTOR_SIZE, - (char __user *)bh->buf); - if (rc) + rc = ums->read_sector(ums, + file_offset / SECTOR_SIZE, + amount / SECTOR_SIZE, + (char __user *)bh->buf); + if (!rc) return -EIO; - nread = amount; + nread = rc * SECTOR_SIZE; VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, (unsigned long long) file_offset, @@ -1126,12 +1113,13 @@ static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh) memset(buf, 0, 8); buf[0] = TYPE_DISK; + buf[1] = curlun->removable ? 0x80 : 0; buf[2] = 2; /* ANSI SCSI level 2 */ buf[3] = 2; /* SCSI-2 INQUIRY data format */ buf[4] = 31; /* Additional length */ /* No special options */ sprintf((char *) (buf + 8), "%-8s%-16s%04x", (char*) vendor_id , - ums_info->name, (u16) 0xffff); + ums->name, (u16) 0xffff); return 36; } @@ -2417,6 +2405,7 @@ static void handle_exception(struct fsg_common *common) int fsg_main_thread(void *common_) { + int ret; struct fsg_common *common = the_fsg_common; /* The main loop */ do { @@ -2426,12 +2415,16 @@ int fsg_main_thread(void *common_) } if (!common->running) { - sleep_thread(common); + ret = sleep_thread(common); + if (ret) + return ret; + continue; } - if (get_next_command(common)) - continue; + ret = get_next_command(common); + if (ret) + return ret; if (!exception_in_progress(common)) common->state = FSG_STATE_DATA_PHASE; @@ -2473,12 +2466,12 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, /* Allocate? */ if (!common) { - common = calloc(sizeof *common, 1); + common = calloc(sizeof(*common), 1); if (!common) return ERR_PTR(-ENOMEM); common->free_storage_on_release = 1; } else { - memset(common, 0, sizeof common); + memset(common, 0, sizeof(*common)); common->free_storage_on_release = 0; } @@ -2527,7 +2520,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, buffhds_first_it: bh->inreq_busy = 0; bh->outreq_busy = 0; - bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL); + bh->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, FSG_BUFLEN); if (unlikely(!bh->buf)) { rc = -ENOMEM; goto error_release; @@ -2634,7 +2627,7 @@ usb_copy_descriptors(struct usb_descriptor_header **src) bytes += (*tmp)->bLength; bytes += (n_desc + 1) * sizeof(*tmp); - mem = kmalloc(bytes, GFP_KERNEL); + mem = memalign(CONFIG_SYS_CACHELINE_SIZE, bytes); if (!mem) return NULL; @@ -2657,8 +2650,6 @@ usb_copy_descriptors(struct usb_descriptor_header **src) return ret; } - - static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); @@ -2786,9 +2777,11 @@ int fsg_add(struct usb_configuration *c) return fsg_bind_config(c->cdev, c, fsg_common); } -int fsg_init(struct ums_board_info *ums) +int fsg_init(struct ums *ums_dev) { - ums_info = ums; + ums = ums_dev; return 0; } + +DECLARE_GADGET_BIND_CALLBACK(usb_dnl_ums, fsg_add);