}
 EXPORT_SYMBOL_GPL(iscsi_conn_login_event);
 
+void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport,
+                          enum iscsi_host_event_code code, uint32_t data_size,
+                          uint8_t *data)
+{
+       struct nlmsghdr *nlh;
+       struct sk_buff *skb;
+       struct iscsi_uevent *ev;
+       int len = NLMSG_SPACE(sizeof(*ev) + data_size);
+
+       skb = alloc_skb(len, GFP_KERNEL);
+       if (!skb) {
+               printk(KERN_ERR "gracefully ignored host event (%d):%d OOM\n",
+                      host_no, code);
+               return;
+       }
+
+       nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
+       ev = NLMSG_DATA(nlh);
+       ev->transport_handle = iscsi_handle(transport);
+       ev->type = ISCSI_KEVENT_HOST_EVENT;
+       ev->r.host_event.host_no = host_no;
+       ev->r.host_event.code = code;
+       ev->r.host_event.data_size = data_size;
+
+       if (data_size)
+               memcpy((char *)ev + sizeof(*ev), data, data_size);
+
+       iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_KERNEL);
+}
+EXPORT_SYMBOL_GPL(iscsi_post_host_event);
+
 static int
 iscsi_if_send_reply(uint32_t group, int seq, int type, int done, int multi,
                    void *payload, int size)
 
        ISCSI_KEVENT_PATH_REQ           = KEVENT_BASE + 7,
        ISCSI_KEVENT_IF_DOWN            = KEVENT_BASE + 8,
        ISCSI_KEVENT_CONN_LOGIN_STATE   = KEVENT_BASE + 9,
+       ISCSI_KEVENT_HOST_EVENT         = KEVENT_BASE + 10,
 };
 
 enum iscsi_tgt_dscvr {
        ISCSI_TGT_DSCVR_SLP             = 3,
 };
 
+enum iscsi_host_event_code {
+       ISCSI_EVENT_LINKUP              = 1,
+       ISCSI_EVENT_LINKDOWN,
+       /* must always be last */
+       ISCSI_EVENT_MAX,
+};
+
 struct iscsi_uevent {
        uint32_t type; /* k/u events type */
        uint32_t iferror; /* carries interface or resource errors */
                struct msg_notify_if_down {
                        uint32_t        host_no;
                } notify_if_down;
+               struct msg_host_event {
+                       uint32_t        host_no;
+                       uint32_t        data_size;
+                       enum iscsi_host_event_code code;
+               } host_event;
        } r;
 } __attribute__ ((aligned (sizeof(uint64_t))));
 
 
                              struct iscsi_transport *transport, uint32_t type,
                              char *data, uint16_t data_size);
 
+extern void iscsi_post_host_event(uint32_t host_no,
+                                 struct iscsi_transport *transport,
+                                 enum iscsi_host_event_code code,
+                                 uint32_t data_size,
+                                 uint8_t *data);
+
 struct iscsi_cls_conn {
        struct list_head conn_list;     /* item in connlist */
        void *dd_data;                  /* LLD private data */