diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-21 00:12:25 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-21 00:12:25 -0400 |
| commit | 19e36ad292ab24980db64a5ff17973d3118a8fb9 (patch) | |
| tree | 175715409a689814e5cd425a98f2d2d47f82addf /drivers/usb/misc | |
| parent | e10abc629f38efd9b6936cf3612583cc846104d9 (diff) | |
| parent | 60d5794fe5a50d02f4a0df84b45910a4dfa8b487 (diff) | |
Merge tag 'usb-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB updates from Greg KH:
"Here's the big pull request for USB and PHY drivers for 4.7-rc1
Full details in the shortlog, but it's the normal major gadget driver
updates, phy updates, new usbip code, as well as a bit of lots of
other stuff.
All have been in linux-next with no reported issues"
* tag 'usb-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (164 commits)
USB: serial: ti_usb_3410_5052: add MOXA UPORT 11x0 support
USB: serial: fix minor-number allocation
USB: serial: quatech2: fix use-after-free in probe error path
USB: serial: mxuport: fix use-after-free in probe error path
USB: serial: keyspan: fix debug and error messages
USB: serial: keyspan: fix URB unlink
USB: serial: keyspan: fix use-after-free in probe error path
USB: serial: io_edgeport: fix memory leaks in probe error path
USB: serial: io_edgeport: fix memory leaks in attach error path
usb: Remove unnecessary space before operator ','.
usb: Remove unnecessary space before open square bracket.
USB: FHCI: avoid redundant condition
usb: host: xhci-rcar: Avoid long wait in xhci_reset()
usb/host/fotg210: remove dead code in create_sysfs_files
usb: wusbcore: Do not initialise statics to 0.
usb: wusbcore: Remove space before ',' and '(' .
USB: serial: cp210x: clean up CRTSCTS flag code
USB: serial: cp210x: get rid of magic numbers in CRTSCTS flag code
USB: serial: cp210x: fix hardware flow-control disable
USB: serial: option: add even more ZTE device ids
...
Diffstat (limited to 'drivers/usb/misc')
| -rw-r--r-- | drivers/usb/misc/Kconfig | 26 | ||||
| -rw-r--r-- | drivers/usb/misc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/usb/misc/sisusbvga/sisusb.c | 4 | ||||
| -rw-r--r-- | drivers/usb/misc/ucsi.c | 478 | ||||
| -rw-r--r-- | drivers/usb/misc/ucsi.h | 215 | ||||
| -rw-r--r-- | drivers/usb/misc/usbtest.c | 7 |
6 files changed, 728 insertions, 3 deletions
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index f7a7fc21be8a..e9e5ae521fa6 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig | |||
| @@ -268,3 +268,29 @@ config USB_CHAOSKEY | |||
| 268 | 268 | ||
| 269 | To compile this driver as a module, choose M here: the | 269 | To compile this driver as a module, choose M here: the |
| 270 | module will be called chaoskey. | 270 | module will be called chaoskey. |
| 271 | |||
| 272 | config UCSI | ||
| 273 | tristate "USB Type-C Connector System Software Interface driver" | ||
| 274 | depends on ACPI | ||
| 275 | help | ||
| 276 | UCSI driver is meant to be used as a convenience tool for desktop and | ||
| 277 | server systems that are not equipped to handle USB in device mode. It | ||
| 278 | will always select USB host role for the USB Type-C ports on systems | ||
| 279 | that provide UCSI interface. | ||
| 280 | |||
| 281 | USB Type-C Connector System Software Interface (UCSI) is a | ||
| 282 | specification for an interface that allows the Operating System to | ||
| 283 | control the USB Type-C ports on a system. Things the need controlling | ||
| 284 | include the USB Data Role (host or device), and when USB Power | ||
| 285 | Delivery is supported, the Power Role (source or sink). With USB | ||
| 286 | Type-C connectors, when two dual role capable devices are attached | ||
| 287 | together, the data role is selected randomly. Therefore it is | ||
| 288 | important to give the OS a way to select the role. Otherwise the user | ||
| 289 | would have to unplug and replug in order in order to attempt to swap | ||
| 290 | the data and power roles. | ||
| 291 | |||
| 292 | The UCSI specification can be downloaded from: | ||
| 293 | http://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html | ||
| 294 | |||
| 295 | To compile the driver as a module, choose M here: the module will be | ||
| 296 | called ucsi. | ||
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 45fd4ac39d3e..2769cf6351b4 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile | |||
| @@ -26,6 +26,7 @@ obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o | |||
| 26 | obj-$(CONFIG_USB_YUREX) += yurex.o | 26 | obj-$(CONFIG_USB_YUREX) += yurex.o |
| 27 | obj-$(CONFIG_USB_HSIC_USB3503) += usb3503.o | 27 | obj-$(CONFIG_USB_HSIC_USB3503) += usb3503.o |
| 28 | obj-$(CONFIG_USB_CHAOSKEY) += chaoskey.o | 28 | obj-$(CONFIG_USB_CHAOSKEY) += chaoskey.o |
| 29 | obj-$(CONFIG_UCSI) += ucsi.o | ||
| 29 | 30 | ||
| 30 | obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ | 31 | obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ |
| 31 | obj-$(CONFIG_USB_LINK_LAYER_TEST) += lvstest.o | 32 | obj-$(CONFIG_USB_LINK_LAYER_TEST) += lvstest.o |
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index a22de52cb083..15666ad7c772 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c | |||
| @@ -2420,7 +2420,7 @@ static int sisusb_open(struct inode *inode, struct file *file) | |||
| 2420 | 2420 | ||
| 2421 | if (!sisusb->devinit) { | 2421 | if (!sisusb->devinit) { |
| 2422 | if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH || | 2422 | if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH || |
| 2423 | sisusb->sisusb_dev->speed == USB_SPEED_SUPER) { | 2423 | sisusb->sisusb_dev->speed >= USB_SPEED_SUPER) { |
| 2424 | if (sisusb_init_gfxdevice(sisusb, 0)) { | 2424 | if (sisusb_init_gfxdevice(sisusb, 0)) { |
| 2425 | mutex_unlock(&sisusb->lock); | 2425 | mutex_unlock(&sisusb->lock); |
| 2426 | dev_err(&sisusb->sisusb_dev->dev, | 2426 | dev_err(&sisusb->sisusb_dev->dev, |
| @@ -3127,7 +3127,7 @@ static int sisusb_probe(struct usb_interface *intf, | |||
| 3127 | 3127 | ||
| 3128 | sisusb->present = 1; | 3128 | sisusb->present = 1; |
| 3129 | 3129 | ||
| 3130 | if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) { | 3130 | if (dev->speed == USB_SPEED_HIGH || dev->speed >= USB_SPEED_SUPER) { |
| 3131 | int initscreen = 1; | 3131 | int initscreen = 1; |
| 3132 | #ifdef INCL_SISUSB_CON | 3132 | #ifdef INCL_SISUSB_CON |
| 3133 | if (sisusb_first_vc > 0 && sisusb_last_vc > 0 && | 3133 | if (sisusb_first_vc > 0 && sisusb_last_vc > 0 && |
diff --git a/drivers/usb/misc/ucsi.c b/drivers/usb/misc/ucsi.c new file mode 100644 index 000000000000..07397bddefa3 --- /dev/null +++ b/drivers/usb/misc/ucsi.c | |||
| @@ -0,0 +1,478 @@ | |||
| 1 | /* | ||
| 2 | * USB Type-C Connector System Software Interface driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2016, Intel Corporation | ||
| 5 | * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/acpi.h> | ||
| 16 | |||
| 17 | #include "ucsi.h" | ||
| 18 | |||
| 19 | /* Double the time defined by MIN_TIME_TO_RESPOND_WITH_BUSY */ | ||
| 20 | #define UCSI_TIMEOUT_MS 20 | ||
| 21 | |||
| 22 | enum ucsi_status { | ||
| 23 | UCSI_IDLE = 0, | ||
| 24 | UCSI_BUSY, | ||
| 25 | UCSI_ERROR, | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct ucsi_connector { | ||
| 29 | int num; | ||
| 30 | struct ucsi *ucsi; | ||
| 31 | struct work_struct work; | ||
| 32 | struct ucsi_connector_capability cap; | ||
| 33 | }; | ||
| 34 | |||
| 35 | struct ucsi { | ||
| 36 | struct device *dev; | ||
| 37 | struct ucsi_data __iomem *data; | ||
| 38 | |||
| 39 | enum ucsi_status status; | ||
| 40 | struct completion complete; | ||
| 41 | struct ucsi_capability cap; | ||
| 42 | struct ucsi_connector *connector; | ||
| 43 | |||
| 44 | /* device lock */ | ||
| 45 | spinlock_t dev_lock; | ||
| 46 | |||
| 47 | /* PPM Communication lock */ | ||
| 48 | struct mutex ppm_lock; | ||
| 49 | |||
| 50 | /* PPM communication flags */ | ||
| 51 | unsigned long flags; | ||
| 52 | #define EVENT_PENDING 0 | ||
| 53 | #define COMMAND_PENDING 1 | ||
| 54 | }; | ||
| 55 | |||
| 56 | static int ucsi_acpi_cmd(struct ucsi *ucsi, struct ucsi_control *ctrl) | ||
| 57 | { | ||
| 58 | uuid_le uuid = UUID_LE(0x6f8398c2, 0x7ca4, 0x11e4, | ||
| 59 | 0xad, 0x36, 0x63, 0x10, 0x42, 0xb5, 0x00, 0x8f); | ||
| 60 | union acpi_object *obj; | ||
| 61 | |||
| 62 | ucsi->data->ctrl.raw_cmd = ctrl->raw_cmd; | ||
| 63 | |||
| 64 | obj = acpi_evaluate_dsm(ACPI_HANDLE(ucsi->dev), uuid.b, 1, 1, NULL); | ||
| 65 | if (!obj) { | ||
| 66 | dev_err(ucsi->dev, "%s: failed to evaluate _DSM\n", __func__); | ||
| 67 | return -EIO; | ||
| 68 | } | ||
| 69 | |||
| 70 | ACPI_FREE(obj); | ||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | |||
| 74 | static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data) | ||
| 75 | { | ||
| 76 | struct ucsi *ucsi = data; | ||
| 77 | struct ucsi_cci *cci; | ||
| 78 | |||
| 79 | spin_lock(&ucsi->dev_lock); | ||
| 80 | |||
| 81 | ucsi->status = UCSI_IDLE; | ||
| 82 | cci = &ucsi->data->cci; | ||
| 83 | |||
| 84 | /* | ||
| 85 | * REVISIT: This is not documented behavior, but all known PPMs ACK | ||
| 86 | * asynchronous events by sending notification with cleared CCI. | ||
| 87 | */ | ||
| 88 | if (!ucsi->data->raw_cci) { | ||
| 89 | if (test_bit(EVENT_PENDING, &ucsi->flags)) | ||
| 90 | complete(&ucsi->complete); | ||
| 91 | else | ||
| 92 | dev_WARN(ucsi->dev, "spurious notification\n"); | ||
| 93 | goto out_unlock; | ||
| 94 | } | ||
| 95 | |||
| 96 | if (test_bit(COMMAND_PENDING, &ucsi->flags)) { | ||
| 97 | if (cci->busy) { | ||
| 98 | ucsi->status = UCSI_BUSY; | ||
| 99 | complete(&ucsi->complete); | ||
| 100 | |||
| 101 | goto out_unlock; | ||
| 102 | } else if (cci->ack_complete || cci->cmd_complete) { | ||
| 103 | /* Error Indication is only valid with commands */ | ||
| 104 | if (cci->error && cci->cmd_complete) | ||
| 105 | ucsi->status = UCSI_ERROR; | ||
| 106 | |||
| 107 | ucsi->data->ctrl.raw_cmd = 0; | ||
| 108 | complete(&ucsi->complete); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | if (cci->connector_change) { | ||
| 113 | struct ucsi_connector *con; | ||
| 114 | |||
| 115 | /* | ||
| 116 | * This is workaround for buggy PPMs that create asynchronous | ||
| 117 | * event notifications before OPM has enabled them. | ||
| 118 | */ | ||
| 119 | if (!ucsi->connector) | ||
| 120 | goto out_unlock; | ||
| 121 | |||
| 122 | con = ucsi->connector + (cci->connector_change - 1); | ||
| 123 | |||
| 124 | /* | ||
| 125 | * PPM will not clear the connector specific bit in Connector | ||
| 126 | * Change Indication field of CCI until the driver has ACK it, | ||
| 127 | * and the driver can not ACK it before it has been processed. | ||
| 128 | * The PPM will not generate new events before the first has | ||
| 129 | * been acknowledged, even if they are for an other connector. | ||
| 130 | * So only one event at a time. | ||
| 131 | */ | ||
| 132 | if (!test_and_set_bit(EVENT_PENDING, &ucsi->flags)) | ||
| 133 | schedule_work(&con->work); | ||
| 134 | } | ||
| 135 | out_unlock: | ||
| 136 | spin_unlock(&ucsi->dev_lock); | ||
| 137 | } | ||
| 138 | |||
| 139 | static int ucsi_ack(struct ucsi *ucsi, u8 cmd) | ||
| 140 | { | ||
| 141 | struct ucsi_control ctrl; | ||
| 142 | int ret; | ||
| 143 | |||
| 144 | ctrl.cmd.cmd = UCSI_ACK_CC_CI; | ||
| 145 | ctrl.cmd.length = 0; | ||
| 146 | ctrl.cmd.data = cmd; | ||
| 147 | ret = ucsi_acpi_cmd(ucsi, &ctrl); | ||
| 148 | if (ret) | ||
| 149 | return ret; | ||
| 150 | |||
| 151 | /* Waiting for ACK also with ACK CMD for now */ | ||
| 152 | ret = wait_for_completion_timeout(&ucsi->complete, | ||
| 153 | msecs_to_jiffies(UCSI_TIMEOUT_MS)); | ||
| 154 | if (!ret) | ||
| 155 | return -ETIMEDOUT; | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | static int ucsi_run_cmd(struct ucsi *ucsi, struct ucsi_control *ctrl, | ||
| 160 | void *data, size_t size) | ||
| 161 | { | ||
| 162 | u16 err_value = 0; | ||
| 163 | int ret; | ||
| 164 | |||
| 165 | set_bit(COMMAND_PENDING, &ucsi->flags); | ||
| 166 | |||
| 167 | ret = ucsi_acpi_cmd(ucsi, ctrl); | ||
| 168 | if (ret) | ||
| 169 | goto err_clear_flag; | ||
| 170 | |||
| 171 | ret = wait_for_completion_timeout(&ucsi->complete, | ||
| 172 | msecs_to_jiffies(UCSI_TIMEOUT_MS)); | ||
| 173 | if (!ret) { | ||
| 174 | ret = -ETIMEDOUT; | ||
| 175 | goto err_clear_flag; | ||
| 176 | } | ||
| 177 | |||
| 178 | switch (ucsi->status) { | ||
| 179 | case UCSI_IDLE: | ||
| 180 | if (data) | ||
| 181 | memcpy(data, ucsi->data->message_in, size); | ||
| 182 | |||
| 183 | ret = ucsi_ack(ucsi, UCSI_ACK_CMD); | ||
| 184 | break; | ||
| 185 | case UCSI_BUSY: | ||
| 186 | /* The caller decides whether to cancel or not */ | ||
| 187 | ret = -EBUSY; | ||
| 188 | goto err_clear_flag; | ||
| 189 | case UCSI_ERROR: | ||
| 190 | ret = ucsi_ack(ucsi, UCSI_ACK_CMD); | ||
| 191 | if (ret) | ||
| 192 | goto err_clear_flag; | ||
| 193 | |||
| 194 | ctrl->cmd.cmd = UCSI_GET_ERROR_STATUS; | ||
| 195 | ctrl->cmd.length = 0; | ||
| 196 | ctrl->cmd.data = 0; | ||
| 197 | ret = ucsi_acpi_cmd(ucsi, ctrl); | ||
| 198 | if (ret) | ||
| 199 | goto err_clear_flag; | ||
| 200 | |||
| 201 | ret = wait_for_completion_timeout(&ucsi->complete, | ||
| 202 | msecs_to_jiffies(UCSI_TIMEOUT_MS)); | ||
| 203 | if (!ret) { | ||
| 204 | ret = -ETIMEDOUT; | ||
| 205 | goto err_clear_flag; | ||
| 206 | } | ||
| 207 | |||
| 208 | memcpy(&err_value, ucsi->data->message_in, sizeof(err_value)); | ||
| 209 | |||
| 210 | /* Something has really gone wrong */ | ||
| 211 | if (WARN_ON(ucsi->status == UCSI_ERROR)) { | ||
| 212 | ret = -ENODEV; | ||
| 213 | goto err_clear_flag; | ||
| 214 | } | ||
| 215 | |||
| 216 | ret = ucsi_ack(ucsi, UCSI_ACK_CMD); | ||
| 217 | if (ret) | ||
| 218 | goto err_clear_flag; | ||
| 219 | |||
| 220 | switch (err_value) { | ||
| 221 | case UCSI_ERROR_INCOMPATIBLE_PARTNER: | ||
| 222 | ret = -EOPNOTSUPP; | ||
| 223 | break; | ||
| 224 | case UCSI_ERROR_CC_COMMUNICATION_ERR: | ||
| 225 | ret = -ECOMM; | ||
| 226 | break; | ||
| 227 | case UCSI_ERROR_CONTRACT_NEGOTIATION_FAIL: | ||
| 228 | ret = -EIO; | ||
| 229 | break; | ||
| 230 | case UCSI_ERROR_DEAD_BATTERY: | ||
| 231 | dev_warn(ucsi->dev, "Dead battery condition!\n"); | ||
| 232 | ret = -EPERM; | ||
| 233 | break; | ||
| 234 | /* The following mean a bug in this driver */ | ||
| 235 | case UCSI_ERROR_INVALID_CON_NUM: | ||
| 236 | case UCSI_ERROR_UNREGONIZED_CMD: | ||
| 237 | case UCSI_ERROR_INVALID_CMD_ARGUMENT: | ||
| 238 | default: | ||
| 239 | dev_warn(ucsi->dev, | ||
| 240 | "%s: possible UCSI driver bug - error %hu\n", | ||
| 241 | __func__, err_value); | ||
| 242 | ret = -EINVAL; | ||
| 243 | break; | ||
| 244 | } | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | ctrl->raw_cmd = 0; | ||
| 248 | err_clear_flag: | ||
| 249 | clear_bit(COMMAND_PENDING, &ucsi->flags); | ||
| 250 | return ret; | ||
| 251 | } | ||
| 252 | |||
| 253 | static void ucsi_connector_change(struct work_struct *work) | ||
| 254 | { | ||
| 255 | struct ucsi_connector *con = container_of(work, struct ucsi_connector, | ||
| 256 | work); | ||
| 257 | struct ucsi_connector_status constat; | ||
| 258 | struct ucsi *ucsi = con->ucsi; | ||
| 259 | struct ucsi_control ctrl; | ||
| 260 | int ret; | ||
| 261 | |||
| 262 | mutex_lock(&ucsi->ppm_lock); | ||
| 263 | |||
| 264 | ctrl.cmd.cmd = UCSI_GET_CONNECTOR_STATUS; | ||
| 265 | ctrl.cmd.length = 0; | ||
| 266 | ctrl.cmd.data = con->num; | ||
| 267 | ret = ucsi_run_cmd(con->ucsi, &ctrl, &constat, sizeof(constat)); | ||
| 268 | if (ret) { | ||
| 269 | dev_err(ucsi->dev, "%s: failed to read connector status (%d)\n", | ||
| 270 | __func__, ret); | ||
| 271 | goto out_ack_event; | ||
| 272 | } | ||
| 273 | |||
| 274 | /* Ignoring disconnections and Alternate Modes */ | ||
| 275 | if (!constat.connected || !(constat.change & | ||
| 276 | (UCSI_CONSTAT_PARTNER_CHANGE | UCSI_CONSTAT_CONNECT_CHANGE)) || | ||
| 277 | constat.partner_flags & UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE) | ||
| 278 | goto out_ack_event; | ||
| 279 | |||
| 280 | /* If the partner got USB Host role, attempting swap */ | ||
| 281 | if (constat.partner_type & UCSI_CONSTAT_PARTNER_TYPE_DFP) { | ||
| 282 | ctrl.uor.cmd = UCSI_SET_UOR; | ||
| 283 | ctrl.uor.con_num = con->num; | ||
| 284 | ctrl.uor.role = UCSI_UOR_ROLE_DFP; | ||
| 285 | |||
| 286 | ret = ucsi_run_cmd(con->ucsi, &ctrl, NULL, 0); | ||
| 287 | if (ret) | ||
| 288 | dev_err(ucsi->dev, "%s: failed to swap role (%d)\n", | ||
| 289 | __func__, ret); | ||
| 290 | } | ||
| 291 | out_ack_event: | ||
| 292 | ucsi_ack(ucsi, UCSI_ACK_EVENT); | ||
| 293 | clear_bit(EVENT_PENDING, &ucsi->flags); | ||
| 294 | mutex_unlock(&ucsi->ppm_lock); | ||
| 295 | } | ||
| 296 | |||
| 297 | static int ucsi_reset_ppm(struct ucsi *ucsi) | ||
| 298 | { | ||
| 299 | int timeout = UCSI_TIMEOUT_MS; | ||
| 300 | struct ucsi_control ctrl; | ||
| 301 | int ret; | ||
| 302 | |||
| 303 | memset(&ctrl, 0, sizeof(ctrl)); | ||
| 304 | ctrl.cmd.cmd = UCSI_PPM_RESET; | ||
| 305 | ret = ucsi_acpi_cmd(ucsi, &ctrl); | ||
| 306 | if (ret) | ||
| 307 | return ret; | ||
| 308 | |||
| 309 | /* There is no quarantee the PPM will ever set the RESET_COMPLETE bit */ | ||
| 310 | while (!ucsi->data->cci.reset_complete && timeout--) | ||
| 311 | usleep_range(1000, 2000); | ||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | |||
| 315 | static int ucsi_init(struct ucsi *ucsi) | ||
| 316 | { | ||
| 317 | struct ucsi_connector *con; | ||
| 318 | struct ucsi_control ctrl; | ||
| 319 | int ret; | ||
| 320 | int i; | ||
| 321 | |||
| 322 | init_completion(&ucsi->complete); | ||
| 323 | spin_lock_init(&ucsi->dev_lock); | ||
| 324 | mutex_init(&ucsi->ppm_lock); | ||
| 325 | |||
| 326 | /* Reset the PPM */ | ||
| 327 | ret = ucsi_reset_ppm(ucsi); | ||
| 328 | if (ret) | ||
| 329 | return ret; | ||
| 330 | |||
| 331 | /* | ||
| 332 | * REVISIT: Executing second reset to WA an issue seen on some of the | ||
| 333 | * Broxton based platforms, where the first reset puts the PPM into a | ||
| 334 | * state where it's unable to recognise some of the commands. | ||
| 335 | */ | ||
| 336 | ret = ucsi_reset_ppm(ucsi); | ||
| 337 | if (ret) | ||
| 338 | return ret; | ||
| 339 | |||
| 340 | mutex_lock(&ucsi->ppm_lock); | ||
| 341 | |||
| 342 | /* Enable basic notifications */ | ||
| 343 | ctrl.cmd.cmd = UCSI_SET_NOTIFICATION_ENABLE; | ||
| 344 | ctrl.cmd.length = 0; | ||
| 345 | ctrl.cmd.data = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR; | ||
| 346 | ret = ucsi_run_cmd(ucsi, &ctrl, NULL, 0); | ||
| 347 | if (ret) | ||
| 348 | goto err_reset; | ||
| 349 | |||
| 350 | /* Get PPM capabilities */ | ||
| 351 | ctrl.cmd.cmd = UCSI_GET_CAPABILITY; | ||
| 352 | ret = ucsi_run_cmd(ucsi, &ctrl, &ucsi->cap, sizeof(ucsi->cap)); | ||
| 353 | if (ret) | ||
| 354 | goto err_reset; | ||
| 355 | |||
| 356 | if (!ucsi->cap.num_connectors) { | ||
| 357 | ret = -ENODEV; | ||
| 358 | goto err_reset; | ||
| 359 | } | ||
| 360 | |||
| 361 | ucsi->connector = devm_kcalloc(ucsi->dev, ucsi->cap.num_connectors, | ||
| 362 | sizeof(*ucsi->connector), GFP_KERNEL); | ||
| 363 | if (!ucsi->connector) { | ||
| 364 | ret = -ENOMEM; | ||
| 365 | goto err_reset; | ||
| 366 | } | ||
| 367 | |||
| 368 | for (i = 1, con = ucsi->connector; i < ucsi->cap.num_connectors + 1; | ||
| 369 | i++, con++) { | ||
| 370 | /* Get connector capability */ | ||
| 371 | ctrl.cmd.cmd = UCSI_GET_CONNECTOR_CAPABILITY; | ||
| 372 | ctrl.cmd.data = i; | ||
| 373 | ret = ucsi_run_cmd(ucsi, &ctrl, &con->cap, sizeof(con->cap)); | ||
| 374 | if (ret) | ||
| 375 | goto err_reset; | ||
| 376 | |||
| 377 | con->num = i; | ||
| 378 | con->ucsi = ucsi; | ||
| 379 | INIT_WORK(&con->work, ucsi_connector_change); | ||
| 380 | } | ||
| 381 | |||
| 382 | /* Enable all notifications */ | ||
| 383 | ctrl.cmd.cmd = UCSI_SET_NOTIFICATION_ENABLE; | ||
| 384 | ctrl.cmd.data = UCSI_ENABLE_NTFY_ALL; | ||
| 385 | ret = ucsi_run_cmd(ucsi, &ctrl, NULL, 0); | ||
| 386 | if (ret < 0) | ||
| 387 | goto err_reset; | ||
| 388 | |||
| 389 | mutex_unlock(&ucsi->ppm_lock); | ||
| 390 | return 0; | ||
| 391 | err_reset: | ||
| 392 | ucsi_reset_ppm(ucsi); | ||
| 393 | mutex_unlock(&ucsi->ppm_lock); | ||
| 394 | return ret; | ||
| 395 | } | ||
| 396 | |||
| 397 | static int ucsi_acpi_probe(struct platform_device *pdev) | ||
| 398 | { | ||
| 399 | struct resource *res; | ||
| 400 | acpi_status status; | ||
| 401 | struct ucsi *ucsi; | ||
| 402 | int ret; | ||
| 403 | |||
| 404 | ucsi = devm_kzalloc(&pdev->dev, sizeof(*ucsi), GFP_KERNEL); | ||
| 405 | if (!ucsi) | ||
| 406 | return -ENOMEM; | ||
| 407 | |||
| 408 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 409 | if (!res) { | ||
| 410 | dev_err(&pdev->dev, "missing memory resource\n"); | ||
| 411 | return -ENODEV; | ||
| 412 | } | ||
| 413 | |||
| 414 | /* | ||
| 415 | * NOTE: ACPI has claimed the memory region as it's also an Operation | ||
| 416 | * Region. It's not possible to request it in the driver. | ||
| 417 | */ | ||
| 418 | ucsi->data = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | ||
| 419 | if (!ucsi->data) | ||
| 420 | return -ENOMEM; | ||
| 421 | |||
| 422 | ucsi->dev = &pdev->dev; | ||
| 423 | |||
| 424 | status = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev), | ||
| 425 | ACPI_ALL_NOTIFY, | ||
| 426 | ucsi_acpi_notify, ucsi); | ||
| 427 | if (ACPI_FAILURE(status)) | ||
| 428 | return -ENODEV; | ||
| 429 | |||
| 430 | ret = ucsi_init(ucsi); | ||
| 431 | if (ret) { | ||
| 432 | acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev), | ||
| 433 | ACPI_ALL_NOTIFY, | ||
| 434 | ucsi_acpi_notify); | ||
| 435 | return ret; | ||
| 436 | } | ||
| 437 | |||
| 438 | platform_set_drvdata(pdev, ucsi); | ||
| 439 | return 0; | ||
| 440 | } | ||
| 441 | |||
| 442 | static int ucsi_acpi_remove(struct platform_device *pdev) | ||
| 443 | { | ||
| 444 | struct ucsi *ucsi = platform_get_drvdata(pdev); | ||
| 445 | |||
| 446 | acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev), | ||
| 447 | ACPI_ALL_NOTIFY, ucsi_acpi_notify); | ||
| 448 | |||
| 449 | /* Make sure there are no events in the middle of being processed */ | ||
| 450 | if (wait_on_bit_timeout(&ucsi->flags, EVENT_PENDING, | ||
| 451 | TASK_UNINTERRUPTIBLE, | ||
| 452 | msecs_to_jiffies(UCSI_TIMEOUT_MS))) | ||
| 453 | dev_WARN(ucsi->dev, "%s: Events still pending\n", __func__); | ||
| 454 | |||
| 455 | ucsi_reset_ppm(ucsi); | ||
| 456 | return 0; | ||
| 457 | } | ||
| 458 | |||
| 459 | static const struct acpi_device_id ucsi_acpi_match[] = { | ||
| 460 | { "PNP0CA0", 0 }, | ||
| 461 | { }, | ||
| 462 | }; | ||
| 463 | MODULE_DEVICE_TABLE(acpi, ucsi_acpi_match); | ||
| 464 | |||
| 465 | static struct platform_driver ucsi_acpi_platform_driver = { | ||
| 466 | .driver = { | ||
| 467 | .name = "ucsi_acpi", | ||
| 468 | .acpi_match_table = ACPI_PTR(ucsi_acpi_match), | ||
| 469 | }, | ||
| 470 | .probe = ucsi_acpi_probe, | ||
| 471 | .remove = ucsi_acpi_remove, | ||
| 472 | }; | ||
| 473 | |||
| 474 | module_platform_driver(ucsi_acpi_platform_driver); | ||
| 475 | |||
| 476 | MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>"); | ||
| 477 | MODULE_LICENSE("GPL v2"); | ||
| 478 | MODULE_DESCRIPTION("USB Type-C System Software Interface (UCSI) driver"); | ||
diff --git a/drivers/usb/misc/ucsi.h b/drivers/usb/misc/ucsi.h new file mode 100644 index 000000000000..6dd11d1fe225 --- /dev/null +++ b/drivers/usb/misc/ucsi.h | |||
| @@ -0,0 +1,215 @@ | |||
| 1 | |||
| 2 | #include <linux/types.h> | ||
| 3 | |||
| 4 | /* -------------------------------------------------------------------------- */ | ||
| 5 | |||
| 6 | /* Command Status and Connector Change Indication (CCI) data structure */ | ||
| 7 | struct ucsi_cci { | ||
| 8 | unsigned int RESERVED1:1; | ||
| 9 | unsigned int connector_change:7; | ||
| 10 | u8 data_length; | ||
| 11 | unsigned int RESERVED9:9; | ||
| 12 | unsigned int not_supported:1; | ||
| 13 | unsigned int cancel_complete:1; | ||
| 14 | unsigned int reset_complete:1; | ||
| 15 | unsigned int busy:1; | ||
| 16 | unsigned int ack_complete:1; | ||
| 17 | unsigned int error:1; | ||
| 18 | unsigned int cmd_complete:1; | ||
| 19 | } __packed; | ||
| 20 | |||
| 21 | /* Default fields in CONTROL data structure */ | ||
| 22 | struct ucsi_command { | ||
| 23 | u8 cmd; | ||
| 24 | u8 length; | ||
| 25 | u64 data:48; | ||
| 26 | } __packed; | ||
| 27 | |||
| 28 | /* Set USB Operation Mode Command structure */ | ||
| 29 | struct ucsi_uor_cmd { | ||
| 30 | u8 cmd; | ||
| 31 | u8 length; | ||
| 32 | u64 con_num:7; | ||
| 33 | u64 role:3; | ||
| 34 | #define UCSI_UOR_ROLE_DFP BIT(0) | ||
| 35 | #define UCSI_UOR_ROLE_UFP BIT(1) | ||
| 36 | #define UCSI_UOR_ROLE_DRP BIT(2) | ||
| 37 | u64 data:38; | ||
| 38 | } __packed; | ||
| 39 | |||
| 40 | struct ucsi_control { | ||
| 41 | union { | ||
| 42 | u64 raw_cmd; | ||
| 43 | struct ucsi_command cmd; | ||
| 44 | struct ucsi_uor_cmd uor; | ||
| 45 | }; | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct ucsi_data { | ||
| 49 | u16 version; | ||
| 50 | u16 RESERVED; | ||
| 51 | union { | ||
| 52 | u32 raw_cci; | ||
| 53 | struct ucsi_cci cci; | ||
| 54 | }; | ||
| 55 | struct ucsi_control ctrl; | ||
| 56 | u32 message_in[4]; | ||
| 57 | u32 message_out[4]; | ||
| 58 | } __packed; | ||
| 59 | |||
| 60 | /* Commands */ | ||
| 61 | #define UCSI_PPM_RESET 0x01 | ||
| 62 | #define UCSI_CANCEL 0x02 | ||
| 63 | #define UCSI_CONNECTOR_RESET 0x03 | ||
| 64 | #define UCSI_ACK_CC_CI 0x04 | ||
| 65 | #define UCSI_SET_NOTIFICATION_ENABLE 0x05 | ||
| 66 | #define UCSI_GET_CAPABILITY 0x06 | ||
| 67 | #define UCSI_GET_CONNECTOR_CAPABILITY 0x07 | ||
| 68 | #define UCSI_SET_UOM 0x08 | ||
| 69 | #define UCSI_SET_UOR 0x09 | ||
| 70 | #define UCSI_SET_PDM 0x0A | ||
| 71 | #define UCSI_SET_PDR 0x0B | ||
| 72 | #define UCSI_GET_ALTERNATE_MODES 0x0C | ||
| 73 | #define UCSI_GET_CAM_SUPPORTED 0x0D | ||
| 74 | #define UCSI_GET_CURRENT_CAM 0x0E | ||
| 75 | #define UCSI_SET_NEW_CAM 0x0F | ||
| 76 | #define UCSI_GET_PDOS 0x10 | ||
| 77 | #define UCSI_GET_CABLE_PROPERTY 0x11 | ||
| 78 | #define UCSI_GET_CONNECTOR_STATUS 0x12 | ||
| 79 | #define UCSI_GET_ERROR_STATUS 0x13 | ||
| 80 | |||
| 81 | /* ACK_CC_CI commands */ | ||
| 82 | #define UCSI_ACK_EVENT 1 | ||
| 83 | #define UCSI_ACK_CMD 2 | ||
| 84 | |||
| 85 | /* Bits for SET_NOTIFICATION_ENABLE command */ | ||
| 86 | #define UCSI_ENABLE_NTFY_CMD_COMPLETE BIT(0) | ||
| 87 | #define UCSI_ENABLE_NTFY_EXT_PWR_SRC_CHANGE BIT(1) | ||
| 88 | #define UCSI_ENABLE_NTFY_PWR_OPMODE_CHANGE BIT(2) | ||
| 89 | #define UCSI_ENABLE_NTFY_CAP_CHANGE BIT(5) | ||
| 90 | #define UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE BIT(6) | ||
| 91 | #define UCSI_ENABLE_NTFY_PD_RESET_COMPLETE BIT(7) | ||
| 92 | #define UCSI_ENABLE_NTFY_CAM_CHANGE BIT(8) | ||
| 93 | #define UCSI_ENABLE_NTFY_BAT_STATUS_CHANGE BIT(9) | ||
| 94 | #define UCSI_ENABLE_NTFY_PARTNER_CHANGE BIT(11) | ||
| 95 | #define UCSI_ENABLE_NTFY_PWR_DIR_CHANGE BIT(12) | ||
| 96 | #define UCSI_ENABLE_NTFY_CONNECTOR_CHANGE BIT(14) | ||
| 97 | #define UCSI_ENABLE_NTFY_ERROR BIT(15) | ||
| 98 | #define UCSI_ENABLE_NTFY_ALL 0xdbe7 | ||
| 99 | |||
| 100 | /* Error information returned by PPM in response to GET_ERROR_STATUS command. */ | ||
| 101 | #define UCSI_ERROR_UNREGONIZED_CMD BIT(0) | ||
| 102 | #define UCSI_ERROR_INVALID_CON_NUM BIT(1) | ||
| 103 | #define UCSI_ERROR_INVALID_CMD_ARGUMENT BIT(2) | ||
| 104 | #define UCSI_ERROR_INCOMPATIBLE_PARTNER BIT(3) | ||
| 105 | #define UCSI_ERROR_CC_COMMUNICATION_ERR BIT(4) | ||
| 106 | #define UCSI_ERROR_DEAD_BATTERY BIT(5) | ||
| 107 | #define UCSI_ERROR_CONTRACT_NEGOTIATION_FAIL BIT(6) | ||
| 108 | |||
| 109 | /* Data structure filled by PPM in response to GET_CAPABILITY command. */ | ||
| 110 | struct ucsi_capability { | ||
| 111 | u32 attributes; | ||
| 112 | #define UCSI_CAP_ATTR_DISABLE_STATE BIT(0) | ||
| 113 | #define UCSI_CAP_ATTR_BATTERY_CHARGING BIT(1) | ||
| 114 | #define UCSI_CAP_ATTR_USB_PD BIT(2) | ||
| 115 | #define UCSI_CAP_ATTR_TYPEC_CURRENT BIT(6) | ||
| 116 | #define UCSI_CAP_ATTR_POWER_AC_SUPPLY BIT(8) | ||
| 117 | #define UCSI_CAP_ATTR_POWER_OTHER BIT(10) | ||
| 118 | #define UCSI_CAP_ATTR_POWER_VBUS BIT(14) | ||
| 119 | u8 num_connectors; | ||
| 120 | u32 features:24; | ||
| 121 | #define UCSI_CAP_SET_UOM BIT(0) | ||
| 122 | #define UCSI_CAP_SET_PDM BIT(1) | ||
| 123 | #define UCSI_CAP_ALT_MODE_DETAILS BIT(2) | ||
| 124 | #define UCSI_CAP_ALT_MODE_OVERRIDE BIT(3) | ||
| 125 | #define UCSI_CAP_PDO_DETAILS BIT(4) | ||
| 126 | #define UCSI_CAP_CABLE_DETAILS BIT(5) | ||
| 127 | #define UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS BIT(6) | ||
| 128 | #define UCSI_CAP_PD_RESET BIT(7) | ||
| 129 | u8 num_alt_modes; | ||
| 130 | u8 RESERVED; | ||
| 131 | u16 bc_version; | ||
| 132 | u16 pd_version; | ||
| 133 | u16 typec_version; | ||
| 134 | } __packed; | ||
| 135 | |||
| 136 | /* Data structure filled by PPM in response to GET_CONNECTOR_CAPABILITY cmd. */ | ||
| 137 | struct ucsi_connector_capability { | ||
| 138 | u8 op_mode; | ||
| 139 | #define UCSI_CONCAP_OPMODE_DFP BIT(0) | ||
| 140 | #define UCSI_CONCAP_OPMODE_UFP BIT(1) | ||
| 141 | #define UCSI_CONCAP_OPMODE_DRP BIT(2) | ||
| 142 | #define UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY BIT(3) | ||
| 143 | #define UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY BIT(4) | ||
| 144 | #define UCSI_CONCAP_OPMODE_USB2 BIT(5) | ||
| 145 | #define UCSI_CONCAP_OPMODE_USB3 BIT(6) | ||
| 146 | #define UCSI_CONCAP_OPMODE_ALT_MODE BIT(7) | ||
| 147 | u8 provider:1; | ||
| 148 | u8 consumer:1; | ||
| 149 | } __packed; | ||
| 150 | |||
| 151 | /* Data structure filled by PPM in response to GET_CABLE_PROPERTY command. */ | ||
| 152 | struct ucsi_cable_property { | ||
| 153 | u16 speed_supported; | ||
| 154 | u8 current_capability; | ||
| 155 | u8 vbus_in_cable:1; | ||
| 156 | u8 active_cable:1; | ||
| 157 | u8 directionality:1; | ||
| 158 | u8 plug_type:2; | ||
| 159 | #define UCSI_CABLE_PROPERTY_PLUG_TYPE_A 0 | ||
| 160 | #define UCSI_CABLE_PROPERTY_PLUG_TYPE_B 1 | ||
| 161 | #define UCSI_CABLE_PROPERTY_PLUG_TYPE_C 2 | ||
| 162 | #define UCSI_CABLE_PROPERTY_PLUG_OTHER 3 | ||
| 163 | u8 mode_support:1; | ||
| 164 | u8 RESERVED_2:2; | ||
| 165 | u8 latency:4; | ||
| 166 | u8 RESERVED_4:4; | ||
| 167 | } __packed; | ||
| 168 | |||
| 169 | /* Data structure filled by PPM in response to GET_CONNECTOR_STATUS command. */ | ||
| 170 | struct ucsi_connector_status { | ||
| 171 | u16 change; | ||
| 172 | #define UCSI_CONSTAT_EXT_SUPPLY_CHANGE BIT(1) | ||
| 173 | #define UCSI_CONSTAT_POWER_OPMODE_CHANGE BIT(2) | ||
| 174 | #define UCSI_CONSTAT_PDOS_CHANGE BIT(5) | ||
| 175 | #define UCSI_CONSTAT_POWER_LEVEL_CHANGE BIT(6) | ||
| 176 | #define UCSI_CONSTAT_PD_RESET_COMPLETE BIT(7) | ||
| 177 | #define UCSI_CONSTAT_CAM_CHANGE BIT(8) | ||
| 178 | #define UCSI_CONSTAT_BC_CHANGE BIT(9) | ||
| 179 | #define UCSI_CONSTAT_PARTNER_CHANGE BIT(11) | ||
| 180 | #define UCSI_CONSTAT_POWER_DIR_CHANGE BIT(12) | ||
| 181 | #define UCSI_CONSTAT_CONNECT_CHANGE BIT(14) | ||
| 182 | #define UCSI_CONSTAT_ERROR BIT(15) | ||
| 183 | u16 pwr_op_mode:3; | ||
| 184 | #define UCSI_CONSTAT_PWR_OPMODE_NONE 0 | ||
| 185 | #define UCSI_CONSTAT_PWR_OPMODE_DEFAULT 1 | ||
| 186 | #define UCSI_CONSTAT_PWR_OPMODE_BC 2 | ||
| 187 | #define UCSI_CONSTAT_PWR_OPMODE_PD 3 | ||
| 188 | #define UCSI_CONSTAT_PWR_OPMODE_TYPEC1_3 4 | ||
| 189 | #define UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0 5 | ||
| 190 | u16 connected:1; | ||
| 191 | u16 pwr_dir:1; | ||
| 192 | u16 partner_flags:8; | ||
| 193 | #define UCSI_CONSTAT_PARTNER_FLAG_USB BIT(0) | ||
| 194 | #define UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE BIT(1) | ||
| 195 | u16 partner_type:3; | ||
| 196 | #define UCSI_CONSTAT_PARTNER_TYPE_DFP 1 | ||
| 197 | #define UCSI_CONSTAT_PARTNER_TYPE_UFP 2 | ||
| 198 | #define UCSI_CONSTAT_PARTNER_TYPE_CABLE_NO_UFP 3 /* Powered Cable */ | ||
| 199 | #define UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP 4 /* Powered Cable */ | ||
| 200 | #define UCSI_CONSTAT_PARTNER_TYPE_DEBUG 5 | ||
| 201 | #define UCSI_CONSTAT_PARTNER_TYPE_AUDIO 6 | ||
| 202 | u32 request_data_obj; | ||
| 203 | u8 bc_status:2; | ||
| 204 | #define UCSI_CONSTAT_BC_NOT_CHARGING 0 | ||
| 205 | #define UCSI_CONSTAT_BC_NOMINAL_CHARGING 1 | ||
| 206 | #define UCSI_CONSTAT_BC_SLOW_CHARGING 2 | ||
| 207 | #define UCSI_CONSTAT_BC_TRICKLE_CHARGING 3 | ||
| 208 | u8 provider_cap_limit_reason:4; | ||
| 209 | #define UCSI_CONSTAT_CAP_PWR_LOWERED 0 | ||
| 210 | #define UCSI_CONSTAT_CAP_PWR_BUDGET_LIMIT 1 | ||
| 211 | u8 RESERVED:2; | ||
| 212 | } __packed; | ||
| 213 | |||
| 214 | /* -------------------------------------------------------------------------- */ | ||
| 215 | |||
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 92fdb6e9faff..6b978f04b8d7 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
| @@ -287,6 +287,9 @@ static struct urb *usbtest_alloc_urb( | |||
| 287 | if (usb_pipein(pipe)) | 287 | if (usb_pipein(pipe)) |
| 288 | urb->transfer_flags |= URB_SHORT_NOT_OK; | 288 | urb->transfer_flags |= URB_SHORT_NOT_OK; |
| 289 | 289 | ||
| 290 | if ((bytes + offset) == 0) | ||
| 291 | return urb; | ||
| 292 | |||
| 290 | if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) | 293 | if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) |
| 291 | urb->transfer_buffer = usb_alloc_coherent(udev, bytes + offset, | 294 | urb->transfer_buffer = usb_alloc_coherent(udev, bytes + offset, |
| 292 | GFP_KERNEL, &urb->transfer_dma); | 295 | GFP_KERNEL, &urb->transfer_dma); |
| @@ -529,6 +532,7 @@ static struct scatterlist * | |||
| 529 | alloc_sglist(int nents, int max, int vary, struct usbtest_dev *dev, int pipe) | 532 | alloc_sglist(int nents, int max, int vary, struct usbtest_dev *dev, int pipe) |
| 530 | { | 533 | { |
| 531 | struct scatterlist *sg; | 534 | struct scatterlist *sg; |
| 535 | unsigned int n_size = 0; | ||
| 532 | unsigned i; | 536 | unsigned i; |
| 533 | unsigned size = max; | 537 | unsigned size = max; |
| 534 | unsigned maxpacket = | 538 | unsigned maxpacket = |
| @@ -561,7 +565,8 @@ alloc_sglist(int nents, int max, int vary, struct usbtest_dev *dev, int pipe) | |||
| 561 | break; | 565 | break; |
| 562 | case 1: | 566 | case 1: |
| 563 | for (j = 0; j < size; j++) | 567 | for (j = 0; j < size; j++) |
| 564 | *buf++ = (u8) ((j % maxpacket) % 63); | 568 | *buf++ = (u8) (((j + n_size) % maxpacket) % 63); |
| 569 | n_size += size; | ||
| 565 | break; | 570 | break; |
| 566 | } | 571 | } |
| 567 | 572 | ||
