| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Remote VUB300 SDIO/SDmem Host Controller Driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * based on USB Skeleton driver - 2.2 |
|---|
| 7 | 8 | * |
|---|
| 8 | 9 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or |
|---|
| 11 | | - * modify it under the terms of the GNU General Public License as |
|---|
| 12 | | - * published by the Free Software Foundation, version 2 |
|---|
| 13 | 10 | * |
|---|
| 14 | 11 | * VUB300: is a USB 2.0 client device with a single SDIO/SDmem/MMC slot |
|---|
| 15 | 12 | * Any SDIO/SDmem/MMC device plugged into the VUB300 will appear, |
|---|
| .. | .. |
|---|
| 98 | 95 | u8 port_number; |
|---|
| 99 | 96 | u8 command_type; |
|---|
| 100 | 97 | u8 command_index; |
|---|
| 101 | | - u8 command_response[0]; |
|---|
| 98 | + u8 command_response[]; |
|---|
| 102 | 99 | } __packed; |
|---|
| 103 | 100 | |
|---|
| 104 | 101 | struct sd_status_header { |
|---|
| .. | .. |
|---|
| 1366 | 1363 | int retval; |
|---|
| 1367 | 1364 | for (n = 0; n < sdio_funcs; n++) { |
|---|
| 1368 | 1365 | struct sdio_func *sf = card->sdio_func[n]; |
|---|
| 1369 | | - l += snprintf(vub300->vub_name + l, |
|---|
| 1366 | + l += scnprintf(vub300->vub_name + l, |
|---|
| 1370 | 1367 | sizeof(vub300->vub_name) - l, "_%04X%04X", |
|---|
| 1371 | 1368 | sf->vendor, sf->device); |
|---|
| 1372 | 1369 | } |
|---|
| .. | .. |
|---|
| 1718 | 1715 | int bytes = 3 & less_cmd; |
|---|
| 1719 | 1716 | int words = less_cmd >> 2; |
|---|
| 1720 | 1717 | u8 *r = vub300->resp.response.command_response; |
|---|
| 1718 | + |
|---|
| 1719 | + if (!resp_len) |
|---|
| 1720 | + return; |
|---|
| 1721 | 1721 | if (bytes == 3) { |
|---|
| 1722 | 1722 | cmd->resp[words] = (r[1 + (words << 2)] << 24) |
|---|
| 1723 | 1723 | | (r[2 + (words << 2)] << 16) |
|---|
| .. | .. |
|---|
| 2052 | 2052 | return; |
|---|
| 2053 | 2053 | kref_get(&vub300->kref); |
|---|
| 2054 | 2054 | if (enable) { |
|---|
| 2055 | + set_current_state(TASK_RUNNING); |
|---|
| 2055 | 2056 | mutex_lock(&vub300->irq_mutex); |
|---|
| 2056 | 2057 | if (vub300->irqs_queued) { |
|---|
| 2057 | 2058 | vub300->irqs_queued -= 1; |
|---|
| .. | .. |
|---|
| 2067 | 2068 | vub300_queue_poll_work(vub300, 0); |
|---|
| 2068 | 2069 | } |
|---|
| 2069 | 2070 | mutex_unlock(&vub300->irq_mutex); |
|---|
| 2071 | + set_current_state(TASK_INTERRUPTIBLE); |
|---|
| 2070 | 2072 | } else { |
|---|
| 2071 | 2073 | vub300->irq_enabled = 0; |
|---|
| 2072 | 2074 | } |
|---|
| 2073 | 2075 | kref_put(&vub300->kref, vub300_delete); |
|---|
| 2074 | | -} |
|---|
| 2075 | | - |
|---|
| 2076 | | -static void vub300_init_card(struct mmc_host *mmc, struct mmc_card *card) |
|---|
| 2077 | | -{ /* NOT irq */ |
|---|
| 2078 | | - struct vub300_mmc_host *vub300 = mmc_priv(mmc); |
|---|
| 2079 | | - dev_info(&vub300->udev->dev, "NO host QUIRKS for this card\n"); |
|---|
| 2080 | 2076 | } |
|---|
| 2081 | 2077 | |
|---|
| 2082 | 2078 | static const struct mmc_host_ops vub300_mmc_ops = { |
|---|
| .. | .. |
|---|
| 2084 | 2080 | .set_ios = vub300_mmc_set_ios, |
|---|
| 2085 | 2081 | .get_ro = vub300_mmc_get_ro, |
|---|
| 2086 | 2082 | .enable_sdio_irq = vub300_enable_sdio_irq, |
|---|
| 2087 | | - .init_card = vub300_init_card, |
|---|
| 2088 | 2083 | }; |
|---|
| 2089 | 2084 | |
|---|
| 2090 | 2085 | static int vub300_probe(struct usb_interface *interface, |
|---|
| .. | .. |
|---|
| 2309 | 2304 | 0x0000, 0x0000, &vub300->system_port_status, |
|---|
| 2310 | 2305 | sizeof(vub300->system_port_status), 1000); |
|---|
| 2311 | 2306 | if (retval < 0) { |
|---|
| 2312 | | - goto error4; |
|---|
| 2307 | + goto error5; |
|---|
| 2313 | 2308 | } else if (sizeof(vub300->system_port_status) == retval) { |
|---|
| 2314 | 2309 | vub300->card_present = |
|---|
| 2315 | 2310 | (0x0001 & vub300->system_port_status.port_flags) ? 1 : 0; |
|---|
| 2316 | 2311 | vub300->read_only = |
|---|
| 2317 | 2312 | (0x0010 & vub300->system_port_status.port_flags) ? 1 : 0; |
|---|
| 2318 | 2313 | } else { |
|---|
| 2319 | | - goto error4; |
|---|
| 2314 | + goto error5; |
|---|
| 2320 | 2315 | } |
|---|
| 2321 | 2316 | usb_set_intfdata(interface, vub300); |
|---|
| 2322 | 2317 | INIT_DELAYED_WORK(&vub300->pollwork, vub300_pollwork_thread); |
|---|
| .. | .. |
|---|
| 2339 | 2334 | "USB vub300 remote SDIO host controller[%d]" |
|---|
| 2340 | 2335 | "connected with no SD/SDIO card inserted\n", |
|---|
| 2341 | 2336 | interface_to_InterfaceNumber(interface)); |
|---|
| 2342 | | - mmc_add_host(mmc); |
|---|
| 2337 | + retval = mmc_add_host(mmc); |
|---|
| 2338 | + if (retval) |
|---|
| 2339 | + goto error6; |
|---|
| 2340 | + |
|---|
| 2343 | 2341 | return 0; |
|---|
| 2342 | +error6: |
|---|
| 2343 | + del_timer_sync(&vub300->inactivity_timer); |
|---|
| 2344 | 2344 | error5: |
|---|
| 2345 | 2345 | mmc_free_host(mmc); |
|---|
| 2346 | 2346 | /* |
|---|