diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 17 | ||||
-rw-r--r-- | drivers/usb/core/hcd.c | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/core.c | 9 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/iowarrior.c | 11 | ||||
-rw-r--r-- | drivers/usb/storage/ene_ub6250.c | 87 | ||||
-rw-r--r-- | drivers/usb/typec/typec.c | 11 |
7 files changed, 86 insertions, 63 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 08669fee6d7f..8f972247b1c1 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -361,17 +361,9 @@ static ssize_t wdm_write if (we < 0) return usb_translate_errors(we); - buf = kmalloc(count, GFP_KERNEL); - if (!buf) { - rv = -ENOMEM; - goto outnl; - } - - r = copy_from_user(buf, buffer, count); - if (r > 0) { - rv = -EFAULT; - goto out_free_mem; - } + buf = memdup_user(buffer, count); + if (IS_ERR(buf)) + return PTR_ERR(buf); /* concurrent writes and disconnect */ r = mutex_lock_interruptible(&desc->wlock); @@ -441,8 +433,7 @@ static ssize_t wdm_write usb_autopm_put_interface(desc->intf); mutex_unlock(&desc->wlock); -outnl: - return rv < 0 ? rv : count; + return count; out_free_mem_pm: usb_autopm_put_interface(desc->intf); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5dea98358c05..e72cbc751619 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -26,6 +26,7 @@ #include <linux/module.h> #include <linux/version.h> #include <linux/kernel.h> +#include <linux/sched/task_stack.h> #include <linux/slab.h> #include <linux/completion.h> #include <linux/utsname.h> @@ -1523,6 +1524,14 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, if (hcd->self.uses_pio_for_control) return ret; if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) { + if (is_vmalloc_addr(urb->setup_packet)) { + WARN_ONCE(1, "setup packet is not dma capable\n"); + return -EAGAIN; + } else if (object_is_on_stack(urb->setup_packet)) { + WARN_ONCE(1, "setup packet is on stack\n"); + return -EAGAIN; + } + urb->setup_dma = dma_map_single( hcd->self.sysdev, urb->setup_packet, @@ -1587,6 +1596,9 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, } else if (is_vmalloc_addr(urb->transfer_buffer)) { WARN_ONCE(1, "transfer buffer not dma capable\n"); ret = -EAGAIN; + } else if (object_is_on_stack(urb->transfer_buffer)) { + WARN_ONCE(1, "transfer buffer is on stack\n"); + ret = -EAGAIN; } else { urb->transfer_dma = dma_map_single( hcd->self.sysdev, diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index efce68e9a8e0..a03aec574f64 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -23,6 +23,7 @@ #include <linux/list.h> #include <linux/err.h> #include <linux/dma-mapping.h> +#include <linux/sched/task_stack.h> #include <linux/workqueue.h> #include <linux/usb/ch9.h> @@ -798,6 +799,14 @@ int usb_gadget_map_request_by_dev(struct device *dev, req->num_mapped_sgs = mapped; } else { + if (is_vmalloc_addr(req->buf)) { + dev_err(dev, "buffer is not dma capable\n"); + return -EFAULT; + } else if (object_is_on_stack(req->buf)) { + dev_err(dev, "buffer is on stack\n"); + return -EFAULT; + } + req->dma = dma_map_single(dev, req->buf, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 980a6b3b2da2..6bc6304672bc 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1105,7 +1105,7 @@ iso_stream_init( addr |= epnum << 8; addr |= dev->devnum; stream->ps.usecs = HS_USECS_ISO(maxp); - think_time = dev->tt ? dev->tt->think_time : 0; + think_time = dev->tt->think_time; stream->ps.tt_usecs = NS_TO_US(think_time + usb_calc_bus_time( dev->speed, is_input, 1, maxp)); hs_transfers = max(1u, (maxp + 187) / 188); diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 83b05a287b0c..7ca4c7e0ea0d 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -368,14 +368,9 @@ static ssize_t iowarrior_write(struct file *file, case USB_DEVICE_ID_CODEMERCS_IOWPV2: case USB_DEVICE_ID_CODEMERCS_IOW40: /* IOW24 and IOW40 use a synchronous call */ - buf = kmalloc(count, GFP_KERNEL); - if (!buf) { - retval = -ENOMEM; - goto exit; - } - if (copy_from_user(buf, user_buffer, count)) { - retval = -EFAULT; - kfree(buf); + buf = memdup_user(user_buffer, count); + if (IS_ERR(buf)) { + retval = PTR_ERR(buf); goto exit; } retval = usb_set_report(dev->interface, 2, 0, buf, count); diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 44af719194b2..28100374f7bd 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -95,12 +95,12 @@ static struct us_unusual_dev ene_ub6250_unusual_dev_list[] = { #define REG_HW_TRAP1 0xFF89 /* SRB Status */ -#define SS_SUCCESS 0x00 /* No Sense */ -#define SS_NOT_READY 0x02 -#define SS_MEDIUM_ERR 0x03 -#define SS_HW_ERR 0x04 -#define SS_ILLEGAL_REQUEST 0x05 -#define SS_UNIT_ATTENTION 0x06 +#define SS_SUCCESS 0x000000 /* No Sense */ +#define SS_NOT_READY 0x023A00 /* Medium not present */ +#define SS_MEDIUM_ERR 0x031100 /* Unrecovered read error */ +#define SS_HW_ERR 0x040800 /* Communication failure */ +#define SS_ILLEGAL_REQUEST 0x052000 /* Invalid command */ +#define SS_UNIT_ATTENTION 0x062900 /* Reset occurred */ /* ENE Load FW Pattern */ #define SD_INIT1_PATTERN 1 @@ -584,24 +584,26 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg) return USB_STOR_TRANSPORT_GOOD; } -static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb) +static int do_scsi_request_sense(struct us_data *us, struct scsi_cmnd *srb) { struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + unsigned char buf[18]; - if (info->SD_Status.Insert && info->SD_Status.Ready) - return USB_STOR_TRANSPORT_GOOD; - else { - ene_sd_init(us); - return USB_STOR_TRANSPORT_GOOD; - } + memset(buf, 0, 18); + buf[0] = 0x70; /* Current error */ + buf[2] = info->SrbStatus >> 16; /* Sense key */ + buf[7] = 10; /* Additional length */ + buf[12] = info->SrbStatus >> 8; /* ASC */ + buf[13] = info->SrbStatus; /* ASCQ */ + usb_stor_set_xfer_buf(buf, sizeof(buf), srb); return USB_STOR_TRANSPORT_GOOD; } -static int sd_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb) +static int do_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb) { unsigned char data_ptr[36] = { - 0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, + 0x00, 0x00, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30 }; @@ -610,6 +612,20 @@ static int sd_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb) return USB_STOR_TRANSPORT_GOOD; } +static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb) +{ + struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + + if (info->SD_Status.Insert && info->SD_Status.Ready) + return USB_STOR_TRANSPORT_GOOD; + else { + ene_sd_init(us); + return USB_STOR_TRANSPORT_GOOD; + } + + return USB_STOR_TRANSPORT_GOOD; +} + static int sd_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb) { struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; @@ -1455,19 +1471,6 @@ static int ms_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb) return USB_STOR_TRANSPORT_GOOD; } -static int ms_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb) -{ - /* pr_info("MS_SCSI_Inquiry\n"); */ - unsigned char data_ptr[36] = { - 0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, - 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, - 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30}; - - usb_stor_set_xfer_buf(data_ptr, 36, srb); - return USB_STOR_TRANSPORT_GOOD; -} - static int ms_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb) { struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; @@ -1940,6 +1943,8 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag) bcb->CDB[0] = 0xEF; result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0); + if (us->srb != NULL) + scsi_set_resid(us->srb, 0); info->BIN_FLAG = flag; kfree(buf); @@ -2223,13 +2228,15 @@ static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb) int result; struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra; - info->SrbStatus = SS_SUCCESS; switch (srb->cmnd[0]) { case TEST_UNIT_READY: result = sd_scsi_test_unit_ready(us, srb); break; /* 0x00 */ + case REQUEST_SENSE: + result = do_scsi_request_sense(us, srb); + break; /* 0x03 */ case INQUIRY: - result = sd_scsi_inquiry(us, srb); + result = do_scsi_inquiry(us, srb); break; /* 0x12 */ case MODE_SENSE: result = sd_scsi_mode_sense(us, srb); @@ -2253,6 +2260,8 @@ static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb) result = USB_STOR_TRANSPORT_FAILED; break; } + if (result == USB_STOR_TRANSPORT_GOOD) + info->SrbStatus = SS_SUCCESS; return result; } @@ -2263,13 +2272,16 @@ static int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb) { int result; struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra; - info->SrbStatus = SS_SUCCESS; + switch (srb->cmnd[0]) { case TEST_UNIT_READY: result = ms_scsi_test_unit_ready(us, srb); break; /* 0x00 */ + case REQUEST_SENSE: + result = do_scsi_request_sense(us, srb); + break; /* 0x03 */ case INQUIRY: - result = ms_scsi_inquiry(us, srb); + result = do_scsi_inquiry(us, srb); break; /* 0x12 */ case MODE_SENSE: result = ms_scsi_mode_sense(us, srb); @@ -2288,26 +2300,29 @@ static int ms_scsi_irp(struct us_data *us, struct scsi_cmnd *srb) result = USB_STOR_TRANSPORT_FAILED; break; } + if (result == USB_STOR_TRANSPORT_GOOD) + info->SrbStatus = SS_SUCCESS; return result; } static int ene_transport(struct scsi_cmnd *srb, struct us_data *us) { - int result = 0; + int result = USB_STOR_XFER_GOOD; struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); /*US_DEBUG(usb_stor_show_command(us, srb)); */ scsi_set_resid(srb, 0); - if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready))) { + if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready))) result = ene_init(us); - } else { + if (result == USB_STOR_XFER_GOOD) { + result = USB_STOR_TRANSPORT_ERROR; if (info->SD_Status.Ready) result = sd_scsi_irp(us, srb); if (info->MS_Status.Ready) result = ms_scsi_irp(us, srb); } - return 0; + return result; } static struct scsi_host_template ene_ub6250_host_template; diff --git a/drivers/usb/typec/typec.c b/drivers/usb/typec/typec.c index 89e540bb7ff3..db5ee730ad24 100644 --- a/drivers/usb/typec/typec.c +++ b/drivers/usb/typec/typec.c @@ -291,7 +291,7 @@ typec_altmode_roles_show(struct device *dev, struct device_attribute *attr, } static void typec_init_modes(struct typec_altmode *alt, - struct typec_mode_desc *desc, bool is_port) + const struct typec_mode_desc *desc, bool is_port) { int i; @@ -378,7 +378,8 @@ static const struct device_type typec_altmode_dev_type = { }; static struct typec_altmode * -typec_register_altmode(struct device *parent, struct typec_altmode_desc *desc) +typec_register_altmode(struct device *parent, + const struct typec_altmode_desc *desc) { struct typec_altmode *alt; int ret; @@ -495,7 +496,7 @@ EXPORT_SYMBOL_GPL(typec_partner_set_identity); */ struct typec_altmode * typec_partner_register_altmode(struct typec_partner *partner, - struct typec_altmode_desc *desc) + const struct typec_altmode_desc *desc) { return typec_register_altmode(&partner->dev, desc); } @@ -590,7 +591,7 @@ static const struct device_type typec_plug_dev_type = { */ struct typec_altmode * typec_plug_register_altmode(struct typec_plug *plug, - struct typec_altmode_desc *desc) + const struct typec_altmode_desc *desc) { return typec_register_altmode(&plug->dev, desc); } @@ -1159,7 +1160,7 @@ EXPORT_SYMBOL_GPL(typec_set_pwr_opmode); */ struct typec_altmode * typec_port_register_altmode(struct typec_port *port, - struct typec_altmode_desc *desc) + const struct typec_altmode_desc *desc) { return typec_register_altmode(&port->dev, desc); } |