diff options
Diffstat (limited to 'drivers/usb/gadget/f_mass_storage.c')
-rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 1a6f415c0d0..6353eca1e85 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c | |||
@@ -1873,17 +1873,14 @@ static int check_command(struct fsg_common *common, int cmnd_size, | |||
1873 | common->lun, lun); | 1873 | common->lun, lun); |
1874 | 1874 | ||
1875 | /* Check the LUN */ | 1875 | /* Check the LUN */ |
1876 | if (common->lun < common->nluns) { | 1876 | curlun = common->curlun; |
1877 | curlun = &common->luns[common->lun]; | 1877 | if (curlun) { |
1878 | common->curlun = curlun; | ||
1879 | if (common->cmnd[0] != REQUEST_SENSE) { | 1878 | if (common->cmnd[0] != REQUEST_SENSE) { |
1880 | curlun->sense_data = SS_NO_SENSE; | 1879 | curlun->sense_data = SS_NO_SENSE; |
1881 | curlun->sense_data_info = 0; | 1880 | curlun->sense_data_info = 0; |
1882 | curlun->info_valid = 0; | 1881 | curlun->info_valid = 0; |
1883 | } | 1882 | } |
1884 | } else { | 1883 | } else { |
1885 | common->curlun = NULL; | ||
1886 | curlun = NULL; | ||
1887 | common->bad_lun_okay = 0; | 1884 | common->bad_lun_okay = 0; |
1888 | 1885 | ||
1889 | /* | 1886 | /* |
@@ -1929,6 +1926,17 @@ static int check_command(struct fsg_common *common, int cmnd_size, | |||
1929 | return 0; | 1926 | return 0; |
1930 | } | 1927 | } |
1931 | 1928 | ||
1929 | /* wrapper of check_command for data size in blocks handling */ | ||
1930 | static int check_command_size_in_blocks(struct fsg_common *common, | ||
1931 | int cmnd_size, enum data_direction data_dir, | ||
1932 | unsigned int mask, int needs_medium, const char *name) | ||
1933 | { | ||
1934 | if (common->curlun) | ||
1935 | common->data_size_from_cmnd <<= common->curlun->blkbits; | ||
1936 | return check_command(common, cmnd_size, data_dir, | ||
1937 | mask, needs_medium, name); | ||
1938 | } | ||
1939 | |||
1932 | static int do_scsi_command(struct fsg_common *common) | 1940 | static int do_scsi_command(struct fsg_common *common) |
1933 | { | 1941 | { |
1934 | struct fsg_buffhd *bh; | 1942 | struct fsg_buffhd *bh; |
@@ -2011,9 +2019,9 @@ static int do_scsi_command(struct fsg_common *common) | |||
2011 | 2019 | ||
2012 | case READ_6: | 2020 | case READ_6: |
2013 | i = common->cmnd[4]; | 2021 | i = common->cmnd[4]; |
2014 | common->data_size_from_cmnd = (i == 0 ? 256 : i) << | 2022 | common->data_size_from_cmnd = (i == 0) ? 256 : i; |
2015 | common->curlun->blkbits; | 2023 | reply = check_command_size_in_blocks(common, 6, |
2016 | reply = check_command(common, 6, DATA_DIR_TO_HOST, | 2024 | DATA_DIR_TO_HOST, |
2017 | (7<<1) | (1<<4), 1, | 2025 | (7<<1) | (1<<4), 1, |
2018 | "READ(6)"); | 2026 | "READ(6)"); |
2019 | if (reply == 0) | 2027 | if (reply == 0) |
@@ -2022,9 +2030,9 @@ static int do_scsi_command(struct fsg_common *common) | |||
2022 | 2030 | ||
2023 | case READ_10: | 2031 | case READ_10: |
2024 | common->data_size_from_cmnd = | 2032 | common->data_size_from_cmnd = |
2025 | get_unaligned_be16(&common->cmnd[7]) << | 2033 | get_unaligned_be16(&common->cmnd[7]); |
2026 | common->curlun->blkbits; | 2034 | reply = check_command_size_in_blocks(common, 10, |
2027 | reply = check_command(common, 10, DATA_DIR_TO_HOST, | 2035 | DATA_DIR_TO_HOST, |
2028 | (1<<1) | (0xf<<2) | (3<<7), 1, | 2036 | (1<<1) | (0xf<<2) | (3<<7), 1, |
2029 | "READ(10)"); | 2037 | "READ(10)"); |
2030 | if (reply == 0) | 2038 | if (reply == 0) |
@@ -2033,9 +2041,9 @@ static int do_scsi_command(struct fsg_common *common) | |||
2033 | 2041 | ||
2034 | case READ_12: | 2042 | case READ_12: |
2035 | common->data_size_from_cmnd = | 2043 | common->data_size_from_cmnd = |
2036 | get_unaligned_be32(&common->cmnd[6]) << | 2044 | get_unaligned_be32(&common->cmnd[6]); |
2037 | common->curlun->blkbits; | 2045 | reply = check_command_size_in_blocks(common, 12, |
2038 | reply = check_command(common, 12, DATA_DIR_TO_HOST, | 2046 | DATA_DIR_TO_HOST, |
2039 | (1<<1) | (0xf<<2) | (0xf<<6), 1, | 2047 | (1<<1) | (0xf<<2) | (0xf<<6), 1, |
2040 | "READ(12)"); | 2048 | "READ(12)"); |
2041 | if (reply == 0) | 2049 | if (reply == 0) |
@@ -2134,9 +2142,9 @@ static int do_scsi_command(struct fsg_common *common) | |||
2134 | 2142 | ||
2135 | case WRITE_6: | 2143 | case WRITE_6: |
2136 | i = common->cmnd[4]; | 2144 | i = common->cmnd[4]; |
2137 | common->data_size_from_cmnd = (i == 0 ? 256 : i) << | 2145 | common->data_size_from_cmnd = (i == 0) ? 256 : i; |
2138 | common->curlun->blkbits; | 2146 | reply = check_command_size_in_blocks(common, 6, |
2139 | reply = check_command(common, 6, DATA_DIR_FROM_HOST, | 2147 | DATA_DIR_FROM_HOST, |
2140 | (7<<1) | (1<<4), 1, | 2148 | (7<<1) | (1<<4), 1, |
2141 | "WRITE(6)"); | 2149 | "WRITE(6)"); |
2142 | if (reply == 0) | 2150 | if (reply == 0) |
@@ -2145,9 +2153,9 @@ static int do_scsi_command(struct fsg_common *common) | |||
2145 | 2153 | ||
2146 | case WRITE_10: | 2154 | case WRITE_10: |
2147 | common->data_size_from_cmnd = | 2155 | common->data_size_from_cmnd = |
2148 | get_unaligned_be16(&common->cmnd[7]) << | 2156 | get_unaligned_be16(&common->cmnd[7]); |
2149 | common->curlun->blkbits; | 2157 | reply = check_command_size_in_blocks(common, 10, |
2150 | reply = check_command(common, 10, DATA_DIR_FROM_HOST, | 2158 | DATA_DIR_FROM_HOST, |
2151 | (1<<1) | (0xf<<2) | (3<<7), 1, | 2159 | (1<<1) | (0xf<<2) | (3<<7), 1, |
2152 | "WRITE(10)"); | 2160 | "WRITE(10)"); |
2153 | if (reply == 0) | 2161 | if (reply == 0) |
@@ -2156,9 +2164,9 @@ static int do_scsi_command(struct fsg_common *common) | |||
2156 | 2164 | ||
2157 | case WRITE_12: | 2165 | case WRITE_12: |
2158 | common->data_size_from_cmnd = | 2166 | common->data_size_from_cmnd = |
2159 | get_unaligned_be32(&common->cmnd[6]) << | 2167 | get_unaligned_be32(&common->cmnd[6]); |
2160 | common->curlun->blkbits; | 2168 | reply = check_command_size_in_blocks(common, 12, |
2161 | reply = check_command(common, 12, DATA_DIR_FROM_HOST, | 2169 | DATA_DIR_FROM_HOST, |
2162 | (1<<1) | (0xf<<2) | (0xf<<6), 1, | 2170 | (1<<1) | (0xf<<2) | (0xf<<6), 1, |
2163 | "WRITE(12)"); | 2171 | "WRITE(12)"); |
2164 | if (reply == 0) | 2172 | if (reply == 0) |
@@ -2273,6 +2281,10 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
2273 | if (common->data_size == 0) | 2281 | if (common->data_size == 0) |
2274 | common->data_dir = DATA_DIR_NONE; | 2282 | common->data_dir = DATA_DIR_NONE; |
2275 | common->lun = cbw->Lun; | 2283 | common->lun = cbw->Lun; |
2284 | if (common->lun >= 0 && common->lun < common->nluns) | ||
2285 | common->curlun = &common->luns[common->lun]; | ||
2286 | else | ||
2287 | common->curlun = NULL; | ||
2276 | common->tag = cbw->Tag; | 2288 | common->tag = cbw->Tag; |
2277 | return 0; | 2289 | return 0; |
2278 | } | 2290 | } |
@@ -2763,7 +2775,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
2763 | * Create the LUNs, open their backing files, and register the | 2775 | * Create the LUNs, open their backing files, and register the |
2764 | * LUN devices in sysfs. | 2776 | * LUN devices in sysfs. |
2765 | */ | 2777 | */ |
2766 | curlun = kzalloc(nluns * sizeof *curlun, GFP_KERNEL); | 2778 | curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL); |
2767 | if (unlikely(!curlun)) { | 2779 | if (unlikely(!curlun)) { |
2768 | rc = -ENOMEM; | 2780 | rc = -ENOMEM; |
2769 | goto error_release; | 2781 | goto error_release; |