qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/kraxel/tags/usb-20180821-pull-request' into staging

usb: mtp write support, bugfixes.

# gpg: Signature made Tue 21 Aug 2018 10:11:36 BST
# gpg: using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/usb-20180821-pull-request:
dev-mtp: rename x-root to rootdir
dev-mtp: Add support for > 4GB file transfers
dev-mtp: retry write for incomplete transfers
dev-mtp: fix buffer allocation for writing file contents
dev-mtp: add support for canceling transaction
ohci: Clear the interrupt counter for erroneous transfers
docs/usb2.txt: ehci has six ports

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+84 -16
+2 -2
docs/usb2.txt
··· 94 94 95 95 First you can (for all USB devices) specify the physical port where 96 96 the device will show up in the guest. This can be done using the 97 - "port" property. UHCI has two root ports (1,2). EHCI has four root 98 - ports (1-4), the emulated (1.1) USB hub has eight ports. 97 + "port" property. UHCI has two root ports (1,2). EHCI has six root 98 + ports (1-6), the emulated (1.1) USB hub has eight ports. 99 99 100 100 Plugging a tablet into UHCI port 1 works like this: 101 101
+79 -14
hw/usb/dev-mtp.c
··· 82 82 FMT_ASSOCIATION = 0x3001, 83 83 84 84 /* event codes */ 85 + EVT_CANCEL_TRANSACTION = 0x4001, 85 86 EVT_OBJ_ADDED = 0x4002, 86 87 EVT_OBJ_REMOVED = 0x4003, 87 88 EVT_OBJ_INFO_CHANGED = 0x4007, ··· 146 147 uint32_t trans; 147 148 uint64_t offset; 148 149 uint64_t length; 149 - uint32_t alloc; 150 + uint64_t alloc; 150 151 uint8_t *data; 151 152 bool first; 153 + /* Used for >4G file sizes */ 154 + bool pending; 155 + uint64_t cached_length; 152 156 int fd; 153 157 }; 154 158 ··· 1551 1555 int length, uint8_t *data) 1552 1556 { 1553 1557 int ret; 1558 + MTPState *s = USB_MTP(dev); 1559 + uint16_t *event = (uint16_t *)data; 1554 1560 1555 - ret = usb_desc_handle_control(dev, p, request, value, index, length, data); 1556 - if (ret >= 0) { 1557 - return; 1561 + switch (request) { 1562 + case ClassInterfaceOutRequest | 0x64: 1563 + if (*event == EVT_CANCEL_TRANSACTION) { 1564 + g_free(s->result); 1565 + s->result = NULL; 1566 + usb_mtp_data_free(s->data_in); 1567 + s->data_in = NULL; 1568 + if (s->write_pending) { 1569 + g_free(s->dataset.filename); 1570 + s->write_pending = false; 1571 + } 1572 + usb_mtp_data_free(s->data_out); 1573 + s->data_out = NULL; 1574 + } else { 1575 + p->status = USB_RET_STALL; 1576 + } 1577 + break; 1578 + default: 1579 + ret = usb_desc_handle_control(dev, p, request, 1580 + value, index, length, data); 1581 + if (ret >= 0) { 1582 + return; 1583 + } 1558 1584 } 1559 1585 1560 1586 trace_usb_mtp_stall(dev->addr, "unknown control request"); 1561 - p->status = USB_RET_STALL; 1562 1587 } 1563 1588 1564 1589 static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p) ··· 1580 1605 g_free(wstr); 1581 1606 } 1582 1607 1608 + /* Wrapper around write, returns 0 on failure */ 1609 + static uint64_t write_retry(int fd, void *buf, uint64_t size) 1610 + { 1611 + uint64_t bytes_left = size, ret; 1612 + 1613 + while (bytes_left > 0) { 1614 + ret = write(fd, buf, bytes_left); 1615 + if ((ret == -1) && (errno != EINTR || errno != EAGAIN || 1616 + errno != EWOULDBLOCK)) { 1617 + break; 1618 + } 1619 + bytes_left -= ret; 1620 + buf += ret; 1621 + } 1622 + 1623 + return size - bytes_left; 1624 + } 1625 + 1583 1626 static void usb_mtp_write_data(MTPState *s) 1584 1627 { 1585 1628 MTPData *d = s->data_out; 1586 1629 MTPObject *parent = 1587 1630 usb_mtp_object_lookup(s, s->dataset.parent_handle); 1588 1631 char *path = NULL; 1589 - int rc = -1; 1632 + uint64_t rc; 1590 1633 mode_t mask = 0644; 1591 1634 1592 1635 assert(d != NULL); ··· 1603 1646 d->fd = mkdir(path, mask); 1604 1647 goto free; 1605 1648 } 1606 - if (s->dataset.size < d->length) { 1649 + if ((s->dataset.size != 0xFFFFFFFF) && (s->dataset.size < d->length)) { 1607 1650 usb_mtp_queue_result(s, RES_STORE_FULL, d->trans, 1608 1651 0, 0, 0, 0); 1609 1652 goto done; ··· 1622 1665 goto success; 1623 1666 } 1624 1667 1625 - rc = write(d->fd, d->data, s->dataset.size); 1626 - if (rc == -1) { 1668 + rc = write_retry(d->fd, d->data, s->dataset.size); 1669 + if (!rc) { 1627 1670 usb_mtp_queue_result(s, RES_STORE_FULL, d->trans, 1628 1671 0, 0, 0, 0); 1629 1672 goto done; ··· 1699 1742 MTPData *d = s->data_out; 1700 1743 uint64_t dlen; 1701 1744 uint32_t data_len = p->iov.size; 1745 + uint64_t total_len; 1702 1746 1703 1747 if (!d) { 1704 1748 usb_mtp_queue_result(s, RES_INVALID_OBJECTINFO, 0, ··· 1707 1751 } 1708 1752 if (d->first) { 1709 1753 /* Total length of incoming data */ 1710 - d->length = cpu_to_le32(container->length) - sizeof(mtp_container); 1754 + total_len = cpu_to_le32(container->length) - sizeof(mtp_container); 1711 1755 /* Length of data in this packet */ 1712 1756 data_len -= sizeof(mtp_container); 1713 - usb_mtp_realloc(d, d->length); 1757 + usb_mtp_realloc(d, total_len); 1758 + d->length += total_len; 1714 1759 d->offset = 0; 1760 + d->cached_length = total_len; 1715 1761 d->first = false; 1762 + d->pending = false; 1763 + } 1764 + 1765 + if (d->pending) { 1766 + usb_mtp_realloc(d, d->cached_length); 1767 + d->length += d->cached_length; 1768 + d->pending = false; 1716 1769 } 1717 1770 1718 1771 if (d->length - d->offset > data_len) { 1719 1772 dlen = data_len; 1720 1773 } else { 1721 1774 dlen = d->length - d->offset; 1775 + /* Check for cached data for large files */ 1776 + if ((s->dataset.size == 0xFFFFFFFF) && (dlen < p->iov.size)) { 1777 + usb_mtp_realloc(d, p->iov.size - dlen); 1778 + d->length += p->iov.size - dlen; 1779 + dlen = p->iov.size; 1780 + } 1722 1781 } 1723 1782 1724 1783 switch (d->code) { ··· 1738 1797 case CMD_SEND_OBJECT: 1739 1798 usb_packet_copy(p, d->data + d->offset, dlen); 1740 1799 d->offset += dlen; 1741 - if (d->offset == d->length) { 1800 + if ((p->iov.size % 64) || !p->iov.size) { 1801 + assert((s->dataset.size == 0xFFFFFFFF) || 1802 + (s->dataset.size == d->length)); 1803 + 1742 1804 usb_mtp_write_data(s); 1743 1805 usb_mtp_data_free(s->data_out); 1744 1806 s->data_out = NULL; 1745 1807 return; 1808 + } 1809 + if (d->offset == d->length) { 1810 + d->pending = true; 1746 1811 } 1747 1812 break; 1748 1813 default: ··· 1953 2018 QTAILQ_INIT(&s->objects); 1954 2019 if (s->desc == NULL) { 1955 2020 if (s->root == NULL) { 1956 - error_setg(errp, "usb-mtp: x-root property must be configured"); 2021 + error_setg(errp, "usb-mtp: rootdir property must be configured"); 1957 2022 return; 1958 2023 } 1959 2024 s->desc = strrchr(s->root, '/'); ··· 1982 2047 }; 1983 2048 1984 2049 static Property mtp_properties[] = { 1985 - DEFINE_PROP_STRING("x-root", MTPState, root), 2050 + DEFINE_PROP_STRING("rootdir", MTPState, root), 1986 2051 DEFINE_PROP_STRING("desc", MTPState, desc), 1987 2052 DEFINE_PROP_BOOL("readonly", MTPState, readonly, true), 1988 2053 DEFINE_PROP_END_OF_LIST(),
+3
hw/usb/hcd-ohci.c
··· 1156 1156 OHCI_SET_BM(td.flags, TD_EC, 3); 1157 1157 break; 1158 1158 } 1159 + /* An error occured so we have to clear the interrupt counter. See 1160 + * spec at 6.4.4 on page 104 */ 1161 + ohci->done_count = 0; 1159 1162 } 1160 1163 ed->head |= OHCI_ED_H; 1161 1164 }