]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'staging-4.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 May 2017 16:02:27 +0000 (09:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 May 2017 16:02:27 +0000 (09:02 -0700)
Pull staging driver fixes from Greg KH:
 "Here are a number of staging driver fixes for 4.12-rc2

  Most of them are typec driver fixes found by reviewers and users of
  the code. There are also some removals of files no longer needed in
  the tree due to the ion driver rewrite in 4.12-rc1, as well as some
  wifi driver fixes. And to round it out, a MAINTAINERS file update.

  All have been in linux-next with no reported issues"

* tag 'staging-4.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (22 commits)
  MAINTAINERS: greybus-dev list is members-only
  staging: fsl-dpaa2/eth: add ETHERNET dependency
  staging: typec: fusb302: refactor resume retry mechanism
  staging: typec: fusb302: reset i2c_busy state in error
  staging: rtl8723bs: remove re-positioned call to kfree in os_dep/ioctl_cfg80211.c
  staging: rtl8192e: GetTs Fix invalid TID 7 warning.
  staging: rtl8192e: rtl92e_get_eeprom_size Fix read size of EPROM_CMD.
  staging: rtl8192e: fix 2 byte alignment of register BSSIDR.
  staging: rtl8192e: rtl92e_fill_tx_desc fix write to mapped out memory.
  staging: vc04_services: Fix bulk cache maintenance
  staging: ccree: remove extraneous spin_unlock_bh() in error handler
  staging: typec: Fix sparse warnings about incorrect types
  staging: typec: fusb302: do not free gpio from managed resource
  staging: typec: tcpm: Fix Port Power Role field in PS_RDY messages
  staging: typec: tcpm: Respond to Discover Identity commands
  staging: typec: tcpm: Set correct flags in PD request messages
  staging: typec: tcpm: Drop duplicate PD messages
  staging: typec: fusb302: Fix chip->vbus_present init value
  staging: typec: fusb302: Fix module autoload
  staging: typec: tcpci: declare private structure as static
  ...

15 files changed:
Documentation/devicetree/bindings/staging/ion/hi6220-ion.txt [deleted file]
MAINTAINERS
drivers/staging/android/ion/devicetree.txt [deleted file]
drivers/staging/ccree/ssi_request_mgr.c
drivers/staging/fsl-dpaa2/Kconfig
drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
drivers/staging/rtl8192e/rtl819x_TSProc.c
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
drivers/staging/typec/fusb302/fusb302.c
drivers/staging/typec/pd.h
drivers/staging/typec/pd_vdo.h
drivers/staging/typec/tcpci.c
drivers/staging/typec/tcpm.c
drivers/staging/typec/tcpm.h
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c

diff --git a/Documentation/devicetree/bindings/staging/ion/hi6220-ion.txt b/Documentation/devicetree/bindings/staging/ion/hi6220-ion.txt
deleted file mode 100644 (file)
index c59e27c..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-Hi6220 SoC ION
-===================================================================
-Required properties:
-- compatible : "hisilicon,hi6220-ion"
-- list of the ION heaps
-       - heap name : maybe heap_sys_user@0
-       - heap id   : id should be unique in the system.
-       - heap base : base ddr address of the heap,0 means that
-       it is dynamic.
-       - heap size : memory size and 0 means it is dynamic.
-       - heap type : the heap type of the heap, please also
-       see the define in ion.h(drivers/staging/android/uapi/ion.h)
--------------------------------------------------------------------
-Example:
-       hi6220-ion {
-               compatible = "hisilicon,hi6220-ion";
-               heap_sys_user@0 {
-                       heap-name = "sys_user";
-                       heap-id   = <0x0>;
-                       heap-base = <0x0>;
-                       heap-size = <0x0>;
-                       heap-type = "ion_system";
-               };
-               heap_sys_contig@0 {
-                       heap-name = "sys_contig";
-                       heap-id   = <0x1>;
-                       heap-base = <0x0>;
-                       heap-size = <0x0>;
-                       heap-type = "ion_system_contig";
-               };
-       };
index 503bcf4e3e8ffd09750bf6ee1b9cce43c7351be6..9e984645c4b08b9e20ebc839704a5d25b0c32032 100644 (file)
@@ -846,7 +846,6 @@ M:  Laura Abbott <labbott@redhat.com>
 M:     Sumit Semwal <sumit.semwal@linaro.org>
 L:     devel@driverdev.osuosl.org
 S:     Supported
