|
@@ -863,6 +863,30 @@ static ssize_t key_store(struct device *dev, struct device_attribute *attr,
|
|
|
}
|
|
|
static DEVICE_ATTR(key, 0600, key_show, key_store);
|
|
|
|
|
|
+static void nvm_authenticate_start(struct tb_switch *sw)
|
|
|
+{
|
|
|
+ struct pci_dev *root_port;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * During host router NVM upgrade we should not allow root port to
|
|
|
+ * go into D3cold because some root ports cannot trigger PME
|
|
|
+ * itself. To be on the safe side keep the root port in D0 during
|
|
|
+ * the whole upgrade process.
|
|
|
+ */
|
|
|
+ root_port = pci_find_pcie_root_port(sw->tb->nhi->pdev);
|
|
|
+ if (root_port)
|
|
|
+ pm_runtime_get_noresume(&root_port->dev);
|
|
|
+}
|
|
|
+
|
|
|
+static void nvm_authenticate_complete(struct tb_switch *sw)
|
|
|
+{
|
|
|
+ struct pci_dev *root_port;
|
|
|
+
|
|
|
+ root_port = pci_find_pcie_root_port(sw->tb->nhi->pdev);
|
|
|
+ if (root_port)
|
|
|
+ pm_runtime_put(&root_port->dev);
|
|
|
+}
|
|
|
+
|
|
|
static ssize_t nvm_authenticate_show(struct device *dev,
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
{
|
|
@@ -912,10 +936,18 @@ static ssize_t nvm_authenticate_store(struct device *dev,
|
|
|
|
|
|
sw->nvm->authenticating = true;
|
|
|
|
|
|
- if (!tb_route(sw))
|
|
|
+ if (!tb_route(sw)) {
|
|
|
+ /*
|
|
|
+ * Keep root port from suspending as long as the
|
|
|
+ * NVM upgrade process is running.
|
|
|
+ */
|
|
|
+ nvm_authenticate_start(sw);
|
|
|
ret = nvm_authenticate_host(sw);
|
|
|
- else
|
|
|
+ if (ret)
|
|
|
+ nvm_authenticate_complete(sw);
|
|
|
+ } else {
|
|
|
ret = nvm_authenticate_device(sw);
|
|
|
+ }
|
|
|
pm_runtime_mark_last_busy(&sw->dev);
|
|
|
pm_runtime_put_autosuspend(&sw->dev);
|
|
|
}
|
|
@@ -1334,6 +1366,10 @@ static int tb_switch_add_dma_port(struct tb_switch *sw)
|
|
|
if (ret <= 0)
|
|
|
return ret;
|
|
|
|
|
|
+ /* Now we can allow root port to suspend again */
|
|
|
+ if (!tb_route(sw))
|
|
|
+ nvm_authenticate_complete(sw);
|
|
|
+
|
|
|
if (status) {
|
|
|
tb_sw_info(sw, "switch flash authentication failed\n");
|
|
|
tb_switch_set_uuid(sw);
|