get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/41575/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 41575,
    "url": "http://patches.dpdk.org/api/patches/41575/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1530027372-24233-2-git-send-email-jia.guo@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1530027372-24233-2-git-send-email-jia.guo@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1530027372-24233-2-git-send-email-jia.guo@intel.com",
    "date": "2018-06-26T15:36:10",
    "name": "[V3,2/4] eal: add failure handle mechanism for hot plug",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "aaf0b4a93396ecd7bcfd5ce783e97e5babc5966f",
    "submitter": {
        "id": 507,
        "url": "http://patches.dpdk.org/api/people/507/?format=api",
        "name": "Guo, Jia",
        "email": "jia.guo@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1530027372-24233-2-git-send-email-jia.guo@intel.com/mbox/",
    "series": [
        {
            "id": 245,
            "url": "http://patches.dpdk.org/api/series/245/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=245",
            "date": "2018-06-26T15:36:09",
            "name": "[V3,1/4] bus/pci: handle device hot unplug",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/245/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/41575/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/41575/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id AFD1A1BB20;\n\tTue, 26 Jun 2018 17:38:31 +0200 (CEST)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id A040D1BB0C\n\tfor <dev@dpdk.org>; Tue, 26 Jun 2018 17:38:29 +0200 (CEST)",
            "from orsmga008.jf.intel.com ([10.7.209.65])\n\tby orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t26 Jun 2018 08:38:29 -0700",
            "from jeffguo-z170x-ud5.sh.intel.com (HELO localhost.localdomain)\n\t([10.67.104.10])\n\tby orsmga008.jf.intel.com with ESMTP; 26 Jun 2018 08:38:26 -0700"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.51,274,1526367600\"; d=\"scan'208\";a=\"52398098\"",
        "From": "Jeff Guo <jia.guo@intel.com>",
        "To": "stephen@networkplumber.org, bruce.richardson@intel.com,\n\tferruh.yigit@intel.com, konstantin.ananyev@intel.com,\n\tgaetan.rivet@6wind.com, jingjing.wu@intel.com, thomas@monjalon.net,\n\tmotih@mellanox.com, matan@mellanox.com, harry.van.haaren@intel.com,\n\tqi.z.zhang@intel.com, shaopeng.he@intel.com, bernard.iremonger@intel.com",
        "Cc": "jblunck@infradead.org, shreyansh.jain@nxp.com, dev@dpdk.org,\n\tjia.guo@intel.com, helin.zhang@intel.com",
        "Date": "Tue, 26 Jun 2018 23:36:10 +0800",
        "Message-Id": "<1530027372-24233-2-git-send-email-jia.guo@intel.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1530027372-24233-1-git-send-email-jia.guo@intel.com>",
        "References": "<1498711073-42917-1-git-send-email-jia.guo@intel.com>\n\t<1530027372-24233-1-git-send-email-jia.guo@intel.com>",
        "Subject": "[dpdk-dev] [PATCH V3 2/4] eal: add failure handle mechanism for hot\n\tplug",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch introduces a failure handler mechanism to handle device\nhot unplug event. When device be hot plug out, the device resource\nbecome invalid, if this resource is still be unexpected read/write,\nsystem will crash.\n\nThis patch let framework help application to handle this fault. When\nsigbus error occur, check the failure address and accordingly remap\nthe invalid memory for the corresponding device, that could guaranty\nthe application not to be shut down when hot unplug devices.\n\nSigned-off-by: Jeff Guo <jia.guo@intel.com>\n---\nv3->v2:\nadd new API and bus ops of bus_signal_handler\ndistingush handle generic sigbus and hotplug sigbus\n---\n drivers/bus/pci/pci_common.c            | 53 ++++++++++++++++++++\n lib/librte_eal/common/eal_common_bus.c  | 34 ++++++++++++-\n lib/librte_eal/common/include/rte_bus.h | 19 +++++++\n lib/librte_eal/linuxapp/eal/eal_dev.c   | 88 ++++++++++++++++++++++++++++++++-\n 4 files changed, 192 insertions(+), 2 deletions(-)",
    "diff": "diff --git a/drivers/bus/pci/pci_common.c b/drivers/bus/pci/pci_common.c\nindex e607d08..4c0ac98 100644\n--- a/drivers/bus/pci/pci_common.c\n+++ b/drivers/bus/pci/pci_common.c\n@@ -472,6 +472,32 @@ pci_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,\n \treturn NULL;\n }\n \n+/* check the failure address belongs to which device. */\n+static struct rte_pci_device *\n+pci_find_device_by_addr(const void *failure_addr)\n+{\n+\tstruct rte_pci_device *pdev = NULL;\n+\tint i;\n+\n+\tFOREACH_DEVICE_ON_PCIBUS(pdev) {\n+\t\tfor (i = 0; i != RTE_DIM(pdev->mem_resource); i++) {\n+\t\t\tif ((uint64_t)(uintptr_t)failure_addr >=\n+\t\t\t    (uint64_t)(uintptr_t)pdev->mem_resource[i].addr &&\n+\t\t\t    (uint64_t)(uintptr_t)failure_addr <\n+\t\t\t    (uint64_t)(uintptr_t)pdev->mem_resource[i].addr +\n+\t\t\t    pdev->mem_resource[i].len) {\n+\t\t\t\tRTE_LOG(INFO, EAL, \"Failure address \"\n+\t\t\t\t\t\"%16.16\"PRIx64\" belongs to \"\n+\t\t\t\t\t\"device %s!\\n\",\n+\t\t\t\t\t(uint64_t)(uintptr_t)failure_addr,\n+\t\t\t\t\tpdev->device.name);\n+\t\t\t\treturn pdev;\n+\t\t\t}\n+\t\t}\n+\t}\n+\treturn NULL;\n+}\n+\n static int\n pci_hotplug_handler(struct rte_device *dev)\n {\n@@ -506,6 +532,32 @@ pci_hotplug_handler(struct rte_device *dev)\n }\n \n static int\n+pci_sigbus_handler(const void *failure_addr)\n+{\n+\tstruct rte_pci_device *pdev = NULL;\n+\tint ret = 0;\n+\n+\tpdev = pci_find_device_by_addr(failure_addr);\n+\tif (!pdev) {\n+\t\t/* not found the device which is illegal access in MMIO,\n+\t\t * so it is a generic sigbus error.\n+\t\t */\n+\t\tret = 1;\n+\t}\n+\n+\t/* handle hotplug when sigbus error is caused of hot removal */\n+\tret = pci_hotplug_handler(&pdev->device);\n+\tif (ret) {\n+\t\tRTE_LOG(ERR, EAL, \"Failed to handle hot plug for device %s\",\n+\t\t\tpdev->name);\n+\t\tret = -1;\n+\t\trte_errno = -1;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int\n pci_plug(struct rte_device *dev)\n {\n \treturn pci_probe_all_drivers(RTE_DEV_TO_PCI(dev));\n@@ -536,6 +588,7 @@ struct rte_pci_bus rte_pci_bus = {\n \t\t.parse = pci_parse,\n \t\t.get_iommu_class = rte_pci_get_iommu_class,\n \t\t.hotplug_handler = pci_hotplug_handler,\n+\t\t.sigbus_handler = pci_sigbus_handler,\n \t},\n \t.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),\n \t.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),\ndiff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c\nindex 0943851..b505b9b 100644\n--- a/lib/librte_eal/common/eal_common_bus.c\n+++ b/lib/librte_eal/common/eal_common_bus.c\n@@ -37,6 +37,7 @@\n #include <rte_bus.h>\n #include <rte_debug.h>\n #include <rte_string_fns.h>\n+#include <rte_errno.h>\n \n #include \"eal_private.h\"\n \n@@ -220,7 +221,6 @@ rte_bus_find_by_device_name(const char *str)\n \treturn rte_bus_find(NULL, bus_can_parse, name);\n }\n \n-\n /*\n  * Get iommu class of devices on the bus.\n  */\n@@ -242,3 +242,35 @@ rte_bus_get_iommu_class(void)\n \t}\n \treturn mode;\n }\n+\n+static int\n+bus_handle_sigbus(const struct rte_bus *bus,\n+\t\t\tconst void *failure_addr)\n+{\n+\treturn !(bus->sigbus_handler && bus->sigbus_handler(failure_addr) <= 0);\n+}\n+\n+int\n+rte_bus_sigbus_handler(const void *failure_addr)\n+{\n+\tstruct rte_bus *bus;\n+\tint old_errno = rte_errno;\n+\tint no_handle = 0;\n+\n+\trte_errno = 0;\n+\n+\tbus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr);\n+\tif (bus == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"No bus can handle the sigbus error!\");\n+\t\tno_handle = 1;\n+\t} else if (rte_errno != 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Failed to handle the sigbus error!\");\n+\t\tno_handle = 1;\n+\t}\n+\n+\t/* if sigbus not be handled, return back old errno. */\n+\tif (no_handle)\n+\t\trte_errno = old_errno;\n+\n+\treturn no_handle;\n+}\ndiff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h\nindex 6507f24..4389c42 100644\n--- a/lib/librte_eal/common/include/rte_bus.h\n+++ b/lib/librte_eal/common/include/rte_bus.h\n@@ -181,6 +181,19 @@ typedef int (*rte_bus_parse_t)(const char *name, void *addr);\n typedef int (*rte_bus_hotplug_handler_t)(struct rte_device *dev);\n \n /**\n+ * Implementation a specific sigbus handler, which is responsible\n+ * for handle the sigbus error which is original memory error, or specific\n+ * memory error that caused of hot unplug.\n+ * @param failure_addr\n+ *\tPointer of the fault address of the sigbus error.\n+ *\n+ * @return\n+ *\t0 on success.\n+ *\t!0 on error.\n+ */\n+typedef int (*rte_bus_sigbus_handler_t)(const void *failure_addr);\n+\n+/**\n  * Bus scan policies\n  */\n enum rte_bus_scan_mode {\n@@ -225,6 +238,7 @@ struct rte_bus {\n \tstruct rte_bus_conf conf;    /**< Bus configuration */\n \trte_bus_get_iommu_class_t get_iommu_class; /**< Get iommu class */\n \trte_bus_hotplug_handler_t hotplug_handler; /**< handle hot plug on bus */\n+\trte_bus_sigbus_handler_t sigbus_handler; /**< handle sigbus error */\n };\n \n /**\n@@ -335,6 +349,11 @@ struct rte_bus *rte_bus_find_by_name(const char *busname);\n enum rte_iova_mode rte_bus_get_iommu_class(void);\n \n /**\n+ * Handle the sigbus error on corresponding bus.\n+ */\n+int rte_bus_sigbus_handler(const void* failure_addr);\n+\n+/**\n  * Helper for Bus registration.\n  * The constructor has higher priority than PMD constructors.\n  */\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_dev.c b/lib/librte_eal/linuxapp/eal/eal_dev.c\nindex 1cf6aeb..c9dddab 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_dev.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_dev.c\n@@ -4,6 +4,8 @@\n \n #include <string.h>\n #include <unistd.h>\n+#include <fcntl.h>\n+#include <signal.h>\n #include <sys/socket.h>\n #include <linux/netlink.h>\n \n@@ -14,15 +16,24 @@\n #include <rte_malloc.h>\n #include <rte_interrupts.h>\n #include <rte_alarm.h>\n+#include <rte_bus.h>\n+#include <rte_eal.h>\n+#include <rte_spinlock.h>\n+#include <rte_errno.h>\n \n #include \"eal_private.h\"\n \n static struct rte_intr_handle intr_handle = {.fd = -1 };\n static bool monitor_started;\n \n+extern struct rte_bus_list rte_bus_list;\n+\n #define EAL_UEV_MSG_LEN 4096\n #define EAL_UEV_MSG_ELEM_LEN 128\n \n+/* spinlock for device failure process */\n+static rte_spinlock_t dev_failure_lock = RTE_SPINLOCK_INITIALIZER;\n+\n static void dev_uev_handler(__rte_unused void *param);\n \n /* identify the system layer which reports this event. */\n@@ -33,6 +44,34 @@ enum eal_dev_event_subsystem {\n \tEAL_DEV_EVENT_SUBSYSTEM_MAX\n };\n \n+static void sigbus_handler(int signum __rte_unused, siginfo_t *info,\n+\t\t\t\tvoid *ctx __rte_unused)\n+{\n+\tint ret;\n+\n+\tRTE_LOG(DEBUG, EAL, \"Thread[%d] catch SIGBUS, fault address:%p\\n\",\n+\t\t(int)pthread_self(), info->si_addr);\n+\n+\trte_spinlock_lock(&dev_failure_lock);\n+\tret = rte_bus_sigbus_handler(info->si_addr);\n+\trte_spinlock_unlock(&dev_failure_lock);\n+\tif (!ret)\n+\t\tRTE_LOG(INFO, EAL,\n+\t\t\t\"Success to handle SIGBUS error for hotplug!\\n\");\n+\telse\n+\t\trte_exit(EXIT_FAILURE,\n+\t\t\t \"A generic SIGBUS error, (rte_errno: %s)!\",\n+\t\t\t strerror(rte_errno));\n+}\n+\n+static int cmp_dev_name(const struct rte_device *dev,\n+\tconst void *_name)\n+{\n+\tconst char *name = _name;\n+\n+\treturn strcmp(dev->name, name);\n+}\n+\n static int\n dev_uev_socket_fd_create(void)\n {\n@@ -147,6 +186,9 @@ dev_uev_handler(__rte_unused void *param)\n \tstruct rte_dev_event uevent;\n \tint ret;\n \tchar buf[EAL_UEV_MSG_LEN];\n+\tstruct rte_bus *bus;\n+\tstruct rte_device *dev;\n+\tconst char *busname;\n \n \tmemset(&uevent, 0, sizeof(struct rte_dev_event));\n \tmemset(buf, 0, EAL_UEV_MSG_LEN);\n@@ -171,13 +213,48 @@ dev_uev_handler(__rte_unused void *param)\n \tRTE_LOG(DEBUG, EAL, \"receive uevent(name:%s, type:%d, subsystem:%d)\\n\",\n \t\tuevent.devname, uevent.type, uevent.subsystem);\n \n-\tif (uevent.devname)\n+\tswitch (uevent.subsystem) {\n+\tcase EAL_DEV_EVENT_SUBSYSTEM_PCI:\n+\tcase EAL_DEV_EVENT_SUBSYSTEM_UIO:\n+\t\tbusname = \"pci\";\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tif (uevent.devname) {\n+\t\tif (uevent.type == RTE_DEV_EVENT_REMOVE) {\n+\t\t\tbus = rte_bus_find_by_name(busname);\n+\t\t\tif (bus == NULL) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot find bus (%s)\\n\",\n+\t\t\t\t\tbusname);\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t\tdev = bus->find_device(NULL, cmp_dev_name,\n+\t\t\t\t\t       uevent.devname);\n+\t\t\tif (dev == NULL) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot find device (%s) on \"\n+\t\t\t\t\t\"bus (%s)\\n\", uevent.devname, busname);\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t\trte_spinlock_lock(&dev_failure_lock);\n+\t\t\tret = bus->hotplug_handler(dev);\n+\t\t\trte_spinlock_unlock(&dev_failure_lock);\n+\t\t\tif (ret) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Can not handle hotplug for \"\n+\t\t\t\t\t\"device (%s)\\n\", dev->name);\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t}\n \t\tdev_callback_process(uevent.devname, uevent.type);\n+\t}\n }\n \n int __rte_experimental\n rte_dev_event_monitor_start(void)\n {\n+\tsigset_t mask;\n+\tstruct sigaction action;\n \tint ret;\n \n \tif (monitor_started)\n@@ -197,6 +274,14 @@ rte_dev_event_monitor_start(void)\n \t\treturn -1;\n \t}\n \n+\t/* register sigbus handler */\n+\tsigemptyset(&mask);\n+\tsigaddset(&mask, SIGBUS);\n+\taction.sa_flags = SA_SIGINFO;\n+\taction.sa_mask = mask;\n+\taction.sa_sigaction = sigbus_handler;\n+\tsigaction(SIGBUS, &action, NULL);\n+\n \tmonitor_started = true;\n \n \treturn 0;\n@@ -220,5 +305,6 @@ rte_dev_event_monitor_stop(void)\n \tclose(intr_handle.fd);\n \tintr_handle.fd = -1;\n \tmonitor_started = false;\n+\n \treturn 0;\n }\n",
    "prefixes": [
        "V3",
        "2/4"
    ]
}