-F:     Documentation/devicetree/bindings/staging/ion/
 F:     drivers/staging/android/ion
 F:     drivers/staging/android/uapi/ion.h
 F:     drivers/staging/android/uapi/ion_test.h
@@ -3116,6 +3115,14 @@ F:       drivers/net/ieee802154/cc2520.c
 F:     include/linux/spi/cc2520.h
 F:     Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
 
+CCREE ARM TRUSTZONE CRYPTOCELL 700 REE DRIVER
+M:     Gilad Ben-Yossef <gilad@benyossef.com>
+L:     linux-crypto@vger.kernel.org
+L:     driverdev-devel@linuxdriverproject.org
+S:     Supported
+F:     drivers/staging/ccree/
+W:     https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family
+
 CEC FRAMEWORK
 M:     Hans Verkuil <hans.verkuil@cisco.com>
 L:     linux-media@vger.kernel.org
@@ -5695,7 +5702,7 @@ M:        Alex Elder <elder@kernel.org>
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 S:     Maintained
 F:     drivers/staging/greybus/
-L:     greybus-dev@lists.linaro.org
+L:     greybus-dev@lists.linaro.org (moderated for non-subscribers)
 
 GREYBUS AUDIO PROTOCOLS DRIVERS
 M:     Vaibhav Agarwal <vaibhav.sr@gmail.com>
diff --git a/drivers/staging/android/ion/devicetree.txt b/drivers/staging/android/ion/devicetree.txt
deleted file mode 100644 (file)
index 1687152..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-Ion Memory Manager
-
-Ion is a memory manager that allows for sharing of buffers via dma-buf.
-Ion allows for different types of allocation via an abstraction called
-a 'heap'. A heap represents a specific type of memory. Each heap has
-a different type. There can be multiple instances of the same heap
-type.
-
-Specific heap instances are tied to heap IDs. Heap IDs are not to be specified
-in the devicetree.
-
-Required properties for Ion
-
-- compatible: "linux,ion" PLUS a compatible property for the device
-
-All child nodes of a linux,ion node are interpreted as heaps
-
-required properties for heaps
-
-- compatible: compatible string for a heap type PLUS a compatible property
-for the specific instance of the heap. Current heap types
--- linux,ion-heap-system
--- linux,ion-heap-system-contig
--- linux,ion-heap-carveout
--- linux,ion-heap-chunk
--- linux,ion-heap-dma
--- linux,ion-heap-custom
-
-Optional properties
-- memory-region: A phandle to a memory region. Required for DMA heap type
-(see reserved-memory.txt for details on the reservation)
-
-Example:
-
-       ion {
-               compatbile = "hisilicon,ion", "linux,ion";
-
-               ion-system-heap {
-                       compatbile = "hisilicon,system-heap", "linux,ion-heap-system"
-               };
-
-               ion-camera-region {
-                       compatible = "hisilicon,camera-heap", "linux,ion-heap-dma"
-                       memory-region = <&camera_region>;
-               };
-
-               ion-fb-region {
-                       compatbile = "hisilicon,fb-heap", "linux,ion-heap-dma"
-                       memory-region = <&fb_region>;
-               };
-       }
index 522bd62c102eafe592349006206f2916ad67b15b..8611adf3bb2e9e8f42d5b210db9a0d20670085c2 100644 (file)
@@ -376,7 +376,6 @@ int send_request(
        rc = ssi_power_mgr_runtime_get(&drvdata->plat_dev->dev);
        if (rc != 0) {
                SSI_LOG_ERR("ssi_power_mgr_runtime_get returned %x\n",rc);
-               spin_unlock_bh(&req_mgr_h->hw_lock);
                return rc;
        }
 #endif
index 2e325cb747ae97bace5497964e27c76b49fe1f80..730fd6d4db33e9bb9fc607b0a6d1cbc26f7079b2 100644 (file)
@@ -12,6 +12,7 @@ config FSL_DPAA2
 config FSL_DPAA2_ETH
        tristate "Freescale DPAA2 Ethernet"
        depends on FSL_DPAA2 && FSL_MC_DPIO
+       depends on NETDEVICES && ETHERNET
        ---help---
          Ethernet driver for Freescale DPAA2 SoCs, using the
          Freescale MC bus driver
index 4723a0bd5067595fdbc38850887cdc69a947c59e..1c6ed5b2a6f96d1d227fb72d9b84f37776c4ece3 100644 (file)
@@ -97,8 +97,9 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
 
        switch (variable) {
        case HW_VAR_BSSID:
-               rtl92e_writel(dev, BSSIDR, ((u32 *)(val))[0]);
-               rtl92e_writew(dev, BSSIDR+2, ((u16 *)(val+2))[0]);
+               /* BSSIDR 2 byte alignment */
+               rtl92e_writew(dev, BSSIDR, *(u16 *)val);
+               rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(val + 2));
                break;
 
        case HW_VAR_MEDIA_STATUS:
@@ -624,7 +625,7 @@ void rtl92e_get_eeprom_size(struct net_device *dev)
        struct r8192_priv *priv = rtllib_priv(dev);
 
        RT_TRACE(COMP_INIT, "===========>%s()\n", __func__);
-       curCR = rtl92e_readl(dev, EPROM_CMD);
+       curCR = rtl92e_readw(dev, EPROM_CMD);
        RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD,
                 curCR);
        priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 :
@@ -961,8 +962,8 @@ static void _rtl92e_net_update(struct net_device *dev)
        rtl92e_config_rate(dev, &rate_config);
        priv->dot11CurrentPreambleMode = PREAMBLE_AUTO;
         priv->basic_rate = rate_config &= 0x15f;
-       rtl92e_writel(dev, BSSIDR, ((u32 *)net->bssid)[0]);
-       rtl92e_writew(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
+       rtl92e_writew(dev, BSSIDR, *(u16 *)net->bssid);
+       rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(net->bssid + 2));
 
        if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
                rtl92e_writew(dev, ATIMWND, 2);
@@ -1182,8 +1183,7 @@ void  rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
                          struct cb_desc *cb_desc, struct sk_buff *skb)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
-       dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
-                        PCI_DMA_TODEVICE);
+       dma_addr_t mapping;
        struct tx_fwinfo_8190pci *pTxFwInfo;
 
        pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data;
@@ -1194,8 +1194,6 @@ void  rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
        pTxFwInfo->Short = _rtl92e_query_is_short(pTxFwInfo->TxHT,
                                                  pTxFwInfo->TxRate, cb_desc);
 
-       if (pci_dma_mapping_error(priv->pdev, mapping))
-               netdev_err(dev, "%s(): DMA Mapping error\n", __func__);
        if (cb_desc->bAMPDUEnable) {
                pTxFwInfo->AllowAggregation = 1;
                pTxFwInfo->RxMF = cb_desc->ampdu_factor;
@@ -1230,6 +1228,14 @@ void  rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
        }
 
        memset((u8 *)pdesc, 0, 12);
+
+       mapping = pci_map_single(priv->pdev, skb->data, skb->len,
+                                PCI_DMA_TODEVICE);
+       if (pci_dma_mapping_error(priv->pdev, mapping)) {
+               netdev_err(dev, "%s(): DMA Mapping error\n", __func__);
+               return;
+       }
+
        pdesc->LINIP = 0;
        pdesc->CmdInit = 1;
        pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8;
index 48bbd9e8a52f3444ff345a934a0721faf556ccc7..dcc4eb691889245e65927172a6e97a206d05fa6c 100644 (file)
@@ -306,11 +306,6 @@ static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr,
        pTsCommonInfo->TClasNum = TCLAS_Num;
 }
 
-static bool IsACValid(unsigned int tid)
-{
-       return tid < 7;
-}
-
 bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
           u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs)
 {
@@ -328,12 +323,6 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
        if (ieee->current_network.qos_data.supported == 0) {
                UP = 0;
        } else {
-               if (!IsACValid(TID)) {
-                       netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n",
-                                   __func__, TID);
-                       return false;
-               }
-
                switch (TID) {
                case 0:
                case 3:
@@ -351,6 +340,10 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
                case 7:
                        UP = 7;
                        break;
+               default:
+                       netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n",
+                                   __func__, TID);
+                       return false;
                }
        }
 
index 5e7a61f24f8dc38daea774986696ec6cc1d9ce9d..36c3189fc4b7f6f981ca683dd53267a5f9e541c3 100644 (file)
@@ -3531,7 +3531,6 @@ int rtw_wdev_alloc(struct adapter *padapter, struct device *dev)
                pwdev_priv->power_mgmt = true;
        else
                pwdev_priv->power_mgmt = false;
-       kfree((u8 *)wdev);
 
        return ret;
 
index 2cee9a952c9b8d164fc3f94140ea6cb63e982d7a..4a356e509fe450b4260ac3b49ec001d4fa9aea7a 100644 (file)
@@ -264,22 +264,36 @@ static void fusb302_debugfs_exit(const struct fusb302_chip *chip) { }
 
 #define FUSB302_RESUME_RETRY 10
 #define FUSB302_RESUME_RETRY_SLEEP 50
-static int fusb302_i2c_write(struct fusb302_chip *chip,
-                            u8 address, u8 data)
+
+static bool fusb302_is_suspended(struct fusb302_chip *chip)
 {
        int retry_cnt;
-       int ret = 0;
 
-       atomic_set(&chip->i2c_busy, 1);
        for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
                if (atomic_read(&chip->pm_suspend)) {
-                       pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
-                              retry_cnt + 1, FUSB302_RESUME_RETRY);
+                       dev_err(chip->dev, "i2c: pm suspend, retry %d/%d\n",
+                               retry_cnt + 1, FUSB302_RESUME_RETRY);
                        msleep(FUSB302_RESUME_RETRY_SLEEP);
                } else {
-                       break;
+                       return false;
                }
        }
+
+       return true;
+}
+
+static int fusb302_i2c_write(struct fusb302_chip *chip,
+                            u8 address, u8 data)
+{
+       int ret = 0;
+
+       atomic_set(&chip->i2c_busy, 1);
+
+       if (fusb302_is_suspended(chip)) {
+               atomic_set(&chip->i2c_busy, 0);
+               return -ETIMEDOUT;
+       }
+
        ret = i2c_smbus_write_byte_data(chip->i2c_client, address, data);
        if (ret < 0)
                fusb302_log(chip, "cannot write 0x%02x to 0x%02x, ret=%d",
@@ -292,21 +306,17 @@ static int fusb302_i2c_write(struct fusb302_chip *chip,
 static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address,
                                   u8 length, const u8 *data)
 {
-       int retry_cnt;
        int ret = 0;
 
        if (length <= 0)
                return ret;
        atomic_set(&chip->i2c_busy, 1);
-       for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
-               if (atomic_read(&chip->pm_suspend)) {
-                       pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
-                              retry_cnt + 1, FUSB302_RESUME_RETRY);
-                       msleep(FUSB302_RESUME_RETRY_SLEEP);
-               } else {
-                       break;
-               }
+
+       if (fusb302_is_suspended(chip)) {
+               atomic_set(&chip->i2c_busy, 0);
+               return -ETIMEDOUT;
        }
+
        ret = i2c_smbus_write_i2c_block_data(chip->i2c_client, address,
                                             length, data);
        if (ret < 0)
@@ -320,19 +330,15 @@ static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address,
 static int fusb302_i2c_read(struct fusb302_chip *chip,
                            u8 address, u8 *data)
 {
-       int retry_cnt;
        int ret = 0;
 
        atomic_set(&chip->i2c_busy, 1);
-       for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
-               if (atomic_read(&chip->pm_suspend)) {
-                       pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
-                              retry_cnt + 1, FUSB302_RESUME_RETRY);
-                       msleep(FUSB302_RESUME_RETRY_SLEEP);
-               } else {
-                       break;
-               }
+
+       if (fusb302_is_suspended(chip)) {
+               atomic_set(&chip->i2c_busy, 0);
+               return -ETIMEDOUT;
        }
+
        ret = i2c_smbus_read_byte_data(chip->i2c_client, address);
        *data = (u8)ret;
        if (ret < 0)
@@ -345,33 +351,31 @@ static int fusb302_i2c_read(struct fusb302_chip *chip,
 static int fusb302_i2c_block_read(struct fusb302_chip *chip, u8 address,
                                  u8 length, u8 *data)
 {
-       int retry_cnt;
        int ret = 0;
 
        if (length <= 0)
                return ret;
        atomic_set(&chip->i2c_busy, 1);
-       for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
-               if (atomic_read(&chip->pm_suspend)) {
-                       pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
-                              retry_cnt + 1, FUSB302_RESUME_RETRY);
-                       msleep(FUSB302_RESUME_RETRY_SLEEP);
-               } else {
-                       break;
-               }
+
+       if (fusb302_is_suspended(chip)) {
+               atomic_set(&chip->i2c_busy, 0);
+               return -ETIMEDOUT;
        }
+
        ret = i2c_smbus_read_i2c_block_data(chip->i2c_client, address,
                                            length, data);
        if (ret < 0) {
                fusb302_log(chip, "cannot block read 0x%02x, len=%d, ret=%d",
                            address, length, ret);
-               return ret;
+               goto done;
        }
        if (ret != length) {
                fusb302_log(chip, "only read %d/%d bytes from 0x%02x",
                            ret, length, address);
-               return -EIO;
+               ret = -EIO;
        }
+
+done:
        atomic_set(&chip->i2c_busy, 0);
 
        return ret;
@@ -489,7 +493,7 @@ static int tcpm_init(struct tcpc_dev *dev)
        ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &data);
        if (ret < 0)
                return ret;
-       chip->vbus_present = !!(FUSB_REG_STATUS0 & FUSB_REG_STATUS0_VBUSOK);
+       chip->vbus_present = !!(data & FUSB_REG_STATUS0_VBUSOK);
        ret = fusb302_i2c_read(chip, FUSB_REG_DEVICE_ID, &data);
        if (ret < 0)
                return ret;
@@ -1025,7 +1029,7 @@ static int fusb302_pd_send_message(struct fusb302_chip *chip,
        buf[pos++] = FUSB302_TKN_SYNC1;
        buf[pos++] = FUSB302_TKN_SYNC2;
 
-       len = pd_header_cnt(msg->header) * 4;
+       len = pd_header_cnt_le(msg->header) * 4;
        /* plug 2 for header */
        len += 2;
        if (len > 0x1F) {
@@ -1481,7 +1485,7 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip,
                                     (u8 *)&msg->header);
        if (ret < 0)
                return ret;
-       len = pd_header_cnt(msg->header) * 4;
+       len = pd_header_cnt_le(msg->header) * 4;
        /* add 4 to length to include the CRC */
        if (len > PD_MAX_PAYLOAD * 4) {
                fusb302_log(chip, "PD message too long %d", len);
@@ -1663,14 +1667,12 @@ static int init_gpio(struct fusb302_chip *chip)
        if (ret < 0) {
                fusb302_log(chip,
                            "cannot set GPIO Int_N to input, ret=%d", ret);
-               gpio_free(chip->gpio_int_n);
                return ret;
        }
        ret = gpio_to_irq(chip->gpio_int_n);
        if (ret < 0) {
                fusb302_log(chip,
                            "cannot request IRQ for GPIO Int_N, ret=%d", ret);
-               gpio_free(chip->gpio_int_n);
                return ret;
        }
        chip->gpio_int_n_irq = ret;
@@ -1787,11 +1789,13 @@ static const struct of_device_id fusb302_dt_match[] = {
        {.compatible = "fcs,fusb302"},
        {},
 };
+MODULE_DEVICE_TABLE(of, fusb302_dt_match);
 
 static const struct i2c_device_id fusb302_i2c_device_id[] = {
        {"typec_fusb302", 0},
        {},
 };
+MODULE_DEVICE_TABLE(i2c, fusb302_i2c_device_id);
 
 static const struct dev_pm_ops fusb302_pm_ops = {
        .suspend = fusb302_pm_suspend,
index 8d97bdb95f2385c7450cf093b8d7042d17520c15..510ef7279900617d5057f559b414239f99a36e03 100644 (file)
@@ -92,6 +92,16 @@ static inline unsigned int pd_header_type_le(__le16 header)
        return pd_header_type(le16_to_cpu(header));
 }
 
+static inline unsigned int pd_header_msgid(u16 header)
+{
+       return (header >> PD_HEADER_ID_SHIFT) & PD_HEADER_ID_MASK;
+}
+
+static inline unsigned int pd_header_msgid_le(__le16 header)
+{
+       return pd_header_msgid(le16_to_cpu(header));
+}
+
 #define PD_MAX_PAYLOAD         7
 
 struct pd_message {
index dba172e0e0d1faf52c9e9c287ef6c7e5be2e11da..d92259f8de0a835ad2a634d079e6d08ab327f654 100644 (file)
@@ -22,6 +22,9 @@
  * VDM object is minimum of VDM header + 6 additional data objects.
  */
 
+#define VDO_MAX_OBJECTS                6
+#define VDO_MAX_SIZE           (VDO_MAX_OBJECTS + 1)
+
 /*
  * VDM header
  * ----------
@@ -34,7 +37,6 @@
  * <5>      :: reserved (SVDM), command type (UVDM)
  * <4:0>    :: command
  */
-#define VDO_MAX_SIZE 7
 #define VDO(vid, type, custom)                         \
        (((vid) << 16) |                                \
         ((type) << 15) |                               \
index 5e5be74c7850032e4bd40705e1628e5cb14bb344..df72d8b01e730d5b2a9de183dbf9d64f662226f6 100644 (file)
@@ -425,7 +425,7 @@ static const struct regmap_config tcpci_regmap_config = {
        .max_register = 0x7F, /* 0x80 .. 0xFF are vendor defined */
 };
 
-const struct tcpc_config tcpci_tcpc_config = {
+static const struct tcpc_config tcpci_tcpc_config = {
        .type = TYPEC_PORT_DFP,
        .default_role = TYPEC_SINK,
 };
index abba655ba00a3469537c61070a747d276aa06cfa..20eb4ebcf8c3dba29f03fa58fa09169c281bf27c 100644 (file)
@@ -238,6 +238,7 @@ struct tcpm_port {
        unsigned int hard_reset_count;
        bool pd_capable;
        bool explicit_contract;
+       unsigned int rx_msgid;
 
        /* Partner capabilities/requests */
        u32 sink_request;
@@ -251,6 +252,8 @@ struct tcpm_port {
        unsigned int nr_src_pdo;
        u32 snk_pdo[PDO_MAX_OBJECTS];
        unsigned int nr_snk_pdo;
+       u32 snk_vdo[VDO_MAX_OBJECTS];
+       unsigned int nr_snk_vdo;
 
        unsigned int max_snk_mv;
        unsigned int max_snk_ma;
@@ -997,6 +1000,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
        struct pd_mode_data *modep;
        int rlen = 0;
        u16 svid;
+       int i;
 
        tcpm_log(port, "Rx VDM cmd 0x%x type %d cmd %d len %d",
                 p0, cmd_type, cmd, cnt);
@@ -1007,6 +1011,14 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
        case CMDT_INIT:
                switch (cmd) {
                case CMD_DISCOVER_IDENT:
+                       /* 6.4.4.3.1: Only respond as UFP (device) */
+                       if (port->data_role == TYPEC_DEVICE &&
+                           port->nr_snk_vdo) {
+                               for (i = 0; i <  port->nr_snk_vdo; i++)
+                                       response[i + 1]
+                                               = cpu_to_le32(port->snk_vdo[i]);
+                               rlen = port->nr_snk_vdo + 1;
+                       }
                        break;
                case CMD_DISCOVER_SVID:
                        break;
@@ -1415,6 +1427,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
                        break;
                case SOFT_RESET_SEND:
                        port->message_id = 0;
+                       port->rx_msgid = -1;
                        if (port->pwr_role == TYPEC_SOURCE)
                                next_state = SRC_SEND_CAPABILITIES;
                        else
@@ -1503,6 +1516,22 @@ static void tcpm_pd_rx_handler(struct work_struct *work)
                 port->attached);
 
        if (port->attached) {
+               enum pd_ctrl_msg_type type = pd_header_type_le(msg->header);
+               unsigned int msgid = pd_header_msgid_le(msg->header);
+
+               /*
+                * USB PD standard, 6.6.1.2:
+                * "... if MessageID value in a received Message is the
+                * same as the stored value, the receiver shall return a
+                * GoodCRC Message with that MessageID value and drop
+                * the Message (this is a retry of an already received
+                * Message). Note: this shall not apply to the Soft_Reset
+                * Message which always has a MessageID value of zero."
+                */
+               if (msgid == port->rx_msgid && type != PD_CTRL_SOFT_RESET)
+                       goto done;
+               port->rx_msgid = msgid;
+
                /*
                 * If both ends believe to be DFP/host, we have a data role
                 * mismatch.
@@ -1520,6 +1549,7 @@ static void tcpm_pd_rx_handler(struct work_struct *work)
                }
        }
 
+done:
        mutex_unlock(&port->lock);
        kfree(event);
 }
@@ -1719,8 +1749,7 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo)
        }
        ma = min(ma, port->max_snk_ma);
 
-       /* XXX: Any other flags need to be set? */
-       flags = 0;
+       flags = RDO_USB_COMM | RDO_NO_SUSPEND;
 
        /* Set mismatch bit if offered power is less than operating power */
        mw = ma * mv / 1000;
@@ -1957,6 +1986,12 @@ static void tcpm_reset_port(struct tcpm_port *port)
        port->attached = false;
        port->pd_capable = false;
 
+       /*
+        * First Rx ID should be 0; set this to a sentinel of -1 so that
+        * we can check tcpm_pd_rx_handler() if we had seen it before.
+        */
+       port->rx_msgid = -1;
+
        port->tcpc->set_pd_rx(port->tcpc, false);
        tcpm_init_vbus(port);   /* also disables charging */
        tcpm_init_vconn(port);
@@ -2170,6 +2205,7 @@ static void run_state_machine(struct tcpm_port *port)
                port->pwr_opmode = TYPEC_PWR_MODE_USB;
                port->caps_count = 0;
                port->message_id = 0;
+               port->rx_msgid = -1;
                port->explicit_contract = false;
                tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
                break;
@@ -2329,6 +2365,7 @@ static void run_state_machine(struct tcpm_port *port)
                typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_USB);
                port->pwr_opmode = TYPEC_PWR_MODE_USB;
                port->message_id = 0;
+               port->rx_msgid = -1;
                port->explicit_contract = false;
                tcpm_set_state(port, SNK_DISCOVERY, 0);
                break;
@@ -2496,6 +2533,7 @@ static void run_state_machine(struct tcpm_port *port)
        /* Soft_Reset states */
        case SOFT_RESET:
                port->message_id = 0;
+               port->rx_msgid = -1;
                tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
                if (port->pwr_role == TYPEC_SOURCE)
                        tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
@@ -2504,6 +2542,7 @@ static void run_state_machine(struct tcpm_port *port)
                break;
        case SOFT_RESET_SEND:
                port->message_id = 0;
+               port->rx_msgid = -1;
                if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET))
                        tcpm_set_state_cond(port, hard_reset_state(port), 0);
                else
@@ -2568,6 +2607,14 @@ static void run_state_machine(struct tcpm_port *port)
                break;
        case PR_SWAP_SRC_SNK_SOURCE_OFF:
                tcpm_set_cc(port, TYPEC_CC_RD);
+               /*
+                * USB-PD standard, 6.2.1.4, Port Power Role:
+                * "During the Power Role Swap Sequence, for the initial Source
+                * Port, the Port Power Role field shall be set to Sink in the
+                * PS_RDY Message indicating that the initial Source’s power
+                * supply is turned off"
+                */
+               tcpm_set_pwr_role(port, TYPEC_SINK);
                if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) {
                        tcpm_set_state(port, ERROR_RECOVERY, 0);
                        break;
@@ -2575,7 +2622,6 @@ static void run_state_machine(struct tcpm_port *port)
                tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON);
                break;
        case PR_SWAP_SRC_SNK_SINK_ON:
-               tcpm_set_pwr_role(port, TYPEC_SINK);
                tcpm_swap_complete(port, 0);
                tcpm_set_state(port, SNK_STARTUP, 0);
                break;
@@ -2587,8 +2633,15 @@ static void run_state_machine(struct tcpm_port *port)
        case PR_SWAP_SNK_SRC_SOURCE_ON:
                tcpm_set_cc(port, tcpm_rp_cc(port));
                tcpm_set_vbus(port, true);
-               tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
+               /*
+                * USB PD standard, 6.2.1.4:
+                * "Subsequent Messages initiated by the Policy Engine,
+                * such as the PS_RDY Message sent to indicate that Vbus
+                * is ready, will have the Port Power Role field set to
+                * Source."
+                */
                tcpm_set_pwr_role(port, TYPEC_SOURCE);
+               tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
                tcpm_swap_complete(port, 0);
                tcpm_set_state(port, SRC_STARTUP, 0);
                break;
@@ -3292,6 +3345,20 @@ static int tcpm_copy_pdos(u32 *dest_pdo, const u32 *src_pdo,
        return nr_pdo;
 }
 
+static int tcpm_copy_vdos(u32 *dest_vdo, const u32 *src_vdo,
+                         unsigned int nr_vdo)
+{
+       unsigned int i;
+
+       if (nr_vdo > VDO_MAX_OBJECTS)
+               nr_vdo = VDO_MAX_OBJECTS;
+
+       for (i = 0; i < nr_vdo; i++)
+               dest_vdo[i] = src_vdo[i];
+
+       return nr_vdo;
+}
+
 void tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo,
                                     unsigned int nr_pdo)
 {
@@ -3382,6 +3449,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
                                          tcpc->config->nr_src_pdo);
        port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, tcpc->config->snk_pdo,
                                          tcpc->config->nr_snk_pdo);
+       port->nr_snk_vdo = tcpm_copy_vdos(port->snk_vdo, tcpc->config->snk_vdo,
+                                         tcpc->config->nr_snk_vdo);
 
        port->max_snk_mv = tcpc->config->max_snk_mv;
        port->max_snk_ma = tcpc->config->max_snk_ma;
index 969b365e65497775f4481478641ab9f07cbbe2c4..19c307d31a5a39267abe546451c89f953ccc0945 100644 (file)
@@ -60,6 +60,9 @@ struct tcpc_config {
        const u32 *snk_pdo;
        unsigned int nr_snk_pdo;
 
+       const u32 *snk_vdo;
+       unsigned int nr_snk_vdo;
+
        unsigned int max_snk_mv;
        unsigned int max_snk_ma;
        unsigned int max_snk_mw;
index 988ee61fb4a7be9d4248c97c89f99ab947465fb0..d04db3f555192d58a9e1f0d9357b0b25578f1a91 100644 (file)
@@ -502,8 +502,15 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
         */
        sg_init_table(scatterlist, num_pages);
        /* Now set the pages for each scatterlist */
-       for (i = 0; i < num_pages; i++)
-               sg_set_page(scatterlist + i, pages[i], PAGE_SIZE, 0);
+       for (i = 0; i < num_pages; i++) {
+               unsigned int len = PAGE_SIZE - offset;
+
+               if (len > count)
+                       len = count;
+               sg_set_page(scatterlist + i, pages[i], len, offset);
+               offset = 0;
+               count -= len;
+       }
 
        dma_buffers = dma_map_sg(g_dev,
                                 scatterlist,
@@ -524,20 +531,20 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
                u32 addr = sg_dma_address(sg);
 
                /* Note: addrs is the address + page_count - 1
-                * The firmware expects the block to be page
+                * The firmware expects blocks after the first to be page-
                 * aligned and a multiple of the page size
                 */
                WARN_ON(len == 0);
-               WARN_ON(len & ~PAGE_MASK);
-               WARN_ON(addr & ~PAGE_MASK);
+               WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
+               WARN_ON(i && (addr & ~PAGE_MASK));
                if (k > 0 &&
-                   ((addrs[k - 1] & PAGE_MASK) |
-                       ((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT)
-                   == addr) {
-                       addrs[k - 1] += (len >> PAGE_SHIFT);
-               } else {
-                       addrs[k++] = addr | ((len >> PAGE_SHIFT) - 1);
-               }
+                   ((addrs[k - 1] & PAGE_MASK) +
+                    (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT))
+                   == (addr & PAGE_MASK))
+                       addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
+               else
+                       addrs[k++] = (addr & PAGE_MASK) |
+                               (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
        }
 
        /* Partial cache lines (fragments) require special measures */