LCOV - code coverage report
Current view: top level - drivers/scsi - scsi_transport_iscsi.c (source / functions) Hit Total Coverage
Test: Real Lines: 21 1648 1.3 %
Date: 2020-10-17 15:46:43 Functions: 0 320 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  * iSCSI transport class definitions
       4                 :            :  *
       5                 :            :  * Copyright (C) IBM Corporation, 2004
       6                 :            :  * Copyright (C) Mike Christie, 2004 - 2005
       7                 :            :  * Copyright (C) Dmitry Yusupov, 2004 - 2005
       8                 :            :  * Copyright (C) Alex Aizman, 2004 - 2005
       9                 :            :  */
      10                 :            : #include <linux/module.h>
      11                 :            : #include <linux/mutex.h>
      12                 :            : #include <linux/slab.h>
      13                 :            : #include <linux/bsg-lib.h>
      14                 :            : #include <linux/idr.h>
      15                 :            : #include <net/tcp.h>
      16                 :            : #include <scsi/scsi.h>
      17                 :            : #include <scsi/scsi_host.h>
      18                 :            : #include <scsi/scsi_device.h>
      19                 :            : #include <scsi/scsi_transport.h>
      20                 :            : #include <scsi/scsi_transport_iscsi.h>
      21                 :            : #include <scsi/iscsi_if.h>
      22                 :            : #include <scsi/scsi_cmnd.h>
      23                 :            : #include <scsi/scsi_bsg_iscsi.h>
      24                 :            : 
      25                 :            : #define ISCSI_TRANSPORT_VERSION "2.0-870"
      26                 :            : 
      27                 :            : #define ISCSI_SEND_MAX_ALLOWED  10
      28                 :            : 
      29                 :            : #define CREATE_TRACE_POINTS
      30                 :            : #include <trace/events/iscsi.h>
      31                 :            : 
      32                 :            : /*
      33                 :            :  * Export tracepoint symbols to be used by other modules.
      34                 :            :  */
      35                 :            : EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_conn);
      36                 :            : EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_eh);
      37                 :            : EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_session);
      38                 :            : EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_tcp);
      39                 :            : EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_sw_tcp);
      40                 :            : 
      41                 :            : static int dbg_session;
      42                 :            : module_param_named(debug_session, dbg_session, int,
      43                 :            :                    S_IRUGO | S_IWUSR);
      44                 :            : MODULE_PARM_DESC(debug_session,
      45                 :            :                  "Turn on debugging for sessions in scsi_transport_iscsi "
      46                 :            :                  "module. Set to 1 to turn on, and zero to turn off. Default "
      47                 :            :                  "is off.");
      48                 :            : 
      49                 :            : static int dbg_conn;
      50                 :            : module_param_named(debug_conn, dbg_conn, int,
      51                 :            :                    S_IRUGO | S_IWUSR);
      52                 :            : MODULE_PARM_DESC(debug_conn,
      53                 :            :                  "Turn on debugging for connections in scsi_transport_iscsi "
      54                 :            :                  "module. Set to 1 to turn on, and zero to turn off. Default "
      55                 :            :                  "is off.");
      56                 :            : 
      57                 :            : #define ISCSI_DBG_TRANS_SESSION(_session, dbg_fmt, arg...)              \
      58                 :            :         do {                                                            \
      59                 :            :                 if (dbg_session)                                        \
      60                 :            :                         iscsi_cls_session_printk(KERN_INFO, _session,   \
      61                 :            :                                                  "%s: " dbg_fmt,      \
      62                 :            :                                                  __func__, ##arg);      \
      63                 :            :                 iscsi_dbg_trace(trace_iscsi_dbg_trans_session,          \
      64                 :            :                                 &(_session)->dev,                        \
      65                 :            :                                 "%s " dbg_fmt, __func__, ##arg);      \
      66                 :            :         } while (0);
      67                 :            : 
      68                 :            : #define ISCSI_DBG_TRANS_CONN(_conn, dbg_fmt, arg...)                    \
      69                 :            :         do {                                                            \
      70                 :            :                 if (dbg_conn)                                           \
      71                 :            :                         iscsi_cls_conn_printk(KERN_INFO, _conn,         \
      72                 :            :                                               "%s: " dbg_fmt,         \
      73                 :            :                                               __func__, ##arg);         \
      74                 :            :                 iscsi_dbg_trace(trace_iscsi_dbg_trans_conn,             \
      75                 :            :                                 &(_conn)->dev,                           \
      76                 :            :                                 "%s " dbg_fmt, __func__, ##arg);      \
      77                 :            :         } while (0);
      78                 :            : 
      79                 :            : struct iscsi_internal {
      80                 :            :         struct scsi_transport_template t;
      81                 :            :         struct iscsi_transport *iscsi_transport;
      82                 :            :         struct list_head list;
      83                 :            :         struct device dev;
      84                 :            : 
      85                 :            :         struct transport_container conn_cont;
      86                 :            :         struct transport_container session_cont;
      87                 :            : };
      88                 :            : 
      89                 :            : static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
      90                 :            : static struct workqueue_struct *iscsi_eh_timer_workq;
      91                 :            : 
      92                 :            : static DEFINE_IDA(iscsi_sess_ida);
      93                 :            : /*
      94                 :            :  * list of registered transports and lock that must
      95                 :            :  * be held while accessing list. The iscsi_transport_lock must
      96                 :            :  * be acquired after the rx_queue_mutex.
      97                 :            :  */
      98                 :            : static LIST_HEAD(iscsi_transports);
      99                 :            : static DEFINE_SPINLOCK(iscsi_transport_lock);
     100                 :            : 
     101                 :            : #define to_iscsi_internal(tmpl) \
     102                 :            :         container_of(tmpl, struct iscsi_internal, t)
     103                 :            : 
     104                 :            : #define dev_to_iscsi_internal(_dev) \
     105                 :            :         container_of(_dev, struct iscsi_internal, dev)
     106                 :            : 
     107                 :          0 : static void iscsi_transport_release(struct device *dev)
     108                 :            : {
     109                 :          0 :         struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
     110                 :          0 :         kfree(priv);
     111                 :          0 : }
     112                 :            : 
     113                 :            : /*
     114                 :            :  * iscsi_transport_class represents the iscsi_transports that are
     115                 :            :  * registered.
     116                 :            :  */
     117                 :            : static struct class iscsi_transport_class = {
     118                 :            :         .name = "iscsi_transport",
     119                 :            :         .dev_release = iscsi_transport_release,
     120                 :            : };
     121                 :            : 
     122                 :            : static ssize_t
     123                 :          0 : show_transport_handle(struct device *dev, struct device_attribute *attr,
     124                 :            :                       char *buf)
     125                 :            : {
     126                 :            :         struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
     127                 :          0 :         return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
     128                 :            : }
     129                 :            : static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
     130                 :            : 
     131                 :            : #define show_transport_attr(name, format)                               \
     132                 :            : static ssize_t                                                          \
     133                 :            : show_transport_##name(struct device *dev,                               \
     134                 :            :                       struct device_attribute *attr,char *buf)          \
     135                 :            : {                                                                       \
     136                 :            :         struct iscsi_internal *priv = dev_to_iscsi_internal(dev);       \
     137                 :            :         return sprintf(buf, format"\n", priv->iscsi_transport->name);   \
     138                 :            : }                                                                       \
     139                 :            : static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
     140                 :            : 
     141                 :          0 : show_transport_attr(caps, "0x%x");
     142                 :            : 
     143                 :            : static struct attribute *iscsi_transport_attrs[] = {
     144                 :            :         &dev_attr_handle.attr,
     145                 :            :         &dev_attr_caps.attr,
     146                 :            :         NULL,
     147                 :            : };
     148                 :            : 
     149                 :            : static struct attribute_group iscsi_transport_group = {
     150                 :            :         .attrs = iscsi_transport_attrs,
     151                 :            : };
     152                 :            : 
     153                 :            : /*
     154                 :            :  * iSCSI endpoint attrs
     155                 :            :  */
     156                 :            : #define iscsi_dev_to_endpoint(_dev) \
     157                 :            :         container_of(_dev, struct iscsi_endpoint, dev)
     158                 :            : 
     159                 :            : #define ISCSI_ATTR(_prefix,_name,_mode,_show,_store)    \
     160                 :            : struct device_attribute dev_attr_##_prefix##_##_name =  \
     161                 :            :         __ATTR(_name,_mode,_show,_store)
     162                 :            : 
     163                 :          0 : static void iscsi_endpoint_release(struct device *dev)
     164                 :            : {
     165                 :          0 :         struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
     166                 :          0 :         kfree(ep);
     167                 :          0 : }
     168                 :            : 
     169                 :            : static struct class iscsi_endpoint_class = {
     170                 :            :         .name = "iscsi_endpoint",
     171                 :            :         .dev_release = iscsi_endpoint_release,
     172                 :            : };
     173                 :            : 
     174                 :            : static ssize_t
     175                 :          0 : show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
     176                 :            : {
     177                 :            :         struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
     178                 :          0 :         return sprintf(buf, "%llu\n", (unsigned long long) ep->id);
     179                 :            : }
     180                 :            : static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
     181                 :            : 
     182                 :            : static struct attribute *iscsi_endpoint_attrs[] = {
     183                 :            :         &dev_attr_ep_handle.attr,
     184                 :            :         NULL,
     185                 :            : };
     186                 :            : 
     187                 :            : static struct attribute_group iscsi_endpoint_group = {
     188                 :            :         .attrs = iscsi_endpoint_attrs,
     189                 :            : };
     190                 :            : 
     191                 :            : #define ISCSI_MAX_EPID -1
     192                 :            : 
     193                 :          0 : static int iscsi_match_epid(struct device *dev, const void *data)
     194                 :            : {
     195                 :            :         struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
     196                 :            :         const uint64_t *epid = data;
     197                 :            : 
     198                 :          0 :         return *epid == ep->id;
     199                 :            : }
     200                 :            : 
     201                 :            : struct iscsi_endpoint *
     202                 :          0 : iscsi_create_endpoint(int dd_size)
     203                 :            : {
     204                 :            :         struct device *dev;
     205                 :            :         struct iscsi_endpoint *ep;
     206                 :            :         uint64_t id;
     207                 :            :         int err;
     208                 :            : 
     209                 :          0 :         for (id = 1; id < ISCSI_MAX_EPID; id++) {
     210                 :          0 :                 dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
     211                 :            :                                         iscsi_match_epid);
     212                 :          0 :                 if (!dev)
     213                 :            :                         break;
     214                 :            :                 else
     215                 :          0 :                         put_device(dev);
     216                 :            :         }
     217                 :          0 :         if (id == ISCSI_MAX_EPID) {
     218                 :          0 :                 printk(KERN_ERR "Too many connections. Max supported %u\n",
     219                 :            :                        ISCSI_MAX_EPID - 1);
     220                 :          0 :                 return NULL;
     221                 :            :         }
     222                 :            : 
     223                 :          0 :         ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL);
     224                 :          0 :         if (!ep)
     225                 :            :                 return NULL;
     226                 :            : 
     227                 :          0 :         ep->id = id;
     228                 :          0 :         ep->dev.class = &iscsi_endpoint_class;
     229                 :          0 :         dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id);
     230                 :          0 :         err = device_register(&ep->dev);
     231                 :          0 :         if (err)
     232                 :            :                 goto free_ep;
     233                 :            : 
     234                 :          0 :         err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
     235                 :          0 :         if (err)
     236                 :            :                 goto unregister_dev;
     237                 :            : 
     238                 :          0 :         if (dd_size)
     239                 :          0 :                 ep->dd_data = &ep[1];
     240                 :          0 :         return ep;
     241                 :            : 
     242                 :            : unregister_dev:
     243                 :          0 :         device_unregister(&ep->dev);
     244                 :          0 :         return NULL;
     245                 :            : 
     246                 :            : free_ep:
     247                 :          0 :         kfree(ep);
     248                 :          0 :         return NULL;
     249                 :            : }
     250                 :            : EXPORT_SYMBOL_GPL(iscsi_create_endpoint);
     251                 :            : 
     252                 :          0 : void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
     253                 :            : {
     254                 :          0 :         sysfs_remove_group(&ep->dev.kobj, &iscsi_endpoint_group);
     255                 :          0 :         device_unregister(&ep->dev);
     256                 :          0 : }
     257                 :            : EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
     258                 :            : 
     259                 :          0 : struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
     260                 :            : {
     261                 :            :         struct iscsi_endpoint *ep;
     262                 :            :         struct device *dev;
     263                 :            : 
     264                 :          0 :         dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
     265                 :            :                                 iscsi_match_epid);
     266                 :          0 :         if (!dev)
     267                 :            :                 return NULL;
     268                 :            : 
     269                 :          0 :         ep = iscsi_dev_to_endpoint(dev);
     270                 :            :         /*
     271                 :            :          * we can drop this now because the interface will prevent
     272                 :            :          * removals and lookups from racing.
     273                 :            :          */
     274                 :          0 :         put_device(dev);
     275                 :          0 :         return ep;
     276                 :            : }
     277                 :            : EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
     278                 :            : 
     279                 :            : /*
     280                 :            :  * Interface to display network param to sysfs
     281                 :            :  */
     282                 :            : 
     283                 :          0 : static void iscsi_iface_release(struct device *dev)
     284                 :            : {
     285                 :            :         struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
     286                 :          0 :         struct device *parent = iface->dev.parent;
     287                 :            : 
     288                 :          0 :         kfree(iface);
     289                 :          0 :         put_device(parent);
     290                 :          0 : }
     291                 :            : 
     292                 :            : 
     293                 :            : static struct class iscsi_iface_class = {
     294                 :            :         .name = "iscsi_iface",
     295                 :            :         .dev_release = iscsi_iface_release,
     296                 :            : };
     297                 :            : 
     298                 :            : #define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store)  \
     299                 :            : struct device_attribute dev_attr_##_prefix##_##_name =          \
     300                 :            :         __ATTR(_name, _mode, _show, _store)
     301                 :            : 
     302                 :            : /* iface attrs show */
     303                 :            : #define iscsi_iface_attr_show(type, name, param_type, param)            \
     304                 :            : static ssize_t                                                          \
     305                 :            : show_##type##_##name(struct device *dev, struct device_attribute *attr, \
     306                 :            :                      char *buf)                                         \
     307                 :            : {                                                                       \
     308                 :            :         struct iscsi_iface *iface = iscsi_dev_to_iface(dev);            \
     309                 :            :         struct iscsi_transport *t = iface->transport;                        \
     310                 :            :         return t->get_iface_param(iface, param_type, param, buf);    \
     311                 :            : }                                                                       \
     312                 :            : 
     313                 :            : #define iscsi_iface_net_attr(type, name, param)                         \
     314                 :            :         iscsi_iface_attr_show(type, name, ISCSI_NET_PARAM, param)       \
     315                 :            : static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
     316                 :            : 
     317                 :            : #define iscsi_iface_attr(type, name, param)                             \
     318                 :            :         iscsi_iface_attr_show(type, name, ISCSI_IFACE_PARAM, param)     \
     319                 :            : static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
     320                 :            : 
     321                 :            : /* generic read only ipv4 attribute */
     322                 :          0 : iscsi_iface_net_attr(ipv4_iface, ipaddress, ISCSI_NET_PARAM_IPV4_ADDR);
     323                 :          0 : iscsi_iface_net_attr(ipv4_iface, gateway, ISCSI_NET_PARAM_IPV4_GW);
     324                 :          0 : iscsi_iface_net_attr(ipv4_iface, subnet, ISCSI_NET_PARAM_IPV4_SUBNET);
     325                 :          0 : iscsi_iface_net_attr(ipv4_iface, bootproto, ISCSI_NET_PARAM_IPV4_BOOTPROTO);
     326                 :          0 : iscsi_iface_net_attr(ipv4_iface, dhcp_dns_address_en,
     327                 :            :                      ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN);
     328                 :          0 : iscsi_iface_net_attr(ipv4_iface, dhcp_slp_da_info_en,
     329                 :            :                      ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN);
     330                 :          0 : iscsi_iface_net_attr(ipv4_iface, tos_en, ISCSI_NET_PARAM_IPV4_TOS_EN);
     331                 :          0 : iscsi_iface_net_attr(ipv4_iface, tos, ISCSI_NET_PARAM_IPV4_TOS);
     332                 :          0 : iscsi_iface_net_attr(ipv4_iface, grat_arp_en,
     333                 :            :                      ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN);
     334                 :          0 : iscsi_iface_net_attr(ipv4_iface, dhcp_alt_client_id_en,
     335                 :            :                      ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN);
     336                 :          0 : iscsi_iface_net_attr(ipv4_iface, dhcp_alt_client_id,
     337                 :            :                      ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID);
     338                 :          0 : iscsi_iface_net_attr(ipv4_iface, dhcp_req_vendor_id_en,
     339                 :            :                      ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN);
     340                 :          0 : iscsi_iface_net_attr(ipv4_iface, dhcp_use_vendor_id_en,
     341                 :            :                      ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN);
     342                 :          0 : iscsi_iface_net_attr(ipv4_iface, dhcp_vendor_id,
     343                 :            :                      ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID);
     344                 :          0 : iscsi_iface_net_attr(ipv4_iface, dhcp_learn_iqn_en,
     345                 :            :                      ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN);
     346                 :          0 : iscsi_iface_net_attr(ipv4_iface, fragment_disable,
     347                 :            :                      ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE);
     348                 :          0 : iscsi_iface_net_attr(ipv4_iface, incoming_forwarding_en,
     349                 :            :                      ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN);
     350                 :          0 : iscsi_iface_net_attr(ipv4_iface, ttl, ISCSI_NET_PARAM_IPV4_TTL);
     351                 :            : 
     352                 :            : /* generic read only ipv6 attribute */
     353                 :          0 : iscsi_iface_net_attr(ipv6_iface, ipaddress, ISCSI_NET_PARAM_IPV6_ADDR);
     354                 :          0 : iscsi_iface_net_attr(ipv6_iface, link_local_addr,
     355                 :            :                      ISCSI_NET_PARAM_IPV6_LINKLOCAL);
     356                 :          0 : iscsi_iface_net_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER);
     357                 :          0 : iscsi_iface_net_attr(ipv6_iface, ipaddr_autocfg,
     358                 :            :                      ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG);
     359                 :          0 : iscsi_iface_net_attr(ipv6_iface, link_local_autocfg,
     360                 :            :                      ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG);
     361                 :          0 : iscsi_iface_net_attr(ipv6_iface, link_local_state,
     362                 :            :                      ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE);
     363                 :          0 : iscsi_iface_net_attr(ipv6_iface, router_state,
     364                 :            :                      ISCSI_NET_PARAM_IPV6_ROUTER_STATE);
     365                 :          0 : iscsi_iface_net_attr(ipv6_iface, grat_neighbor_adv_en,
     366                 :            :                      ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN);
     367                 :          0 : iscsi_iface_net_attr(ipv6_iface, mld_en, ISCSI_NET_PARAM_IPV6_MLD_EN);
     368                 :          0 : iscsi_iface_net_attr(ipv6_iface, flow_label, ISCSI_NET_PARAM_IPV6_FLOW_LABEL);
     369                 :          0 : iscsi_iface_net_attr(ipv6_iface, traffic_class,
     370                 :            :                      ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS);
     371                 :          0 : iscsi_iface_net_attr(ipv6_iface, hop_limit, ISCSI_NET_PARAM_IPV6_HOP_LIMIT);
     372                 :          0 : iscsi_iface_net_attr(ipv6_iface, nd_reachable_tmo,
     373                 :            :                      ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO);
     374                 :          0 : iscsi_iface_net_attr(ipv6_iface, nd_rexmit_time,
     375                 :            :                      ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME);
     376                 :          0 : iscsi_iface_net_attr(ipv6_iface, nd_stale_tmo,
     377                 :            :                      ISCSI_NET_PARAM_IPV6_ND_STALE_TMO);
     378                 :          0 : iscsi_iface_net_attr(ipv6_iface, dup_addr_detect_cnt,
     379                 :            :                      ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT);
     380                 :          0 : iscsi_iface_net_attr(ipv6_iface, router_adv_link_mtu,
     381                 :            :                      ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU);
     382                 :            : 
     383                 :            : /* common read only iface attribute */
     384                 :          0 : iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE);
     385                 :          0 : iscsi_iface_net_attr(iface, vlan_id, ISCSI_NET_PARAM_VLAN_ID);
     386                 :          0 : iscsi_iface_net_attr(iface, vlan_priority, ISCSI_NET_PARAM_VLAN_PRIORITY);
     387                 :          0 : iscsi_iface_net_attr(iface, vlan_enabled, ISCSI_NET_PARAM_VLAN_ENABLED);
     388                 :          0 : iscsi_iface_net_attr(iface, mtu, ISCSI_NET_PARAM_MTU);
     389                 :          0 : iscsi_iface_net_attr(iface, port, ISCSI_NET_PARAM_PORT);
     390                 :          0 : iscsi_iface_net_attr(iface, ipaddress_state, ISCSI_NET_PARAM_IPADDR_STATE);
     391                 :          0 : iscsi_iface_net_attr(iface, delayed_ack_en, ISCSI_NET_PARAM_DELAYED_ACK_EN);
     392                 :          0 : iscsi_iface_net_attr(iface, tcp_nagle_disable,
     393                 :            :                      ISCSI_NET_PARAM_TCP_NAGLE_DISABLE);
     394                 :          0 : iscsi_iface_net_attr(iface, tcp_wsf_disable, ISCSI_NET_PARAM_TCP_WSF_DISABLE);
     395                 :          0 : iscsi_iface_net_attr(iface, tcp_wsf, ISCSI_NET_PARAM_TCP_WSF);
     396                 :          0 : iscsi_iface_net_attr(iface, tcp_timer_scale, ISCSI_NET_PARAM_TCP_TIMER_SCALE);
     397                 :          0 : iscsi_iface_net_attr(iface, tcp_timestamp_en, ISCSI_NET_PARAM_TCP_TIMESTAMP_EN);
     398                 :          0 : iscsi_iface_net_attr(iface, cache_id, ISCSI_NET_PARAM_CACHE_ID);
     399                 :          0 : iscsi_iface_net_attr(iface, redirect_en, ISCSI_NET_PARAM_REDIRECT_EN);
     400                 :            : 
     401                 :            : /* common iscsi specific settings attributes */
     402                 :          0 : iscsi_iface_attr(iface, def_taskmgmt_tmo, ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO);
     403                 :          0 : iscsi_iface_attr(iface, header_digest, ISCSI_IFACE_PARAM_HDRDGST_EN);
     404                 :          0 : iscsi_iface_attr(iface, data_digest, ISCSI_IFACE_PARAM_DATADGST_EN);
     405                 :          0 : iscsi_iface_attr(iface, immediate_data, ISCSI_IFACE_PARAM_IMM_DATA_EN);
     406                 :          0 : iscsi_iface_attr(iface, initial_r2t, ISCSI_IFACE_PARAM_INITIAL_R2T_EN);
     407                 :          0 : iscsi_iface_attr(iface, data_seq_in_order,
     408                 :            :                  ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN);
     409                 :          0 : iscsi_iface_attr(iface, data_pdu_in_order, ISCSI_IFACE_PARAM_PDU_INORDER_EN);
     410                 :          0 : iscsi_iface_attr(iface, erl, ISCSI_IFACE_PARAM_ERL);
     411                 :          0 : iscsi_iface_attr(iface, max_recv_dlength, ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH);
     412                 :          0 : iscsi_iface_attr(iface, first_burst_len, ISCSI_IFACE_PARAM_FIRST_BURST);
     413                 :          0 : iscsi_iface_attr(iface, max_outstanding_r2t, ISCSI_IFACE_PARAM_MAX_R2T);
     414                 :          0 : iscsi_iface_attr(iface, max_burst_len, ISCSI_IFACE_PARAM_MAX_BURST);
     415                 :          0 : iscsi_iface_attr(iface, chap_auth, ISCSI_IFACE_PARAM_CHAP_AUTH_EN);
     416                 :          0 : iscsi_iface_attr(iface, bidi_chap, ISCSI_IFACE_PARAM_BIDI_CHAP_EN);
     417                 :          0 : iscsi_iface_attr(iface, discovery_auth_optional,
     418                 :            :                  ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL);
     419                 :          0 : iscsi_iface_attr(iface, discovery_logout,
     420                 :            :                  ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN);
     421                 :          0 : iscsi_iface_attr(iface, strict_login_comp_en,
     422                 :            :                  ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN);
     423                 :          0 : iscsi_iface_attr(iface, initiator_name, ISCSI_IFACE_PARAM_INITIATOR_NAME);
     424                 :            : 
     425                 :          0 : static umode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
     426                 :            :                                           struct attribute *attr, int i)
     427                 :            : {
     428                 :            :         struct device *dev = container_of(kobj, struct device, kobj);
     429                 :            :         struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
     430                 :          0 :         struct iscsi_transport *t = iface->transport;
     431                 :            :         int param;
     432                 :            :         int param_type;
     433                 :            : 
     434                 :          0 :         if (attr == &dev_attr_iface_enabled.attr)
     435                 :            :                 param = ISCSI_NET_PARAM_IFACE_ENABLE;
     436                 :          0 :         else if (attr == &dev_attr_iface_vlan_id.attr)
     437                 :            :                 param = ISCSI_NET_PARAM_VLAN_ID;
     438                 :          0 :         else if (attr == &dev_attr_iface_vlan_priority.attr)
     439                 :            :                 param = ISCSI_NET_PARAM_VLAN_PRIORITY;
     440                 :          0 :         else if (attr == &dev_attr_iface_vlan_enabled.attr)
     441                 :            :                 param = ISCSI_NET_PARAM_VLAN_ENABLED;
     442                 :          0 :         else if (attr == &dev_attr_iface_mtu.attr)
     443                 :            :                 param = ISCSI_NET_PARAM_MTU;
     444                 :          0 :         else if (attr == &dev_attr_iface_port.attr)
     445                 :            :                 param = ISCSI_NET_PARAM_PORT;
     446                 :          0 :         else if (attr == &dev_attr_iface_ipaddress_state.attr)
     447                 :            :                 param = ISCSI_NET_PARAM_IPADDR_STATE;
     448                 :          0 :         else if (attr == &dev_attr_iface_delayed_ack_en.attr)
     449                 :            :                 param = ISCSI_NET_PARAM_DELAYED_ACK_EN;
     450                 :          0 :         else if (attr == &dev_attr_iface_tcp_nagle_disable.attr)
     451                 :            :                 param = ISCSI_NET_PARAM_TCP_NAGLE_DISABLE;
     452                 :          0 :         else if (attr == &dev_attr_iface_tcp_wsf_disable.attr)
     453                 :            :                 param = ISCSI_NET_PARAM_TCP_WSF_DISABLE;
     454                 :          0 :         else if (attr == &dev_attr_iface_tcp_wsf.attr)
     455                 :            :                 param = ISCSI_NET_PARAM_TCP_WSF;
     456                 :          0 :         else if (attr == &dev_attr_iface_tcp_timer_scale.attr)
     457                 :            :                 param = ISCSI_NET_PARAM_TCP_TIMER_SCALE;
     458                 :          0 :         else if (attr == &dev_attr_iface_tcp_timestamp_en.attr)
     459                 :            :                 param = ISCSI_NET_PARAM_TCP_TIMESTAMP_EN;
     460                 :          0 :         else if (attr == &dev_attr_iface_cache_id.attr)
     461                 :            :                 param = ISCSI_NET_PARAM_CACHE_ID;
     462                 :          0 :         else if (attr == &dev_attr_iface_redirect_en.attr)
     463                 :            :                 param = ISCSI_NET_PARAM_REDIRECT_EN;
     464                 :          0 :         else if (attr == &dev_attr_iface_def_taskmgmt_tmo.attr)
     465                 :            :                 param = ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO;
     466                 :          0 :         else if (attr == &dev_attr_iface_header_digest.attr)
     467                 :            :                 param = ISCSI_IFACE_PARAM_HDRDGST_EN;
     468                 :          0 :         else if (attr == &dev_attr_iface_data_digest.attr)
     469                 :            :                 param = ISCSI_IFACE_PARAM_DATADGST_EN;
     470                 :          0 :         else if (attr == &dev_attr_iface_immediate_data.attr)
     471                 :            :                 param = ISCSI_IFACE_PARAM_IMM_DATA_EN;
     472                 :          0 :         else if (attr == &dev_attr_iface_initial_r2t.attr)
     473                 :            :                 param = ISCSI_IFACE_PARAM_INITIAL_R2T_EN;
     474                 :          0 :         else if (attr == &dev_attr_iface_data_seq_in_order.attr)
     475                 :            :                 param = ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN;
     476                 :          0 :         else if (attr == &dev_attr_iface_data_pdu_in_order.attr)
     477                 :            :                 param = ISCSI_IFACE_PARAM_PDU_INORDER_EN;
     478                 :          0 :         else if (attr == &dev_attr_iface_erl.attr)
     479                 :            :                 param = ISCSI_IFACE_PARAM_ERL;
     480                 :          0 :         else if (attr == &dev_attr_iface_max_recv_dlength.attr)
     481                 :            :                 param = ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH;
     482                 :          0 :         else if (attr == &dev_attr_iface_first_burst_len.attr)
     483                 :            :                 param = ISCSI_IFACE_PARAM_FIRST_BURST;
     484                 :          0 :         else if (attr == &dev_attr_iface_max_outstanding_r2t.attr)
     485                 :            :                 param = ISCSI_IFACE_PARAM_MAX_R2T;
     486                 :          0 :         else if (attr == &dev_attr_iface_max_burst_len.attr)
     487                 :            :                 param = ISCSI_IFACE_PARAM_MAX_BURST;
     488                 :          0 :         else if (attr == &dev_attr_iface_chap_auth.attr)
     489                 :            :                 param = ISCSI_IFACE_PARAM_CHAP_AUTH_EN;
     490                 :          0 :         else if (attr == &dev_attr_iface_bidi_chap.attr)
     491                 :            :                 param = ISCSI_IFACE_PARAM_BIDI_CHAP_EN;
     492                 :          0 :         else if (attr == &dev_attr_iface_discovery_auth_optional.attr)
     493                 :            :                 param = ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL;
     494                 :          0 :         else if (attr == &dev_attr_iface_discovery_logout.attr)
     495                 :            :                 param = ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN;
     496                 :          0 :         else if (attr == &dev_attr_iface_strict_login_comp_en.attr)
     497                 :            :                 param = ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN;
     498                 :          0 :         else if (attr == &dev_attr_iface_initiator_name.attr)
     499                 :            :                 param = ISCSI_IFACE_PARAM_INITIATOR_NAME;
     500                 :          0 :         else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
     501                 :          0 :                 if (attr == &dev_attr_ipv4_iface_ipaddress.attr)
     502                 :            :                         param = ISCSI_NET_PARAM_IPV4_ADDR;
     503                 :          0 :                 else if (attr == &dev_attr_ipv4_iface_gateway.attr)
     504                 :            :                         param = ISCSI_NET_PARAM_IPV4_GW;
     505                 :          0 :                 else if (attr == &dev_attr_ipv4_iface_subnet.attr)
     506                 :            :                         param = ISCSI_NET_PARAM_IPV4_SUBNET;
     507                 :          0 :                 else if (attr == &dev_attr_ipv4_iface_bootproto.attr)
     508                 :            :                         param = ISCSI_NET_PARAM_IPV4_BOOTPROTO;
     509                 :          0 :                 else if (attr ==
     510                 :            :                          &dev_attr_ipv4_iface_dhcp_dns_address_en.attr)
     511                 :            :                         param = ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN;
     512                 :          0 :                 else if (attr ==
     513                 :            :                          &dev_attr_ipv4_iface_dhcp_slp_da_info_en.attr)
     514                 :            :                         param = ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN;
     515                 :          0 :                 else if (attr == &dev_attr_ipv4_iface_tos_en.attr)
     516                 :            :                         param = ISCSI_NET_PARAM_IPV4_TOS_EN;
     517                 :          0 :                 else if (attr == &dev_attr_ipv4_iface_tos.attr)
     518                 :            :                         param = ISCSI_NET_PARAM_IPV4_TOS;
     519                 :          0 :                 else if (attr == &dev_attr_ipv4_iface_grat_arp_en.attr)
     520                 :            :                         param = ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN;
     521                 :          0 :                 else if (attr ==
     522                 :            :                          &dev_attr_ipv4_iface_dhcp_alt_client_id_en.attr)
     523                 :            :                         param = ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN;
     524                 :          0 :                 else if (attr == &dev_attr_ipv4_iface_dhcp_alt_client_id.attr)
     525                 :            :                         param = ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID;
     526                 :          0 :                 else if (attr ==
     527                 :            :                          &dev_attr_ipv4_iface_dhcp_req_vendor_id_en.attr)
     528                 :            :                         param = ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN;
     529                 :          0 :                 else if (attr ==
     530                 :            :                          &dev_attr_ipv4_iface_dhcp_use_vendor_id_en.attr)
     531                 :            :                         param = ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN;
     532                 :          0 :                 else if (attr == &dev_attr_ipv4_iface_dhcp_vendor_id.attr)
     533                 :            :                         param = ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID;
     534                 :          0 :                 else if (attr ==
     535                 :            :                          &dev_attr_ipv4_iface_dhcp_learn_iqn_en.attr)
     536                 :            :                         param = ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN;
     537                 :          0 :                 else if (attr ==
     538                 :            :                          &dev_attr_ipv4_iface_fragment_disable.attr)
     539                 :            :                         param = ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE;
     540                 :          0 :                 else if (attr ==
     541                 :            :                          &dev_attr_ipv4_iface_incoming_forwarding_en.attr)
     542                 :            :                         param = ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN;
     543                 :          0 :                 else if (attr == &dev_attr_ipv4_iface_ttl.attr)
     544                 :            :                         param = ISCSI_NET_PARAM_IPV4_TTL;
     545                 :            :                 else
     546                 :            :                         return 0;
     547                 :          0 :         } else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) {
     548                 :          0 :                 if (attr == &dev_attr_ipv6_iface_ipaddress.attr)
     549                 :            :                         param = ISCSI_NET_PARAM_IPV6_ADDR;
     550                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_link_local_addr.attr)
     551                 :            :                         param = ISCSI_NET_PARAM_IPV6_LINKLOCAL;
     552                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_router_addr.attr)
     553                 :            :                         param = ISCSI_NET_PARAM_IPV6_ROUTER;
     554                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_ipaddr_autocfg.attr)
     555                 :            :                         param = ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG;
     556                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_link_local_autocfg.attr)
     557                 :            :                         param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG;
     558                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_link_local_state.attr)
     559                 :            :                         param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE;
     560                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_router_state.attr)
     561                 :            :                         param = ISCSI_NET_PARAM_IPV6_ROUTER_STATE;
     562                 :          0 :                 else if (attr ==
     563                 :            :                          &dev_attr_ipv6_iface_grat_neighbor_adv_en.attr)
     564                 :            :                         param = ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN;
     565                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_mld_en.attr)
     566                 :            :                         param = ISCSI_NET_PARAM_IPV6_MLD_EN;
     567                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_flow_label.attr)
     568                 :            :                         param = ISCSI_NET_PARAM_IPV6_FLOW_LABEL;
     569                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_traffic_class.attr)
     570                 :            :                         param = ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS;
     571                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_hop_limit.attr)
     572                 :            :                         param = ISCSI_NET_PARAM_IPV6_HOP_LIMIT;
     573                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_nd_reachable_tmo.attr)
     574                 :            :                         param = ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO;
     575                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_nd_rexmit_time.attr)
     576                 :            :                         param = ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME;
     577                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_nd_stale_tmo.attr)
     578                 :            :                         param = ISCSI_NET_PARAM_IPV6_ND_STALE_TMO;
     579                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_dup_addr_detect_cnt.attr)
     580                 :            :                         param = ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT;
     581                 :          0 :                 else if (attr == &dev_attr_ipv6_iface_router_adv_link_mtu.attr)
     582                 :            :                         param = ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU;
     583                 :            :                 else
     584                 :            :                         return 0;
     585                 :            :         } else {
     586                 :          0 :                 WARN_ONCE(1, "Invalid iface attr");
     587                 :            :                 return 0;
     588                 :            :         }
     589                 :            : 
     590                 :          0 :         switch (param) {
     591                 :            :         case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO:
     592                 :            :         case ISCSI_IFACE_PARAM_HDRDGST_EN:
     593                 :            :         case ISCSI_IFACE_PARAM_DATADGST_EN:
     594                 :            :         case ISCSI_IFACE_PARAM_IMM_DATA_EN:
     595                 :            :         case ISCSI_IFACE_PARAM_INITIAL_R2T_EN:
     596                 :            :         case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN:
     597                 :            :         case ISCSI_IFACE_PARAM_PDU_INORDER_EN:
     598                 :            :         case ISCSI_IFACE_PARAM_ERL:
     599                 :            :         case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH:
     600                 :            :         case ISCSI_IFACE_PARAM_FIRST_BURST:
     601                 :            :         case ISCSI_IFACE_PARAM_MAX_R2T:
     602                 :            :         case ISCSI_IFACE_PARAM_MAX_BURST:
     603                 :            :         case ISCSI_IFACE_PARAM_CHAP_AUTH_EN:
     604                 :            :         case ISCSI_IFACE_PARAM_BIDI_CHAP_EN:
     605                 :            :         case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL:
     606                 :            :         case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN:
     607                 :            :         case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN:
     608                 :            :         case ISCSI_IFACE_PARAM_INITIATOR_NAME:
     609                 :            :                 param_type = ISCSI_IFACE_PARAM;
     610                 :            :                 break;
     611                 :            :         default:
     612                 :            :                 param_type = ISCSI_NET_PARAM;
     613                 :            :         }
     614                 :            : 
     615                 :          0 :         return t->attr_is_visible(param_type, param);
     616                 :            : }
     617                 :            : 
     618                 :            : static struct attribute *iscsi_iface_attrs[] = {
     619                 :            :         &dev_attr_iface_enabled.attr,
     620                 :            :         &dev_attr_iface_vlan_id.attr,
     621                 :            :         &dev_attr_iface_vlan_priority.attr,
     622                 :            :         &dev_attr_iface_vlan_enabled.attr,
     623                 :            :         &dev_attr_ipv4_iface_ipaddress.attr,
     624                 :            :         &dev_attr_ipv4_iface_gateway.attr,
     625                 :            :         &dev_attr_ipv4_iface_subnet.attr,
     626                 :            :         &dev_attr_ipv4_iface_bootproto.attr,
     627                 :            :         &dev_attr_ipv6_iface_ipaddress.attr,
     628                 :            :         &dev_attr_ipv6_iface_link_local_addr.attr,
     629                 :            :         &dev_attr_ipv6_iface_router_addr.attr,
     630                 :            :         &dev_attr_ipv6_iface_ipaddr_autocfg.attr,
     631                 :            :         &dev_attr_ipv6_iface_link_local_autocfg.attr,
     632                 :            :         &dev_attr_iface_mtu.attr,
     633                 :            :         &dev_attr_iface_port.attr,
     634                 :            :         &dev_attr_iface_ipaddress_state.attr,
     635                 :            :         &dev_attr_iface_delayed_ack_en.attr,
     636                 :            :         &dev_attr_iface_tcp_nagle_disable.attr,
     637                 :            :         &dev_attr_iface_tcp_wsf_disable.attr,
     638                 :            :         &dev_attr_iface_tcp_wsf.attr,
     639                 :            :         &dev_attr_iface_tcp_timer_scale.attr,
     640                 :            :         &dev_attr_iface_tcp_timestamp_en.attr,
     641                 :            :         &dev_attr_iface_cache_id.attr,
     642                 :            :         &dev_attr_iface_redirect_en.attr,
     643                 :            :         &dev_attr_iface_def_taskmgmt_tmo.attr,
     644                 :            :         &dev_attr_iface_header_digest.attr,
     645                 :            :         &dev_attr_iface_data_digest.attr,
     646                 :            :         &dev_attr_iface_immediate_data.attr,
     647                 :            :         &dev_attr_iface_initial_r2t.attr,
     648                 :            :         &dev_attr_iface_data_seq_in_order.attr,
     649                 :            :         &dev_attr_iface_data_pdu_in_order.attr,
     650                 :            :         &dev_attr_iface_erl.attr,
     651                 :            :         &dev_attr_iface_max_recv_dlength.attr,
     652                 :            :         &dev_attr_iface_first_burst_len.attr,
     653                 :            :         &dev_attr_iface_max_outstanding_r2t.attr,
     654                 :            :         &dev_attr_iface_max_burst_len.attr,
     655                 :            :         &dev_attr_iface_chap_auth.attr,
     656                 :            :         &dev_attr_iface_bidi_chap.attr,
     657                 :            :         &dev_attr_iface_discovery_auth_optional.attr,
     658                 :            :         &dev_attr_iface_discovery_logout.attr,
     659                 :            :         &dev_attr_iface_strict_login_comp_en.attr,
     660                 :            :         &dev_attr_iface_initiator_name.attr,
     661                 :            :         &dev_attr_ipv4_iface_dhcp_dns_address_en.attr,
     662                 :            :         &dev_attr_ipv4_iface_dhcp_slp_da_info_en.attr,
     663                 :            :         &dev_attr_ipv4_iface_tos_en.attr,
     664                 :            :         &dev_attr_ipv4_iface_tos.attr,
     665                 :            :         &dev_attr_ipv4_iface_grat_arp_en.attr,
     666                 :            :         &dev_attr_ipv4_iface_dhcp_alt_client_id_en.attr,
     667                 :            :         &dev_attr_ipv4_iface_dhcp_alt_client_id.attr,
     668                 :            :         &dev_attr_ipv4_iface_dhcp_req_vendor_id_en.attr,
     669                 :            :         &dev_attr_ipv4_iface_dhcp_use_vendor_id_en.attr,
     670                 :            :         &dev_attr_ipv4_iface_dhcp_vendor_id.attr,
     671                 :            :         &dev_attr_ipv4_iface_dhcp_learn_iqn_en.attr,
     672                 :            :         &dev_attr_ipv4_iface_fragment_disable.attr,
     673                 :            :         &dev_attr_ipv4_iface_incoming_forwarding_en.attr,
     674                 :            :         &dev_attr_ipv4_iface_ttl.attr,
     675                 :            :         &dev_attr_ipv6_iface_link_local_state.attr,
     676                 :            :         &dev_attr_ipv6_iface_router_state.attr,
     677                 :            :         &dev_attr_ipv6_iface_grat_neighbor_adv_en.attr,
     678                 :            :         &dev_attr_ipv6_iface_mld_en.attr,
     679                 :            :         &dev_attr_ipv6_iface_flow_label.attr,
     680                 :            :         &dev_attr_ipv6_iface_traffic_class.attr,
     681                 :            :         &dev_attr_ipv6_iface_hop_limit.attr,
     682                 :            :         &dev_attr_ipv6_iface_nd_reachable_tmo.attr,
     683                 :            :         &dev_attr_ipv6_iface_nd_rexmit_time.attr,
     684                 :            :         &dev_attr_ipv6_iface_nd_stale_tmo.attr,
     685                 :            :         &dev_attr_ipv6_iface_dup_addr_detect_cnt.attr,
     686                 :            :         &dev_attr_ipv6_iface_router_adv_link_mtu.attr,
     687                 :            :         NULL,
     688                 :            : };
     689                 :            : 
     690                 :            : static struct attribute_group iscsi_iface_group = {
     691                 :            :         .attrs = iscsi_iface_attrs,
     692                 :            :         .is_visible = iscsi_iface_attr_is_visible,
     693                 :            : };
     694                 :            : 
     695                 :            : /* convert iscsi_ipaddress_state values to ascii string name */
     696                 :            : static const struct {
     697                 :            :         enum iscsi_ipaddress_state      value;
     698                 :            :         char                            *name;
     699                 :            : } iscsi_ipaddress_state_names[] = {
     700                 :            :         {ISCSI_IPDDRESS_STATE_UNCONFIGURED,     "Unconfigured" },
     701                 :            :         {ISCSI_IPDDRESS_STATE_ACQUIRING,        "Acquiring" },
     702                 :            :         {ISCSI_IPDDRESS_STATE_TENTATIVE,        "Tentative" },
     703                 :            :         {ISCSI_IPDDRESS_STATE_VALID,            "Valid" },
     704                 :            :         {ISCSI_IPDDRESS_STATE_DISABLING,        "Disabling" },
     705                 :            :         {ISCSI_IPDDRESS_STATE_INVALID,          "Invalid" },
     706                 :            :         {ISCSI_IPDDRESS_STATE_DEPRECATED,       "Deprecated" },
     707                 :            : };
     708                 :            : 
     709                 :          0 : char *iscsi_get_ipaddress_state_name(enum iscsi_ipaddress_state port_state)
     710                 :            : {
     711                 :            :         int i;
     712                 :            :         char *state = NULL;
     713                 :            : 
     714                 :          0 :         for (i = 0; i < ARRAY_SIZE(iscsi_ipaddress_state_names); i++) {
     715                 :          0 :                 if (iscsi_ipaddress_state_names[i].value == port_state) {
     716                 :          0 :                         state = iscsi_ipaddress_state_names[i].name;
     717                 :          0 :                         break;
     718                 :            :                 }
     719                 :            :         }
     720                 :          0 :         return state;
     721                 :            : }
     722                 :            : EXPORT_SYMBOL_GPL(iscsi_get_ipaddress_state_name);
     723                 :            : 
     724                 :            : /* convert iscsi_router_state values to ascii string name */
     725                 :            : static const struct {
     726                 :            :         enum iscsi_router_state value;
     727                 :            :         char                    *name;
     728                 :            : } iscsi_router_state_names[] = {
     729                 :            :         {ISCSI_ROUTER_STATE_UNKNOWN,            "Unknown" },
     730                 :            :         {ISCSI_ROUTER_STATE_ADVERTISED,         "Advertised" },
     731                 :            :         {ISCSI_ROUTER_STATE_MANUAL,             "Manual" },
     732                 :            :         {ISCSI_ROUTER_STATE_STALE,              "Stale" },
     733                 :            : };
     734                 :            : 
     735                 :          0 : char *iscsi_get_router_state_name(enum iscsi_router_state router_state)
     736                 :            : {
     737                 :            :         int i;
     738                 :            :         char *state = NULL;
     739                 :            : 
     740                 :          0 :         for (i = 0; i < ARRAY_SIZE(iscsi_router_state_names); i++) {
     741                 :          0 :                 if (iscsi_router_state_names[i].value == router_state) {
     742                 :          0 :                         state = iscsi_router_state_names[i].name;
     743                 :          0 :                         break;
     744                 :            :                 }
     745                 :            :         }
     746                 :          0 :         return state;
     747                 :            : }
     748                 :            : EXPORT_SYMBOL_GPL(iscsi_get_router_state_name);
     749                 :            : 
     750                 :            : struct iscsi_iface *
     751                 :          0 : iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
     752                 :            :                    uint32_t iface_type, uint32_t iface_num, int dd_size)
     753                 :            : {
     754                 :            :         struct iscsi_iface *iface;
     755                 :            :         int err;
     756                 :            : 
     757                 :          0 :         iface = kzalloc(sizeof(*iface) + dd_size, GFP_KERNEL);
     758                 :          0 :         if (!iface)
     759                 :            :                 return NULL;
     760                 :            : 
     761                 :          0 :         iface->transport = transport;
     762                 :          0 :         iface->iface_type = iface_type;
     763                 :          0 :         iface->iface_num = iface_num;
     764                 :          0 :         iface->dev.release = iscsi_iface_release;
     765                 :          0 :         iface->dev.class = &iscsi_iface_class;
     766                 :            :         /* parent reference released in iscsi_iface_release */
     767                 :          0 :         iface->dev.parent = get_device(&shost->shost_gendev);
     768                 :          0 :         if (iface_type == ISCSI_IFACE_TYPE_IPV4)
     769                 :          0 :                 dev_set_name(&iface->dev, "ipv4-iface-%u-%u", shost->host_no,
     770                 :            :                              iface_num);
     771                 :            :         else
     772                 :          0 :                 dev_set_name(&iface->dev, "ipv6-iface-%u-%u", shost->host_no,
     773                 :            :                              iface_num);
     774                 :            : 
     775                 :          0 :         err = device_register(&iface->dev);
     776                 :          0 :         if (err)
     777                 :            :                 goto free_iface;
     778                 :            : 
     779                 :          0 :         err = sysfs_create_group(&iface->dev.kobj, &iscsi_iface_group);
     780                 :          0 :         if (err)
     781                 :            :                 goto unreg_iface;
     782                 :            : 
     783                 :          0 :         if (dd_size)
     784                 :          0 :                 iface->dd_data = &iface[1];
     785                 :          0 :         return iface;
     786                 :            : 
     787                 :            : unreg_iface:
     788                 :          0 :         device_unregister(&iface->dev);
     789                 :          0 :         return NULL;
     790                 :            : 
     791                 :            : free_iface:
     792                 :          0 :         put_device(iface->dev.parent);
     793                 :          0 :         kfree(iface);
     794                 :          0 :         return NULL;
     795                 :            : }
     796                 :            : EXPORT_SYMBOL_GPL(iscsi_create_iface);
     797                 :            : 
     798                 :          0 : void iscsi_destroy_iface(struct iscsi_iface *iface)
     799                 :            : {
     800                 :          0 :         sysfs_remove_group(&iface->dev.kobj, &iscsi_iface_group);
     801                 :          0 :         device_unregister(&iface->dev);
     802                 :          0 : }
     803                 :            : EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
     804                 :            : 
     805                 :            : /*
     806                 :            :  * Interface to display flash node params to sysfs
     807                 :            :  */
     808                 :            : 
     809                 :            : #define ISCSI_FLASHNODE_ATTR(_prefix, _name, _mode, _show, _store)      \
     810                 :            : struct device_attribute dev_attr_##_prefix##_##_name =                  \
     811                 :            :         __ATTR(_name, _mode, _show, _store)
     812                 :            : 
     813                 :            : /* flash node session attrs show */
     814                 :            : #define iscsi_flashnode_sess_attr_show(type, name, param)               \
     815                 :            : static ssize_t                                                          \
     816                 :            : show_##type##_##name(struct device *dev, struct device_attribute *attr, \
     817                 :            :                      char *buf)                                         \
     818                 :            : {                                                                       \
     819                 :            :         struct iscsi_bus_flash_session *fnode_sess =                    \
     820                 :            :                                         iscsi_dev_to_flash_session(dev);\
     821                 :            :         struct iscsi_transport *t = fnode_sess->transport;           \
     822                 :            :         return t->get_flashnode_param(fnode_sess, param, buf);               \
     823                 :            : }                                                                       \
     824                 :            : 
     825                 :            : 
     826                 :            : #define iscsi_flashnode_sess_attr(type, name, param)                    \
     827                 :            :         iscsi_flashnode_sess_attr_show(type, name, param)               \
     828                 :            : static ISCSI_FLASHNODE_ATTR(type, name, S_IRUGO,                        \
     829                 :            :                             show_##type##_##name, NULL);
     830                 :            : 
     831                 :            : /* Flash node session attributes */
     832                 :            : 
     833                 :          0 : iscsi_flashnode_sess_attr(fnode, auto_snd_tgt_disable,
     834                 :            :                           ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE);
     835                 :          0 : iscsi_flashnode_sess_attr(fnode, discovery_session,
     836                 :            :                           ISCSI_FLASHNODE_DISCOVERY_SESS);
     837                 :          0 : iscsi_flashnode_sess_attr(fnode, portal_type, ISCSI_FLASHNODE_PORTAL_TYPE);
     838                 :          0 : iscsi_flashnode_sess_attr(fnode, entry_enable, ISCSI_FLASHNODE_ENTRY_EN);
     839                 :          0 : iscsi_flashnode_sess_attr(fnode, immediate_data, ISCSI_FLASHNODE_IMM_DATA_EN);
     840                 :          0 : iscsi_flashnode_sess_attr(fnode, initial_r2t, ISCSI_FLASHNODE_INITIAL_R2T_EN);
     841                 :          0 : iscsi_flashnode_sess_attr(fnode, data_seq_in_order,
     842                 :            :                           ISCSI_FLASHNODE_DATASEQ_INORDER);
     843                 :          0 : iscsi_flashnode_sess_attr(fnode, data_pdu_in_order,
     844                 :            :                           ISCSI_FLASHNODE_PDU_INORDER);
     845                 :          0 : iscsi_flashnode_sess_attr(fnode, chap_auth, ISCSI_FLASHNODE_CHAP_AUTH_EN);
     846                 :          0 : iscsi_flashnode_sess_attr(fnode, discovery_logout,
     847                 :            :                           ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN);
     848                 :          0 : iscsi_flashnode_sess_attr(fnode, bidi_chap, ISCSI_FLASHNODE_BIDI_CHAP_EN);
     849                 :          0 : iscsi_flashnode_sess_attr(fnode, discovery_auth_optional,
     850                 :            :                           ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL);
     851                 :          0 : iscsi_flashnode_sess_attr(fnode, erl, ISCSI_FLASHNODE_ERL);
     852                 :          0 : iscsi_flashnode_sess_attr(fnode, first_burst_len, ISCSI_FLASHNODE_FIRST_BURST);
     853                 :          0 : iscsi_flashnode_sess_attr(fnode, def_time2wait, ISCSI_FLASHNODE_DEF_TIME2WAIT);
     854                 :          0 : iscsi_flashnode_sess_attr(fnode, def_time2retain,
     855                 :            :                           ISCSI_FLASHNODE_DEF_TIME2RETAIN);
     856                 :          0 : iscsi_flashnode_sess_attr(fnode, max_outstanding_r2t, ISCSI_FLASHNODE_MAX_R2T);
     857                 :          0 : iscsi_flashnode_sess_attr(fnode, isid, ISCSI_FLASHNODE_ISID);
     858                 :          0 : iscsi_flashnode_sess_attr(fnode, tsid, ISCSI_FLASHNODE_TSID);
     859                 :          0 : iscsi_flashnode_sess_attr(fnode, max_burst_len, ISCSI_FLASHNODE_MAX_BURST);
     860                 :          0 : iscsi_flashnode_sess_attr(fnode, def_taskmgmt_tmo,
     861                 :            :                           ISCSI_FLASHNODE_DEF_TASKMGMT_TMO);
     862                 :          0 : iscsi_flashnode_sess_attr(fnode, targetalias, ISCSI_FLASHNODE_ALIAS);
     863                 :          0 : iscsi_flashnode_sess_attr(fnode, targetname, ISCSI_FLASHNODE_NAME);
     864                 :          0 : iscsi_flashnode_sess_attr(fnode, tpgt, ISCSI_FLASHNODE_TPGT);
     865                 :          0 : iscsi_flashnode_sess_attr(fnode, discovery_parent_idx,
     866                 :            :                           ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX);
     867                 :          0 : iscsi_flashnode_sess_attr(fnode, discovery_parent_type,
     868                 :            :                           ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE);
     869                 :          0 : iscsi_flashnode_sess_attr(fnode, chap_in_idx, ISCSI_FLASHNODE_CHAP_IN_IDX);
     870                 :          0 : iscsi_flashnode_sess_attr(fnode, chap_out_idx, ISCSI_FLASHNODE_CHAP_OUT_IDX);
     871                 :          0 : iscsi_flashnode_sess_attr(fnode, username, ISCSI_FLASHNODE_USERNAME);
     872                 :          0 : iscsi_flashnode_sess_attr(fnode, username_in, ISCSI_FLASHNODE_USERNAME_IN);
     873                 :          0 : iscsi_flashnode_sess_attr(fnode, password, ISCSI_FLASHNODE_PASSWORD);
     874                 :          0 : iscsi_flashnode_sess_attr(fnode, password_in, ISCSI_FLASHNODE_PASSWORD_IN);
     875                 :          0 : iscsi_flashnode_sess_attr(fnode, is_boot_target, ISCSI_FLASHNODE_IS_BOOT_TGT);
     876                 :            : 
     877                 :            : static struct attribute *iscsi_flashnode_sess_attrs[] = {
     878                 :            :         &dev_attr_fnode_auto_snd_tgt_disable.attr,
     879                 :            :         &dev_attr_fnode_discovery_session.attr,
     880                 :            :         &dev_attr_fnode_portal_type.attr,
     881                 :            :         &dev_attr_fnode_entry_enable.attr,
     882                 :            :         &dev_attr_fnode_immediate_data.attr,
     883                 :            :         &dev_attr_fnode_initial_r2t.attr,
     884                 :            :         &dev_attr_fnode_data_seq_in_order.attr,
     885                 :            :         &dev_attr_fnode_data_pdu_in_order.attr,
     886                 :            :         &dev_attr_fnode_chap_auth.attr,
     887                 :            :         &dev_attr_fnode_discovery_logout.attr,
     888                 :            :         &dev_attr_fnode_bidi_chap.attr,
     889                 :            :         &dev_attr_fnode_discovery_auth_optional.attr,
     890                 :            :         &dev_attr_fnode_erl.attr,
     891                 :            :         &dev_attr_fnode_first_burst_len.attr,
     892                 :            :         &dev_attr_fnode_def_time2wait.attr,
     893                 :            :         &dev_attr_fnode_def_time2retain.attr,
     894                 :            :         &dev_attr_fnode_max_outstanding_r2t.attr,
     895                 :            :         &dev_attr_fnode_isid.attr,
     896                 :            :         &dev_attr_fnode_tsid.attr,
     897                 :            :         &dev_attr_fnode_max_burst_len.attr,
     898                 :            :         &dev_attr_fnode_def_taskmgmt_tmo.attr,
     899                 :            :         &dev_attr_fnode_targetalias.attr,
     900                 :            :         &dev_attr_fnode_targetname.attr,
     901                 :            :         &dev_attr_fnode_tpgt.attr,
     902                 :            :         &dev_attr_fnode_discovery_parent_idx.attr,
     903                 :            :         &dev_attr_fnode_discovery_parent_type.attr,
     904                 :            :         &dev_attr_fnode_chap_in_idx.attr,
     905                 :            :         &dev_attr_fnode_chap_out_idx.attr,
     906                 :            :         &dev_attr_fnode_username.attr,
     907                 :            :         &dev_attr_fnode_username_in.attr,
     908                 :            :         &dev_attr_fnode_password.attr,
     909                 :            :         &dev_attr_fnode_password_in.attr,
     910                 :            :         &dev_attr_fnode_is_boot_target.attr,
     911                 :            :         NULL,
     912                 :            : };
     913                 :            : 
     914                 :          0 : static umode_t iscsi_flashnode_sess_attr_is_visible(struct kobject *kobj,
     915                 :            :                                                     struct attribute *attr,
     916                 :            :                                                     int i)
     917                 :            : {
     918                 :            :         struct device *dev = container_of(kobj, struct device, kobj);
     919                 :            :         struct iscsi_bus_flash_session *fnode_sess =
     920                 :            :                                                 iscsi_dev_to_flash_session(dev);
     921                 :          0 :         struct iscsi_transport *t = fnode_sess->transport;
     922                 :            :         int param;
     923                 :            : 
     924                 :          0 :         if (attr == &dev_attr_fnode_auto_snd_tgt_disable.attr) {
     925                 :            :                 param = ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE;
     926                 :          0 :         } else if (attr == &dev_attr_fnode_discovery_session.attr) {
     927                 :            :                 param = ISCSI_FLASHNODE_DISCOVERY_SESS;
     928                 :          0 :         } else if (attr == &dev_attr_fnode_portal_type.attr) {
     929                 :            :                 param = ISCSI_FLASHNODE_PORTAL_TYPE;
     930                 :          0 :         } else if (attr == &dev_attr_fnode_entry_enable.attr) {
     931                 :            :                 param = ISCSI_FLASHNODE_ENTRY_EN;
     932                 :          0 :         } else if (attr == &dev_attr_fnode_immediate_data.attr) {
     933                 :            :                 param = ISCSI_FLASHNODE_IMM_DATA_EN;
     934                 :          0 :         } else if (attr == &dev_attr_fnode_initial_r2t.attr) {
     935                 :            :                 param = ISCSI_FLASHNODE_INITIAL_R2T_EN;
     936                 :          0 :         } else if (attr == &dev_attr_fnode_data_seq_in_order.attr) {
     937                 :            :                 param = ISCSI_FLASHNODE_DATASEQ_INORDER;
     938                 :          0 :         } else if (attr == &dev_attr_fnode_data_pdu_in_order.attr) {
     939                 :            :                 param = ISCSI_FLASHNODE_PDU_INORDER;
     940                 :          0 :         } else if (attr == &dev_attr_fnode_chap_auth.attr) {
     941                 :            :                 param = ISCSI_FLASHNODE_CHAP_AUTH_EN;
     942                 :          0 :         } else if (attr == &dev_attr_fnode_discovery_logout.attr) {
     943                 :            :                 param = ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN;
     944                 :          0 :         } else if (attr == &dev_attr_fnode_bidi_chap.attr) {
     945                 :            :                 param = ISCSI_FLASHNODE_BIDI_CHAP_EN;
     946                 :          0 :         } else if (attr == &dev_attr_fnode_discovery_auth_optional.attr) {
     947                 :            :                 param = ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL;
     948                 :          0 :         } else if (attr == &dev_attr_fnode_erl.attr) {
     949                 :            :                 param = ISCSI_FLASHNODE_ERL;
     950                 :          0 :         } else if (attr == &dev_attr_fnode_first_burst_len.attr) {
     951                 :            :                 param = ISCSI_FLASHNODE_FIRST_BURST;
     952                 :          0 :         } else if (attr == &dev_attr_fnode_def_time2wait.attr) {
     953                 :            :                 param = ISCSI_FLASHNODE_DEF_TIME2WAIT;
     954                 :          0 :         } else if (attr == &dev_attr_fnode_def_time2retain.attr) {
     955                 :            :                 param = ISCSI_FLASHNODE_DEF_TIME2RETAIN;
     956                 :          0 :         } else if (attr == &dev_attr_fnode_max_outstanding_r2t.attr) {
     957                 :            :                 param = ISCSI_FLASHNODE_MAX_R2T;
     958                 :          0 :         } else if (attr == &dev_attr_fnode_isid.attr) {
     959                 :            :                 param = ISCSI_FLASHNODE_ISID;
     960                 :          0 :         } else if (attr == &dev_attr_fnode_tsid.attr) {
     961                 :            :                 param = ISCSI_FLASHNODE_TSID;
     962                 :          0 :         } else if (attr == &dev_attr_fnode_max_burst_len.attr) {
     963                 :            :                 param = ISCSI_FLASHNODE_MAX_BURST;
     964                 :          0 :         } else if (attr == &dev_attr_fnode_def_taskmgmt_tmo.attr) {
     965                 :            :                 param = ISCSI_FLASHNODE_DEF_TASKMGMT_TMO;
     966                 :          0 :         } else if (attr == &dev_attr_fnode_targetalias.attr) {
     967                 :            :                 param = ISCSI_FLASHNODE_ALIAS;
     968                 :          0 :         } else if (attr == &dev_attr_fnode_targetname.attr) {
     969                 :            :                 param = ISCSI_FLASHNODE_NAME;
     970                 :          0 :         } else if (attr == &dev_attr_fnode_tpgt.attr) {
     971                 :            :                 param = ISCSI_FLASHNODE_TPGT;
     972                 :          0 :         } else if (attr == &dev_attr_fnode_discovery_parent_idx.attr) {
     973                 :            :                 param = ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX;
     974                 :          0 :         } else if (attr == &dev_attr_fnode_discovery_parent_type.attr) {
     975                 :            :                 param = ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE;
     976                 :          0 :         } else if (attr == &dev_attr_fnode_chap_in_idx.attr) {
     977                 :            :                 param = ISCSI_FLASHNODE_CHAP_IN_IDX;
     978                 :          0 :         } else if (attr == &dev_attr_fnode_chap_out_idx.attr) {
     979                 :            :                 param = ISCSI_FLASHNODE_CHAP_OUT_IDX;
     980                 :          0 :         } else if (attr == &dev_attr_fnode_username.attr) {
     981                 :            :                 param = ISCSI_FLASHNODE_USERNAME;
     982                 :          0 :         } else if (attr == &dev_attr_fnode_username_in.attr) {
     983                 :            :                 param = ISCSI_FLASHNODE_USERNAME_IN;
     984                 :          0 :         } else if (attr == &dev_attr_fnode_password.attr) {
     985                 :            :                 param = ISCSI_FLASHNODE_PASSWORD;
     986                 :          0 :         } else if (attr == &dev_attr_fnode_password_in.attr) {
     987                 :            :                 param = ISCSI_FLASHNODE_PASSWORD_IN;
     988                 :          0 :         } else if (attr == &dev_attr_fnode_is_boot_target.attr) {
     989                 :            :                 param = ISCSI_FLASHNODE_IS_BOOT_TGT;
     990                 :            :         } else {
     991                 :          0 :                 WARN_ONCE(1, "Invalid flashnode session attr");
     992                 :            :                 return 0;
     993                 :            :         }
     994                 :            : 
     995                 :          0 :         return t->attr_is_visible(ISCSI_FLASHNODE_PARAM, param);
     996                 :            : }
     997                 :            : 
     998                 :            : static struct attribute_group iscsi_flashnode_sess_attr_group = {
     999                 :            :         .attrs = iscsi_flashnode_sess_attrs,
    1000                 :            :         .is_visible = iscsi_flashnode_sess_attr_is_visible,
    1001                 :            : };
    1002                 :            : 
    1003                 :            : static const struct attribute_group *iscsi_flashnode_sess_attr_groups[] = {
    1004                 :            :         &iscsi_flashnode_sess_attr_group,
    1005                 :            :         NULL,
    1006                 :            : };
    1007                 :            : 
    1008                 :          0 : static void iscsi_flashnode_sess_release(struct device *dev)
    1009                 :            : {
    1010                 :            :         struct iscsi_bus_flash_session *fnode_sess =
    1011                 :          0 :                                                 iscsi_dev_to_flash_session(dev);
    1012                 :            : 
    1013                 :          0 :         kfree(fnode_sess->targetname);
    1014                 :          0 :         kfree(fnode_sess->targetalias);
    1015                 :          0 :         kfree(fnode_sess->portal_type);
    1016                 :          0 :         kfree(fnode_sess);
    1017                 :          0 : }
    1018                 :            : 
    1019                 :            : static const struct device_type iscsi_flashnode_sess_dev_type = {
    1020                 :            :         .name = "iscsi_flashnode_sess_dev_type",
    1021                 :            :         .groups = iscsi_flashnode_sess_attr_groups,
    1022                 :            :         .release = iscsi_flashnode_sess_release,
    1023                 :            : };
    1024                 :            : 
    1025                 :            : /* flash node connection attrs show */
    1026                 :            : #define iscsi_flashnode_conn_attr_show(type, name, param)               \
    1027                 :            : static ssize_t                                                          \
    1028                 :            : show_##type##_##name(struct device *dev, struct device_attribute *attr, \
    1029                 :            :                      char *buf)                                         \
    1030                 :            : {                                                                       \
    1031                 :            :         struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);\
    1032                 :            :         struct iscsi_bus_flash_session *fnode_sess =                    \
    1033                 :            :                                 iscsi_flash_conn_to_flash_session(fnode_conn);\
    1034                 :            :         struct iscsi_transport *t = fnode_conn->transport;           \
    1035                 :            :         return t->get_flashnode_param(fnode_sess, param, buf);               \
    1036                 :            : }                                                                       \
    1037                 :            : 
    1038                 :            : 
    1039                 :            : #define iscsi_flashnode_conn_attr(type, name, param)                    \
    1040                 :            :         iscsi_flashnode_conn_attr_show(type, name, param)               \
    1041                 :            : static ISCSI_FLASHNODE_ATTR(type, name, S_IRUGO,                        \
    1042                 :            :                             show_##type##_##name, NULL);
    1043                 :            : 
    1044                 :            : /* Flash node connection attributes */
    1045                 :            : 
    1046                 :          0 : iscsi_flashnode_conn_attr(fnode, is_fw_assigned_ipv6,
    1047                 :            :                           ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6);
    1048                 :          0 : iscsi_flashnode_conn_attr(fnode, header_digest, ISCSI_FLASHNODE_HDR_DGST_EN);
    1049                 :          0 : iscsi_flashnode_conn_attr(fnode, data_digest, ISCSI_FLASHNODE_DATA_DGST_EN);
    1050                 :          0 : iscsi_flashnode_conn_attr(fnode, snack_req, ISCSI_FLASHNODE_SNACK_REQ_EN);
    1051                 :          0 : iscsi_flashnode_conn_attr(fnode, tcp_timestamp_stat,
    1052                 :            :                           ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT);
    1053                 :          0 : iscsi_flashnode_conn_attr(fnode, tcp_nagle_disable,
    1054                 :            :                           ISCSI_FLASHNODE_TCP_NAGLE_DISABLE);
    1055                 :          0 : iscsi_flashnode_conn_attr(fnode, tcp_wsf_disable,
    1056                 :            :                           ISCSI_FLASHNODE_TCP_WSF_DISABLE);
    1057                 :          0 : iscsi_flashnode_conn_attr(fnode, tcp_timer_scale,
    1058                 :            :                           ISCSI_FLASHNODE_TCP_TIMER_SCALE);
    1059                 :          0 : iscsi_flashnode_conn_attr(fnode, tcp_timestamp_enable,
    1060                 :            :                           ISCSI_FLASHNODE_TCP_TIMESTAMP_EN);
    1061                 :          0 : iscsi_flashnode_conn_attr(fnode, fragment_disable,
    1062                 :            :                           ISCSI_FLASHNODE_IP_FRAG_DISABLE);
    1063                 :          0 : iscsi_flashnode_conn_attr(fnode, keepalive_tmo, ISCSI_FLASHNODE_KEEPALIVE_TMO);
    1064                 :          0 : iscsi_flashnode_conn_attr(fnode, port, ISCSI_FLASHNODE_PORT);
    1065                 :          0 : iscsi_flashnode_conn_attr(fnode, ipaddress, ISCSI_FLASHNODE_IPADDR);
    1066                 :          0 : iscsi_flashnode_conn_attr(fnode, max_recv_dlength,
    1067                 :            :                           ISCSI_FLASHNODE_MAX_RECV_DLENGTH);
    1068                 :          0 : iscsi_flashnode_conn_attr(fnode, max_xmit_dlength,
    1069                 :            :                           ISCSI_FLASHNODE_MAX_XMIT_DLENGTH);
    1070                 :          0 : iscsi_flashnode_conn_attr(fnode, local_port, ISCSI_FLASHNODE_LOCAL_PORT);
    1071                 :          0 : iscsi_flashnode_conn_attr(fnode, ipv4_tos, ISCSI_FLASHNODE_IPV4_TOS);
    1072                 :          0 : iscsi_flashnode_conn_attr(fnode, ipv6_traffic_class, ISCSI_FLASHNODE_IPV6_TC);
    1073                 :          0 : iscsi_flashnode_conn_attr(fnode, ipv6_flow_label,
    1074                 :            :                           ISCSI_FLASHNODE_IPV6_FLOW_LABEL);
    1075                 :          0 : iscsi_flashnode_conn_attr(fnode, redirect_ipaddr,
    1076                 :            :                           ISCSI_FLASHNODE_REDIRECT_IPADDR);
    1077                 :          0 : iscsi_flashnode_conn_attr(fnode, max_segment_size,
    1078                 :            :                           ISCSI_FLASHNODE_MAX_SEGMENT_SIZE);
    1079                 :          0 : iscsi_flashnode_conn_attr(fnode, link_local_ipv6,
    1080                 :            :                           ISCSI_FLASHNODE_LINK_LOCAL_IPV6);
    1081                 :          0 : iscsi_flashnode_conn_attr(fnode, tcp_xmit_wsf, ISCSI_FLASHNODE_TCP_XMIT_WSF);
    1082                 :          0 : iscsi_flashnode_conn_attr(fnode, tcp_recv_wsf, ISCSI_FLASHNODE_TCP_RECV_WSF);
    1083                 :          0 : iscsi_flashnode_conn_attr(fnode, statsn, ISCSI_FLASHNODE_STATSN);
    1084                 :          0 : iscsi_flashnode_conn_attr(fnode, exp_statsn, ISCSI_FLASHNODE_EXP_STATSN);
    1085                 :            : 
    1086                 :            : static struct attribute *iscsi_flashnode_conn_attrs[] = {
    1087                 :            :         &dev_attr_fnode_is_fw_assigned_ipv6.attr,
    1088                 :            :         &dev_attr_fnode_header_digest.attr,
    1089                 :            :         &dev_attr_fnode_data_digest.attr,
    1090                 :            :         &dev_attr_fnode_snack_req.attr,
    1091                 :            :         &dev_attr_fnode_tcp_timestamp_stat.attr,
    1092                 :            :         &dev_attr_fnode_tcp_nagle_disable.attr,
    1093                 :            :         &dev_attr_fnode_tcp_wsf_disable.attr,
    1094                 :            :         &dev_attr_fnode_tcp_timer_scale.attr,
    1095                 :            :         &dev_attr_fnode_tcp_timestamp_enable.attr,
    1096                 :            :         &dev_attr_fnode_fragment_disable.attr,
    1097                 :            :         &dev_attr_fnode_max_recv_dlength.attr,
    1098                 :            :         &dev_attr_fnode_max_xmit_dlength.attr,
    1099                 :            :         &dev_attr_fnode_keepalive_tmo.attr,
    1100                 :            :         &dev_attr_fnode_port.attr,
    1101                 :            :         &dev_attr_fnode_ipaddress.attr,
    1102                 :            :         &dev_attr_fnode_redirect_ipaddr.attr,
    1103                 :            :         &dev_attr_fnode_max_segment_size.attr,
    1104                 :            :         &dev_attr_fnode_local_port.attr,
    1105                 :            :         &dev_attr_fnode_ipv4_tos.attr,
    1106                 :            :         &dev_attr_fnode_ipv6_traffic_class.attr,
    1107                 :            :         &dev_attr_fnode_ipv6_flow_label.attr,
    1108                 :            :         &dev_attr_fnode_link_local_ipv6.attr,
    1109                 :            :         &dev_attr_fnode_tcp_xmit_wsf.attr,
    1110                 :            :         &dev_attr_fnode_tcp_recv_wsf.attr,
    1111                 :            :         &dev_attr_fnode_statsn.attr,
    1112                 :            :         &dev_attr_fnode_exp_statsn.attr,
    1113                 :            :         NULL,
    1114                 :            : };
    1115                 :            : 
    1116                 :          0 : static umode_t iscsi_flashnode_conn_attr_is_visible(struct kobject *kobj,
    1117                 :            :                                                     struct attribute *attr,
    1118                 :            :                                                     int i)
    1119                 :            : {
    1120                 :            :         struct device *dev = container_of(kobj, struct device, kobj);
    1121                 :            :         struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);
    1122                 :          0 :         struct iscsi_transport *t = fnode_conn->transport;
    1123                 :            :         int param;
    1124                 :            : 
    1125                 :          0 :         if (attr == &dev_attr_fnode_is_fw_assigned_ipv6.attr) {
    1126                 :            :                 param = ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6;
    1127                 :          0 :         } else if (attr == &dev_attr_fnode_header_digest.attr) {
    1128                 :            :                 param = ISCSI_FLASHNODE_HDR_DGST_EN;
    1129                 :          0 :         } else if (attr == &dev_attr_fnode_data_digest.attr) {
    1130                 :            :                 param = ISCSI_FLASHNODE_DATA_DGST_EN;
    1131                 :          0 :         } else if (attr == &dev_attr_fnode_snack_req.attr) {
    1132                 :            :                 param = ISCSI_FLASHNODE_SNACK_REQ_EN;
    1133                 :          0 :         } else if (attr == &dev_attr_fnode_tcp_timestamp_stat.attr) {
    1134                 :            :                 param = ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT;
    1135                 :          0 :         } else if (attr == &dev_attr_fnode_tcp_nagle_disable.attr) {
    1136                 :            :                 param = ISCSI_FLASHNODE_TCP_NAGLE_DISABLE;
    1137                 :          0 :         } else if (attr == &dev_attr_fnode_tcp_wsf_disable.attr) {
    1138                 :            :                 param = ISCSI_FLASHNODE_TCP_WSF_DISABLE;
    1139                 :          0 :         } else if (attr == &dev_attr_fnode_tcp_timer_scale.attr) {
    1140                 :            :                 param = ISCSI_FLASHNODE_TCP_TIMER_SCALE;
    1141                 :          0 :         } else if (attr == &dev_attr_fnode_tcp_timestamp_enable.attr) {
    1142                 :            :                 param = ISCSI_FLASHNODE_TCP_TIMESTAMP_EN;
    1143                 :          0 :         } else if (attr == &dev_attr_fnode_fragment_disable.attr) {
    1144                 :            :                 param = ISCSI_FLASHNODE_IP_FRAG_DISABLE;
    1145                 :          0 :         } else if (attr == &dev_attr_fnode_max_recv_dlength.attr) {
    1146                 :            :                 param = ISCSI_FLASHNODE_MAX_RECV_DLENGTH;
    1147                 :          0 :         } else if (attr == &dev_attr_fnode_max_xmit_dlength.attr) {
    1148                 :            :                 param = ISCSI_FLASHNODE_MAX_XMIT_DLENGTH;
    1149                 :          0 :         } else if (attr == &dev_attr_fnode_keepalive_tmo.attr) {
    1150                 :            :                 param = ISCSI_FLASHNODE_KEEPALIVE_TMO;
    1151                 :          0 :         } else if (attr == &dev_attr_fnode_port.attr) {
    1152                 :            :                 param = ISCSI_FLASHNODE_PORT;
    1153                 :          0 :         } else if (attr == &dev_attr_fnode_ipaddress.attr) {
    1154                 :            :                 param = ISCSI_FLASHNODE_IPADDR;
    1155                 :          0 :         } else if (attr == &dev_attr_fnode_redirect_ipaddr.attr) {
    1156                 :            :                 param = ISCSI_FLASHNODE_REDIRECT_IPADDR;
    1157                 :          0 :         } else if (attr == &dev_attr_fnode_max_segment_size.attr) {
    1158                 :            :                 param = ISCSI_FLASHNODE_MAX_SEGMENT_SIZE;
    1159                 :          0 :         } else if (attr == &dev_attr_fnode_local_port.attr) {
    1160                 :            :                 param = ISCSI_FLASHNODE_LOCAL_PORT;
    1161                 :          0 :         } else if (attr == &dev_attr_fnode_ipv4_tos.attr) {
    1162                 :            :                 param = ISCSI_FLASHNODE_IPV4_TOS;
    1163                 :          0 :         } else if (attr == &dev_attr_fnode_ipv6_traffic_class.attr) {
    1164                 :            :                 param = ISCSI_FLASHNODE_IPV6_TC;
    1165                 :          0 :         } else if (attr == &dev_attr_fnode_ipv6_flow_label.attr) {
    1166                 :            :                 param = ISCSI_FLASHNODE_IPV6_FLOW_LABEL;
    1167                 :          0 :         } else if (attr == &dev_attr_fnode_link_local_ipv6.attr) {
    1168                 :            :                 param = ISCSI_FLASHNODE_LINK_LOCAL_IPV6;
    1169                 :          0 :         } else if (attr == &dev_attr_fnode_tcp_xmit_wsf.attr) {
    1170                 :            :                 param = ISCSI_FLASHNODE_TCP_XMIT_WSF;
    1171                 :          0 :         } else if (attr == &dev_attr_fnode_tcp_recv_wsf.attr) {
    1172                 :            :                 param = ISCSI_FLASHNODE_TCP_RECV_WSF;
    1173                 :          0 :         } else if (attr == &dev_attr_fnode_statsn.attr) {
    1174                 :            :                 param = ISCSI_FLASHNODE_STATSN;
    1175                 :          0 :         } else if (attr == &dev_attr_fnode_exp_statsn.attr) {
    1176                 :            :                 param = ISCSI_FLASHNODE_EXP_STATSN;
    1177                 :            :         } else {
    1178                 :          0 :                 WARN_ONCE(1, "Invalid flashnode connection attr");
    1179                 :            :                 return 0;
    1180                 :            :         }
    1181                 :            : 
    1182                 :          0 :         return t->attr_is_visible(ISCSI_FLASHNODE_PARAM, param);
    1183                 :            : }
    1184                 :            : 
    1185                 :            : static struct attribute_group iscsi_flashnode_conn_attr_group = {
    1186                 :            :         .attrs = iscsi_flashnode_conn_attrs,
    1187                 :            :         .is_visible = iscsi_flashnode_conn_attr_is_visible,
    1188                 :            : };
    1189                 :            : 
    1190                 :            : static const struct attribute_group *iscsi_flashnode_conn_attr_groups[] = {
    1191                 :            :         &iscsi_flashnode_conn_attr_group,
    1192                 :            :         NULL,
    1193                 :            : };
    1194                 :            : 
    1195                 :          0 : static void iscsi_flashnode_conn_release(struct device *dev)
    1196                 :            : {
    1197                 :          0 :         struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);
    1198                 :            : 
    1199                 :          0 :         kfree(fnode_conn->ipaddress);
    1200                 :          0 :         kfree(fnode_conn->redirect_ipaddr);
    1201                 :          0 :         kfree(fnode_conn->link_local_ipv6_addr);
    1202                 :          0 :         kfree(fnode_conn);
    1203                 :          0 : }
    1204                 :            : 
    1205                 :            : static const struct device_type iscsi_flashnode_conn_dev_type = {
    1206                 :            :         .name = "iscsi_flashnode_conn_dev_type",
    1207                 :            :         .groups = iscsi_flashnode_conn_attr_groups,
    1208                 :            :         .release = iscsi_flashnode_conn_release,
    1209                 :            : };
    1210                 :            : 
    1211                 :            : static struct bus_type iscsi_flashnode_bus;
    1212                 :            : 
    1213                 :          0 : int iscsi_flashnode_bus_match(struct device *dev,
    1214                 :            :                                      struct device_driver *drv)
    1215                 :            : {
    1216                 :          0 :         if (dev->bus == &iscsi_flashnode_bus)
    1217                 :            :                 return 1;
    1218                 :          0 :         return 0;
    1219                 :            : }
    1220                 :            : EXPORT_SYMBOL_GPL(iscsi_flashnode_bus_match);
    1221                 :            : 
    1222                 :            : static struct bus_type iscsi_flashnode_bus = {
    1223                 :            :         .name = "iscsi_flashnode",
    1224                 :            :         .match = &iscsi_flashnode_bus_match,
    1225                 :            : };
    1226                 :            : 
    1227                 :            : /**
    1228                 :            :  * iscsi_create_flashnode_sess - Add flashnode session entry in sysfs
    1229                 :            :  * @shost: pointer to host data
    1230                 :            :  * @index: index of flashnode to add in sysfs
    1231                 :            :  * @transport: pointer to transport data
    1232                 :            :  * @dd_size: total size to allocate
    1233                 :            :  *
    1234                 :            :  * Adds a sysfs entry for the flashnode session attributes
    1235                 :            :  *
    1236                 :            :  * Returns:
    1237                 :            :  *  pointer to allocated flashnode sess on success
    1238                 :            :  *  %NULL on failure
    1239                 :            :  */
    1240                 :            : struct iscsi_bus_flash_session *
    1241                 :          0 : iscsi_create_flashnode_sess(struct Scsi_Host *shost, int index,
    1242                 :            :                             struct iscsi_transport *transport,
    1243                 :            :                             int dd_size)
    1244                 :            : {
    1245                 :            :         struct iscsi_bus_flash_session *fnode_sess;
    1246                 :            :         int err;
    1247                 :            : 
    1248                 :          0 :         fnode_sess = kzalloc(sizeof(*fnode_sess) + dd_size, GFP_KERNEL);
    1249                 :          0 :         if (!fnode_sess)
    1250                 :            :                 return NULL;
    1251                 :            : 
    1252                 :          0 :         fnode_sess->transport = transport;
    1253                 :          0 :         fnode_sess->target_id = index;
    1254                 :          0 :         fnode_sess->dev.type = &iscsi_flashnode_sess_dev_type;
    1255                 :          0 :         fnode_sess->dev.bus = &iscsi_flashnode_bus;
    1256                 :          0 :         fnode_sess->dev.parent = &shost->shost_gendev;
    1257                 :          0 :         dev_set_name(&fnode_sess->dev, "flashnode_sess-%u:%u",
    1258                 :            :                      shost->host_no, index);
    1259                 :            : 
    1260                 :          0 :         err = device_register(&fnode_sess->dev);
    1261                 :          0 :         if (err)
    1262                 :            :                 goto free_fnode_sess;
    1263                 :            : 
    1264                 :          0 :         if (dd_size)
    1265                 :          0 :                 fnode_sess->dd_data = &fnode_sess[1];
    1266                 :            : 
    1267                 :          0 :         return fnode_sess;
    1268                 :            : 
    1269                 :            : free_fnode_sess:
    1270                 :          0 :         kfree(fnode_sess);
    1271                 :          0 :         return NULL;
    1272                 :            : }
    1273                 :            : EXPORT_SYMBOL_GPL(iscsi_create_flashnode_sess);
    1274                 :            : 
    1275                 :            : /**
    1276                 :            :  * iscsi_create_flashnode_conn - Add flashnode conn entry in sysfs
    1277                 :            :  * @shost: pointer to host data
    1278                 :            :  * @fnode_sess: pointer to the parent flashnode session entry
    1279                 :            :  * @transport: pointer to transport data
    1280                 :            :  * @dd_size: total size to allocate
    1281                 :            :  *
    1282                 :            :  * Adds a sysfs entry for the flashnode connection attributes
    1283                 :            :  *
    1284                 :            :  * Returns:
    1285                 :            :  *  pointer to allocated flashnode conn on success
    1286                 :            :  *  %NULL on failure
    1287                 :            :  */
    1288                 :            : struct iscsi_bus_flash_conn *
    1289                 :          0 : iscsi_create_flashnode_conn(struct Scsi_Host *shost,
    1290                 :            :                             struct iscsi_bus_flash_session *fnode_sess,
    1291                 :            :                             struct iscsi_transport *transport,
    1292                 :            :                             int dd_size)
    1293                 :            : {
    1294                 :            :         struct iscsi_bus_flash_conn *fnode_conn;
    1295                 :            :         int err;
    1296                 :            : 
    1297                 :          0 :         fnode_conn = kzalloc(sizeof(*fnode_conn) + dd_size, GFP_KERNEL);
    1298                 :          0 :         if (!fnode_conn)
    1299                 :            :                 return NULL;
    1300                 :            : 
    1301                 :          0 :         fnode_conn->transport = transport;
    1302                 :          0 :         fnode_conn->dev.type = &iscsi_flashnode_conn_dev_type;
    1303                 :          0 :         fnode_conn->dev.bus = &iscsi_flashnode_bus;
    1304                 :          0 :         fnode_conn->dev.parent = &fnode_sess->dev;
    1305                 :          0 :         dev_set_name(&fnode_conn->dev, "flashnode_conn-%u:%u:0",
    1306                 :            :                      shost->host_no, fnode_sess->target_id);
    1307                 :            : 
    1308                 :          0 :         err = device_register(&fnode_conn->dev);
    1309                 :          0 :         if (err)
    1310                 :            :                 goto free_fnode_conn;
    1311                 :            : 
    1312                 :          0 :         if (dd_size)
    1313                 :          0 :                 fnode_conn->dd_data = &fnode_conn[1];
    1314                 :            : 
    1315                 :          0 :         return fnode_conn;
    1316                 :            : 
    1317                 :            : free_fnode_conn:
    1318                 :          0 :         kfree(fnode_conn);
    1319                 :          0 :         return NULL;
    1320                 :            : }
    1321                 :            : EXPORT_SYMBOL_GPL(iscsi_create_flashnode_conn);
    1322                 :            : 
    1323                 :            : /**
    1324                 :            :  * iscsi_is_flashnode_conn_dev - verify passed device is to be flashnode conn
    1325                 :            :  * @dev: device to verify
    1326                 :            :  * @data: pointer to data containing value to use for verification
    1327                 :            :  *
    1328                 :            :  * Verifies if the passed device is flashnode conn device
    1329                 :            :  *
    1330                 :            :  * Returns:
    1331                 :            :  *  1 on success
    1332                 :            :  *  0 on failure
    1333                 :            :  */
    1334                 :          0 : static int iscsi_is_flashnode_conn_dev(struct device *dev, void *data)
    1335                 :            : {
    1336                 :          0 :         return dev->bus == &iscsi_flashnode_bus;
    1337                 :            : }
    1338                 :            : 
    1339                 :            : static int iscsi_destroy_flashnode_conn(struct iscsi_bus_flash_conn *fnode_conn)
    1340                 :            : {
    1341                 :          0 :         device_unregister(&fnode_conn->dev);
    1342                 :            :         return 0;
    1343                 :            : }
    1344                 :            : 
    1345                 :          0 : static int flashnode_match_index(struct device *dev, void *data)
    1346                 :            : {
    1347                 :            :         struct iscsi_bus_flash_session *fnode_sess = NULL;
    1348                 :            :         int ret = 0;
    1349                 :            : 
    1350                 :          0 :         if (!iscsi_flashnode_bus_match(dev, NULL))
    1351                 :            :                 goto exit_match_index;
    1352                 :            : 
    1353                 :            :         fnode_sess = iscsi_dev_to_flash_session(dev);
    1354                 :          0 :         ret = (fnode_sess->target_id == *((int *)data)) ? 1 : 0;
    1355                 :            : 
    1356                 :            : exit_match_index:
    1357                 :          0 :         return ret;
    1358                 :            : }
    1359                 :            : 
    1360                 :            : /**
    1361                 :            :  * iscsi_get_flashnode_by_index -finds flashnode session entry by index
    1362                 :            :  * @shost: pointer to host data
    1363                 :            :  * @idx: index to match
    1364                 :            :  *
    1365                 :            :  * Finds the flashnode session object for the passed index
    1366                 :            :  *
    1367                 :            :  * Returns:
    1368                 :            :  *  pointer to found flashnode session object on success
    1369                 :            :  *  %NULL on failure
    1370                 :            :  */
    1371                 :            : static struct iscsi_bus_flash_session *
    1372                 :            : iscsi_get_flashnode_by_index(struct Scsi_Host *shost, uint32_t idx)
    1373                 :            : {
    1374                 :            :         struct iscsi_bus_flash_session *fnode_sess = NULL;
    1375                 :            :         struct device *dev;
    1376                 :            : 
    1377                 :          0 :         dev = device_find_child(&shost->shost_gendev, &idx,
    1378                 :            :                                 flashnode_match_index);
    1379                 :          0 :         if (dev)
    1380                 :          0 :                 fnode_sess = iscsi_dev_to_flash_session(dev);
    1381                 :            : 
    1382                 :            :         return fnode_sess;
    1383                 :            : }
    1384                 :            : 
    1385                 :            : /**
    1386                 :            :  * iscsi_find_flashnode_sess - finds flashnode session entry
    1387                 :            :  * @shost: pointer to host data
    1388                 :            :  * @data: pointer to data containing value to use for comparison
    1389                 :            :  * @fn: function pointer that does actual comparison
    1390                 :            :  *
    1391                 :            :  * Finds the flashnode session object comparing the data passed using logic
    1392                 :            :  * defined in passed function pointer
    1393                 :            :  *
    1394                 :            :  * Returns:
    1395                 :            :  *  pointer to found flashnode session device object on success
    1396                 :            :  *  %NULL on failure
    1397                 :            :  */
    1398                 :            : struct device *
    1399                 :          0 : iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
    1400                 :            :                           int (*fn)(struct device *dev, void *data))
    1401                 :            : {
    1402                 :          0 :         return device_find_child(&shost->shost_gendev, data, fn);
    1403                 :            : }
    1404                 :            : EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
    1405                 :            : 
    1406                 :            : /**
    1407                 :            :  * iscsi_find_flashnode_conn - finds flashnode connection entry
    1408                 :            :  * @fnode_sess: pointer to parent flashnode session entry
    1409                 :            :  *
    1410                 :            :  * Finds the flashnode connection object comparing the data passed using logic
    1411                 :            :  * defined in passed function pointer
    1412                 :            :  *
    1413                 :            :  * Returns:
    1414                 :            :  *  pointer to found flashnode connection device object on success
    1415                 :            :  *  %NULL on failure
    1416                 :            :  */
    1417                 :            : struct device *
    1418                 :          0 : iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess)
    1419                 :            : {
    1420                 :          0 :         return device_find_child(&fnode_sess->dev, NULL,
    1421                 :            :                                  iscsi_is_flashnode_conn_dev);
    1422                 :            : }
    1423                 :            : EXPORT_SYMBOL_GPL(iscsi_find_flashnode_conn);
    1424                 :            : 
    1425                 :          0 : static int iscsi_iter_destroy_flashnode_conn_fn(struct device *dev, void *data)
    1426                 :            : {
    1427                 :          0 :         if (!iscsi_is_flashnode_conn_dev(dev, NULL))
    1428                 :            :                 return 0;
    1429                 :            : 
    1430                 :          0 :         return iscsi_destroy_flashnode_conn(iscsi_dev_to_flash_conn(dev));
    1431                 :            : }
    1432                 :            : 
    1433                 :            : /**
    1434                 :            :  * iscsi_destroy_flashnode_sess - destroy flashnode session entry
    1435                 :            :  * @fnode_sess: pointer to flashnode session entry to be destroyed
    1436                 :            :  *
    1437                 :            :  * Deletes the flashnode session entry and all children flashnode connection
    1438                 :            :  * entries from sysfs
    1439                 :            :  */
    1440                 :          0 : void iscsi_destroy_flashnode_sess(struct iscsi_bus_flash_session *fnode_sess)
    1441                 :            : {
    1442                 :            :         int err;
    1443                 :            : 
    1444                 :          0 :         err = device_for_each_child(&fnode_sess->dev, NULL,
    1445                 :            :                                     iscsi_iter_destroy_flashnode_conn_fn);
    1446                 :          0 :         if (err)
    1447                 :          0 :                 pr_err("Could not delete all connections for %s. Error %d.\n",
    1448                 :            :                        fnode_sess->dev.kobj.name, err);
    1449                 :            : 
    1450                 :          0 :         device_unregister(&fnode_sess->dev);
    1451                 :          0 : }
    1452                 :            : EXPORT_SYMBOL_GPL(iscsi_destroy_flashnode_sess);
    1453                 :            : 
    1454                 :          0 : static int iscsi_iter_destroy_flashnode_fn(struct device *dev, void *data)
    1455                 :            : {
    1456                 :          0 :         if (!iscsi_flashnode_bus_match(dev, NULL))
    1457                 :            :                 return 0;
    1458                 :            : 
    1459                 :          0 :         iscsi_destroy_flashnode_sess(iscsi_dev_to_flash_session(dev));
    1460                 :          0 :         return 0;
    1461                 :            : }
    1462                 :            : 
    1463                 :            : /**
    1464                 :            :  * iscsi_destroy_all_flashnode - destroy all flashnode session entries
    1465                 :            :  * @shost: pointer to host data
    1466                 :            :  *
    1467                 :            :  * Destroys all the flashnode session entries and all corresponding children
    1468                 :            :  * flashnode connection entries from sysfs
    1469                 :            :  */
    1470                 :          0 : void iscsi_destroy_all_flashnode(struct Scsi_Host *shost)
    1471                 :            : {
    1472                 :          0 :         device_for_each_child(&shost->shost_gendev, NULL,
    1473                 :            :                               iscsi_iter_destroy_flashnode_fn);
    1474                 :          0 : }
    1475                 :            : EXPORT_SYMBOL_GPL(iscsi_destroy_all_flashnode);
    1476                 :            : 
    1477                 :            : /*
    1478                 :            :  * BSG support
    1479                 :            :  */
    1480                 :            : /**
    1481                 :            :  * iscsi_bsg_host_dispatch - Dispatch command to LLD.
    1482                 :            :  * @job: bsg job to be processed
    1483                 :            :  */
    1484                 :          0 : static int iscsi_bsg_host_dispatch(struct bsg_job *job)
    1485                 :            : {
    1486                 :          0 :         struct Scsi_Host *shost = iscsi_job_to_shost(job);
    1487                 :          0 :         struct iscsi_bsg_request *req = job->request;
    1488                 :          0 :         struct iscsi_bsg_reply *reply = job->reply;
    1489                 :          0 :         struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
    1490                 :            :         int cmdlen = sizeof(uint32_t);  /* start with length of msgcode */
    1491                 :            :         int ret;
    1492                 :            : 
    1493                 :            :         /* check if we have the msgcode value at least */
    1494                 :          0 :         if (job->request_len < sizeof(uint32_t)) {
    1495                 :            :                 ret = -ENOMSG;
    1496                 :            :                 goto fail_host_msg;
    1497                 :            :         }
    1498                 :            : 
    1499                 :            :         /* Validate the host command */
    1500                 :          0 :         switch (req->msgcode) {
    1501                 :            :         case ISCSI_BSG_HST_VENDOR:
    1502                 :            :                 cmdlen += sizeof(struct iscsi_bsg_host_vendor);
    1503                 :          0 :                 if ((shost->hostt->vendor_id == 0L) ||
    1504                 :          0 :                     (req->rqst_data.h_vendor.vendor_id !=
    1505                 :            :                         shost->hostt->vendor_id)) {
    1506                 :            :                         ret = -ESRCH;
    1507                 :            :                         goto fail_host_msg;
    1508                 :            :                 }
    1509                 :            :                 break;
    1510                 :            :         default:
    1511                 :            :                 ret = -EBADR;
    1512                 :            :                 goto fail_host_msg;
    1513                 :            :         }
    1514                 :            : 
    1515                 :            :         /* check if we really have all the request data needed */
    1516                 :          0 :         if (job->request_len < cmdlen) {
    1517                 :            :                 ret = -ENOMSG;
    1518                 :            :                 goto fail_host_msg;
    1519                 :            :         }
    1520                 :            : 
    1521                 :          0 :         ret = i->iscsi_transport->bsg_request(job);
    1522                 :          0 :         if (!ret)
    1523                 :            :                 return 0;
    1524                 :            : 
    1525                 :            : fail_host_msg:
    1526                 :            :         /* return the errno failure code as the only status */
    1527                 :          0 :         BUG_ON(job->reply_len < sizeof(uint32_t));
    1528                 :          0 :         reply->reply_payload_rcv_len = 0;
    1529                 :          0 :         reply->result = ret;
    1530                 :          0 :         job->reply_len = sizeof(uint32_t);
    1531                 :          0 :         bsg_job_done(job, ret, 0);
    1532                 :          0 :         return 0;
    1533                 :            : }
    1534                 :            : 
    1535                 :            : /**
    1536                 :            :  * iscsi_bsg_host_add - Create and add the bsg hooks to receive requests
    1537                 :            :  * @shost: shost for iscsi_host
    1538                 :            :  * @ihost: iscsi_cls_host adding the structures to
    1539                 :            :  */
    1540                 :            : static int
    1541                 :          0 : iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
    1542                 :            : {
    1543                 :          0 :         struct device *dev = &shost->shost_gendev;
    1544                 :          0 :         struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
    1545                 :            :         struct request_queue *q;
    1546                 :            :         char bsg_name[20];
    1547                 :            : 
    1548                 :          0 :         if (!i->iscsi_transport->bsg_request)
    1549                 :            :                 return -ENOTSUPP;
    1550                 :            : 
    1551                 :          0 :         snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
    1552                 :          0 :         q = bsg_setup_queue(dev, bsg_name, iscsi_bsg_host_dispatch, NULL, 0);
    1553                 :          0 :         if (IS_ERR(q)) {
    1554                 :          0 :                 shost_printk(KERN_ERR, shost, "bsg interface failed to "
    1555                 :            :                              "initialize - no request queue\n");
    1556                 :          0 :                 return PTR_ERR(q);
    1557                 :            :         }
    1558                 :          0 :         __scsi_init_queue(shost, q);
    1559                 :            : 
    1560                 :          0 :         ihost->bsg_q = q;
    1561                 :          0 :         return 0;
    1562                 :            : }
    1563                 :            : 
    1564                 :          0 : static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
    1565                 :            :                             struct device *cdev)
    1566                 :            : {
    1567                 :          0 :         struct Scsi_Host *shost = dev_to_shost(dev);
    1568                 :          0 :         struct iscsi_cls_host *ihost = shost->shost_data;
    1569                 :            : 
    1570                 :          0 :         memset(ihost, 0, sizeof(*ihost));
    1571                 :            :         atomic_set(&ihost->nr_scans, 0);
    1572                 :          0 :         mutex_init(&ihost->mutex);
    1573                 :            : 
    1574                 :          0 :         iscsi_bsg_host_add(shost, ihost);
    1575                 :            :         /* ignore any bsg add error - we just can't do sgio */
    1576                 :            : 
    1577                 :          0 :         return 0;
    1578                 :            : }
    1579                 :            : 
    1580                 :          0 : static int iscsi_remove_host(struct transport_container *tc,
    1581                 :            :                              struct device *dev, struct device *cdev)
    1582                 :            : {
    1583                 :          0 :         struct Scsi_Host *shost = dev_to_shost(dev);
    1584                 :          0 :         struct iscsi_cls_host *ihost = shost->shost_data;
    1585                 :            : 
    1586                 :          0 :         bsg_remove_queue(ihost->bsg_q);
    1587                 :          0 :         return 0;
    1588                 :            : }
    1589                 :            : 
    1590                 :            : static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
    1591                 :            :                                "iscsi_host",
    1592                 :            :                                iscsi_setup_host,
    1593                 :            :                                iscsi_remove_host,
    1594                 :            :                                NULL);
    1595                 :            : 
    1596                 :            : static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
    1597                 :            :                                "iscsi_session",
    1598                 :            :                                NULL,
    1599                 :            :                                NULL,
    1600                 :            :                                NULL);
    1601                 :            : 
    1602                 :            : static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
    1603                 :            :                                "iscsi_connection",
    1604                 :            :                                NULL,
    1605                 :            :                                NULL,
    1606                 :            :                                NULL);
    1607                 :            : 
    1608                 :            : static struct sock *nls;
    1609                 :            : static DEFINE_MUTEX(rx_queue_mutex);
    1610                 :            : 
    1611                 :            : static LIST_HEAD(sesslist);
    1612                 :            : static DEFINE_SPINLOCK(sesslock);
    1613                 :            : static LIST_HEAD(connlist);
    1614                 :            : static DEFINE_SPINLOCK(connlock);
    1615                 :            : 
    1616                 :            : static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
    1617                 :            : {
    1618                 :          0 :         struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent);
    1619                 :          0 :         return sess->sid;
    1620                 :            : }
    1621                 :            : 
    1622                 :            : /*
    1623                 :            :  * Returns the matching session to a given sid
    1624                 :            :  */
    1625                 :          0 : static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid)
    1626                 :            : {
    1627                 :            :         unsigned long flags;
    1628                 :            :         struct iscsi_cls_session *sess;
    1629                 :            : 
    1630                 :          0 :         spin_lock_irqsave(&sesslock, flags);
    1631                 :          0 :         list_for_each_entry(sess, &sesslist, sess_list) {
    1632                 :          0 :                 if (sess->sid == sid) {
    1633                 :            :                         spin_unlock_irqrestore(&sesslock, flags);
    1634                 :          0 :                         return sess;
    1635                 :            :                 }
    1636                 :            :         }
    1637                 :            :         spin_unlock_irqrestore(&sesslock, flags);
    1638                 :          0 :         return NULL;
    1639                 :            : }
    1640                 :            : 
    1641                 :            : /*
    1642                 :            :  * Returns the matching connection to a given sid / cid tuple
    1643                 :            :  */
    1644                 :          0 : static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
    1645                 :            : {
    1646                 :            :         unsigned long flags;
    1647                 :            :         struct iscsi_cls_conn *conn;
    1648                 :            : 
    1649                 :          0 :         spin_lock_irqsave(&connlock, flags);
    1650                 :          0 :         list_for_each_entry(conn, &connlist, conn_list) {
    1651                 :          0 :                 if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
    1652                 :            :                         spin_unlock_irqrestore(&connlock, flags);
    1653                 :          0 :                         return conn;
    1654                 :            :                 }
    1655                 :            :         }
    1656                 :            :         spin_unlock_irqrestore(&connlock, flags);
    1657                 :          0 :         return NULL;
    1658                 :            : }
    1659                 :            : 
    1660                 :            : /*
    1661                 :            :  * The following functions can be used by LLDs that allocate
    1662                 :            :  * their own scsi_hosts or by software iscsi LLDs
    1663                 :            :  */
    1664                 :            : static struct {
    1665                 :            :         int value;
    1666                 :            :         char *name;
    1667                 :            : } iscsi_session_state_names[] = {
    1668                 :            :         { ISCSI_SESSION_LOGGED_IN,      "LOGGED_IN" },
    1669                 :            :         { ISCSI_SESSION_FAILED,         "FAILED" },
    1670                 :            :         { ISCSI_SESSION_FREE,           "FREE" },
    1671                 :            : };
    1672                 :            : 
    1673                 :            : static const char *iscsi_session_state_name(int state)
    1674                 :            : {
    1675                 :            :         int i;
    1676                 :            :         char *name = NULL;
    1677                 :            : 
    1678                 :          0 :         for (i = 0; i < ARRAY_SIZE(iscsi_session_state_names); i++) {
    1679                 :          0 :                 if (iscsi_session_state_names[i].value == state) {
    1680                 :          0 :                         name = iscsi_session_state_names[i].name;
    1681                 :            :                         break;
    1682                 :            :                 }
    1683                 :            :         }
    1684                 :            :         return name;
    1685                 :            : }
    1686                 :            : 
    1687                 :          0 : int iscsi_session_chkready(struct iscsi_cls_session *session)
    1688                 :            : {
    1689                 :            :         unsigned long flags;
    1690                 :            :         int err;
    1691                 :            : 
    1692                 :          0 :         spin_lock_irqsave(&session->lock, flags);
    1693                 :          0 :         switch (session->state) {
    1694                 :            :         case ISCSI_SESSION_LOGGED_IN:
    1695                 :            :                 err = 0;
    1696                 :            :                 break;
    1697                 :            :         case ISCSI_SESSION_FAILED:
    1698                 :            :                 err = DID_IMM_RETRY << 16;
    1699                 :            :                 break;
    1700                 :            :         case ISCSI_SESSION_FREE:
    1701                 :            :                 err = DID_TRANSPORT_FAILFAST << 16;
    1702                 :            :                 break;
    1703                 :            :         default:
    1704                 :            :                 err = DID_NO_CONNECT << 16;
    1705                 :            :                 break;
    1706                 :            :         }
    1707                 :            :         spin_unlock_irqrestore(&session->lock, flags);
    1708                 :          0 :         return err;
    1709                 :            : }
    1710                 :            : EXPORT_SYMBOL_GPL(iscsi_session_chkready);
    1711                 :            : 
    1712                 :          0 : int iscsi_is_session_online(struct iscsi_cls_session *session)
    1713                 :            : {
    1714                 :            :         unsigned long flags;
    1715                 :            :         int ret = 0;
    1716                 :            : 
    1717                 :          0 :         spin_lock_irqsave(&session->lock, flags);
    1718                 :          0 :         if (session->state == ISCSI_SESSION_LOGGED_IN)
    1719                 :            :                 ret = 1;
    1720                 :            :         spin_unlock_irqrestore(&session->lock, flags);
    1721                 :          0 :         return ret;
    1722                 :            : }
    1723                 :            : EXPORT_SYMBOL_GPL(iscsi_is_session_online);
    1724                 :            : 
    1725                 :          0 : static void iscsi_session_release(struct device *dev)
    1726                 :            : {
    1727                 :          0 :         struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
    1728                 :            :         struct Scsi_Host *shost;
    1729                 :            : 
    1730                 :          0 :         shost = iscsi_session_to_shost(session);
    1731                 :          0 :         scsi_host_put(shost);
    1732                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Completing session release\n");
    1733                 :          0 :         kfree(session);
    1734                 :          0 : }
    1735                 :            : 
    1736                 :          0 : int iscsi_is_session_dev(const struct device *dev)
    1737                 :            : {
    1738                 :          0 :         return dev->release == iscsi_session_release;
    1739                 :            : }
    1740                 :            : EXPORT_SYMBOL_GPL(iscsi_is_session_dev);
    1741                 :            : 
    1742                 :          0 : static int iscsi_iter_session_fn(struct device *dev, void *data)
    1743                 :            : {
    1744                 :          0 :         void (* fn) (struct iscsi_cls_session *) = data;
    1745                 :            : 
    1746                 :          0 :         if (!iscsi_is_session_dev(dev))
    1747                 :            :                 return 0;
    1748                 :          0 :         fn(iscsi_dev_to_session(dev));
    1749                 :          0 :         return 0;
    1750                 :            : }
    1751                 :            : 
    1752                 :          0 : void iscsi_host_for_each_session(struct Scsi_Host *shost,
    1753                 :            :                                  void (*fn)(struct iscsi_cls_session *))
    1754                 :            : {
    1755                 :          0 :         device_for_each_child(&shost->shost_gendev, fn,
    1756                 :            :                               iscsi_iter_session_fn);
    1757                 :          0 : }
    1758                 :            : EXPORT_SYMBOL_GPL(iscsi_host_for_each_session);
    1759                 :            : 
    1760                 :            : /**
    1761                 :            :  * iscsi_scan_finished - helper to report when running scans are done
    1762                 :            :  * @shost: scsi host
    1763                 :            :  * @time: scan run time
    1764                 :            :  *
    1765                 :            :  * This function can be used by drives like qla4xxx to report to the scsi
    1766                 :            :  * layer when the scans it kicked off at module load time are done.
    1767                 :            :  */
    1768                 :          0 : int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
    1769                 :            : {
    1770                 :          0 :         struct iscsi_cls_host *ihost = shost->shost_data;
    1771                 :            :         /*
    1772                 :            :          * qla4xxx will have kicked off some session unblocks before calling
    1773                 :            :          * scsi_scan_host, so just wait for them to complete.
    1774                 :            :          */
    1775                 :          0 :         return !atomic_read(&ihost->nr_scans);
    1776                 :            : }
    1777                 :            : EXPORT_SYMBOL_GPL(iscsi_scan_finished);
    1778                 :            : 
    1779                 :            : struct iscsi_scan_data {
    1780                 :            :         unsigned int channel;
    1781                 :            :         unsigned int id;
    1782                 :            :         u64 lun;
    1783                 :            :         enum scsi_scan_mode rescan;
    1784                 :            : };
    1785                 :            : 
    1786                 :          0 : static int iscsi_user_scan_session(struct device *dev, void *data)
    1787                 :            : {
    1788                 :            :         struct iscsi_scan_data *scan_data = data;
    1789                 :            :         struct iscsi_cls_session *session;
    1790                 :            :         struct Scsi_Host *shost;
    1791                 :            :         struct iscsi_cls_host *ihost;
    1792                 :            :         unsigned long flags;
    1793                 :            :         unsigned int id;
    1794                 :            : 
    1795                 :          0 :         if (!iscsi_is_session_dev(dev))
    1796                 :            :                 return 0;
    1797                 :            : 
    1798                 :            :         session = iscsi_dev_to_session(dev);
    1799                 :            : 
    1800                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Scanning session\n");
    1801                 :            : 
    1802                 :          0 :         shost = iscsi_session_to_shost(session);
    1803                 :          0 :         ihost = shost->shost_data;
    1804                 :            : 
    1805                 :          0 :         mutex_lock(&ihost->mutex);
    1806                 :          0 :         spin_lock_irqsave(&session->lock, flags);
    1807                 :          0 :         if (session->state != ISCSI_SESSION_LOGGED_IN) {
    1808                 :            :                 spin_unlock_irqrestore(&session->lock, flags);
    1809                 :            :                 goto user_scan_exit;
    1810                 :            :         }
    1811                 :          0 :         id = session->target_id;
    1812                 :            :         spin_unlock_irqrestore(&session->lock, flags);
    1813                 :            : 
    1814                 :          0 :         if (id != ISCSI_MAX_TARGET) {
    1815                 :          0 :                 if ((scan_data->channel == SCAN_WILD_CARD ||
    1816                 :          0 :                      scan_data->channel == 0) &&
    1817                 :          0 :                     (scan_data->id == SCAN_WILD_CARD ||
    1818                 :            :                      scan_data->id == id))
    1819                 :          0 :                         scsi_scan_target(&session->dev, 0, id,
    1820                 :            :                                          scan_data->lun, scan_data->rescan);
    1821                 :            :         }
    1822                 :            : 
    1823                 :            : user_scan_exit:
    1824                 :          0 :         mutex_unlock(&ihost->mutex);
    1825                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Completed session scan\n");
    1826                 :          0 :         return 0;
    1827                 :            : }
    1828                 :            : 
    1829                 :          0 : static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
    1830                 :            :                            uint id, u64 lun)
    1831                 :            : {
    1832                 :            :         struct iscsi_scan_data scan_data;
    1833                 :            : 
    1834                 :          0 :         scan_data.channel = channel;
    1835                 :          0 :         scan_data.id = id;
    1836                 :          0 :         scan_data.lun = lun;
    1837                 :          0 :         scan_data.rescan = SCSI_SCAN_MANUAL;
    1838                 :            : 
    1839                 :          0 :         return device_for_each_child(&shost->shost_gendev, &scan_data,
    1840                 :            :                                      iscsi_user_scan_session);
    1841                 :            : }
    1842                 :            : 
    1843                 :          0 : static void iscsi_scan_session(struct work_struct *work)
    1844                 :            : {
    1845                 :            :         struct iscsi_cls_session *session =
    1846                 :            :                         container_of(work, struct iscsi_cls_session, scan_work);
    1847                 :          0 :         struct Scsi_Host *shost = iscsi_session_to_shost(session);
    1848                 :          0 :         struct iscsi_cls_host *ihost = shost->shost_data;
    1849                 :            :         struct iscsi_scan_data scan_data;
    1850                 :            : 
    1851                 :          0 :         scan_data.channel = 0;
    1852                 :          0 :         scan_data.id = SCAN_WILD_CARD;
    1853                 :          0 :         scan_data.lun = SCAN_WILD_CARD;
    1854                 :          0 :         scan_data.rescan = SCSI_SCAN_RESCAN;
    1855                 :            : 
    1856                 :          0 :         iscsi_user_scan_session(&session->dev, &scan_data);
    1857                 :          0 :         atomic_dec(&ihost->nr_scans);
    1858                 :          0 : }
    1859                 :            : 
    1860                 :            : /**
    1861                 :            :  * iscsi_block_scsi_eh - block scsi eh until session state has transistioned
    1862                 :            :  * @cmd: scsi cmd passed to scsi eh handler
    1863                 :            :  *
    1864                 :            :  * If the session is down this function will wait for the recovery
    1865                 :            :  * timer to fire or for the session to be logged back in. If the
    1866                 :            :  * recovery timer fires then FAST_IO_FAIL is returned. The caller
    1867                 :            :  * should pass this error value to the scsi eh.
    1868                 :            :  */
    1869                 :          0 : int iscsi_block_scsi_eh(struct scsi_cmnd *cmd)
    1870                 :            : {
    1871                 :            :         struct iscsi_cls_session *session =
    1872                 :          0 :                         starget_to_session(scsi_target(cmd->device));
    1873                 :            :         unsigned long flags;
    1874                 :            :         int ret = 0;
    1875                 :            : 
    1876                 :          0 :         spin_lock_irqsave(&session->lock, flags);
    1877                 :          0 :         while (session->state != ISCSI_SESSION_LOGGED_IN) {
    1878                 :          0 :                 if (session->state == ISCSI_SESSION_FREE) {
    1879                 :            :                         ret = FAST_IO_FAIL;
    1880                 :            :                         break;
    1881                 :            :                 }
    1882                 :            :                 spin_unlock_irqrestore(&session->lock, flags);
    1883                 :          0 :                 msleep(1000);
    1884                 :          0 :                 spin_lock_irqsave(&session->lock, flags);
    1885                 :            :         }
    1886                 :            :         spin_unlock_irqrestore(&session->lock, flags);
    1887                 :          0 :         return ret;
    1888                 :            : }
    1889                 :            : EXPORT_SYMBOL_GPL(iscsi_block_scsi_eh);
    1890                 :            : 
    1891                 :          0 : static void session_recovery_timedout(struct work_struct *work)
    1892                 :            : {
    1893                 :            :         struct iscsi_cls_session *session =
    1894                 :          0 :                 container_of(work, struct iscsi_cls_session,
    1895                 :            :                              recovery_work.work);
    1896                 :            :         unsigned long flags;
    1897                 :            : 
    1898                 :          0 :         iscsi_cls_session_printk(KERN_INFO, session,
    1899                 :            :                                  "session recovery timed out after %d secs\n",
    1900                 :            :                                  session->recovery_tmo);
    1901                 :            : 
    1902                 :          0 :         spin_lock_irqsave(&session->lock, flags);
    1903                 :          0 :         switch (session->state) {
    1904                 :            :         case ISCSI_SESSION_FAILED:
    1905                 :          0 :                 session->state = ISCSI_SESSION_FREE;
    1906                 :          0 :                 break;
    1907                 :            :         case ISCSI_SESSION_LOGGED_IN:
    1908                 :            :         case ISCSI_SESSION_FREE:
    1909                 :            :                 /* we raced with the unblock's flush */
    1910                 :            :                 spin_unlock_irqrestore(&session->lock, flags);
    1911                 :          0 :                 return;
    1912                 :            :         }
    1913                 :            :         spin_unlock_irqrestore(&session->lock, flags);
    1914                 :            : 
    1915                 :          0 :         if (session->transport->session_recovery_timedout)
    1916                 :          0 :                 session->transport->session_recovery_timedout(session);
    1917                 :            : 
    1918                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
    1919                 :          0 :         scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
    1920                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n");
    1921                 :            : }
    1922                 :            : 
    1923                 :          0 : static void __iscsi_unblock_session(struct work_struct *work)
    1924                 :            : {
    1925                 :            :         struct iscsi_cls_session *session =
    1926                 :            :                         container_of(work, struct iscsi_cls_session,
    1927                 :            :                                      unblock_work);
    1928                 :          0 :         struct Scsi_Host *shost = iscsi_session_to_shost(session);
    1929                 :          0 :         struct iscsi_cls_host *ihost = shost->shost_data;
    1930                 :            :         unsigned long flags;
    1931                 :            : 
    1932                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Unblocking session\n");
    1933                 :            :         /*
    1934                 :            :          * The recovery and unblock work get run from the same workqueue,
    1935                 :            :          * so try to cancel it if it was going to run after this unblock.
    1936                 :            :          */
    1937                 :          0 :         cancel_delayed_work(&session->recovery_work);
    1938                 :          0 :         spin_lock_irqsave(&session->lock, flags);
    1939                 :          0 :         session->state = ISCSI_SESSION_LOGGED_IN;
    1940                 :            :         spin_unlock_irqrestore(&session->lock, flags);
    1941                 :            :         /* start IO */
    1942                 :          0 :         scsi_target_unblock(&session->dev, SDEV_RUNNING);
    1943                 :            :         /*
    1944                 :            :          * Only do kernel scanning if the driver is properly hooked into
    1945                 :            :          * the async scanning code (drivers like iscsi_tcp do login and
    1946                 :            :          * scanning from userspace).
    1947                 :            :          */
    1948                 :          0 :         if (shost->hostt->scan_finished) {
    1949                 :          0 :                 if (scsi_queue_work(shost, &session->scan_work))
    1950                 :          0 :                         atomic_inc(&ihost->nr_scans);
    1951                 :            :         }
    1952                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking session\n");
    1953                 :          0 : }
    1954                 :            : 
    1955                 :            : /**
    1956                 :            :  * iscsi_unblock_session - set a session as logged in and start IO.
    1957                 :            :  * @session: iscsi session
    1958                 :            :  *
    1959                 :            :  * Mark a session as ready to accept IO.
    1960                 :            :  */
    1961                 :          0 : void iscsi_unblock_session(struct iscsi_cls_session *session)
    1962                 :            : {
    1963                 :          0 :         queue_work(iscsi_eh_timer_workq, &session->unblock_work);
    1964                 :            :         /*
    1965                 :            :          * make sure all the events have completed before tell the driver
    1966                 :            :          * it is safe
    1967                 :            :          */
    1968                 :          0 :         flush_workqueue(iscsi_eh_timer_workq);
    1969                 :          0 : }
    1970                 :            : EXPORT_SYMBOL_GPL(iscsi_unblock_session);
    1971                 :            : 
    1972                 :          0 : static void __iscsi_block_session(struct work_struct *work)
    1973                 :            : {
    1974                 :            :         struct iscsi_cls_session *session =
    1975                 :            :                         container_of(work, struct iscsi_cls_session,
    1976                 :            :                                      block_work);
    1977                 :            :         unsigned long flags;
    1978                 :            : 
    1979                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Blocking session\n");
    1980                 :          0 :         spin_lock_irqsave(&session->lock, flags);
    1981                 :          0 :         session->state = ISCSI_SESSION_FAILED;
    1982                 :            :         spin_unlock_irqrestore(&session->lock, flags);
    1983                 :          0 :         scsi_target_block(&session->dev);
    1984                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n");
    1985                 :          0 :         if (session->recovery_tmo >= 0)
    1986                 :          0 :                 queue_delayed_work(iscsi_eh_timer_workq,
    1987                 :            :                                    &session->recovery_work,
    1988                 :          0 :                                    session->recovery_tmo * HZ);
    1989                 :          0 : }
    1990                 :            : 
    1991                 :          0 : void iscsi_block_session(struct iscsi_cls_session *session)
    1992                 :            : {
    1993                 :          0 :         queue_work(iscsi_eh_timer_workq, &session->block_work);
    1994                 :          0 : }
    1995                 :            : EXPORT_SYMBOL_GPL(iscsi_block_session);
    1996                 :            : 
    1997                 :          0 : static void __iscsi_unbind_session(struct work_struct *work)
    1998                 :            : {
    1999                 :            :         struct iscsi_cls_session *session =
    2000                 :          0 :                         container_of(work, struct iscsi_cls_session,
    2001                 :            :                                      unbind_work);
    2002                 :          0 :         struct Scsi_Host *shost = iscsi_session_to_shost(session);
    2003                 :          0 :         struct iscsi_cls_host *ihost = shost->shost_data;
    2004                 :            :         unsigned long flags;
    2005                 :            :         unsigned int target_id;
    2006                 :            : 
    2007                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");
    2008                 :            : 
    2009                 :            :         /* Prevent new scans and make sure scanning is not in progress */
    2010                 :          0 :         mutex_lock(&ihost->mutex);
    2011                 :          0 :         spin_lock_irqsave(&session->lock, flags);
    2012                 :          0 :         if (session->target_id == ISCSI_MAX_TARGET) {
    2013                 :            :                 spin_unlock_irqrestore(&session->lock, flags);
    2014                 :          0 :                 mutex_unlock(&ihost->mutex);
    2015                 :          0 :                 goto unbind_session_exit;
    2016                 :            :         }
    2017                 :            : 
    2018                 :            :         target_id = session->target_id;
    2019                 :          0 :         session->target_id = ISCSI_MAX_TARGET;
    2020                 :            :         spin_unlock_irqrestore(&session->lock, flags);
    2021                 :          0 :         mutex_unlock(&ihost->mutex);
    2022                 :            : 
    2023                 :          0 :         if (session->ida_used)
    2024                 :          0 :                 ida_simple_remove(&iscsi_sess_ida, target_id);
    2025                 :            : 
    2026                 :          0 :         scsi_remove_target(&session->dev);
    2027                 :            : 
    2028                 :            : unbind_session_exit:
    2029                 :          0 :         iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
    2030                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
    2031                 :          0 : }
    2032                 :            : 
    2033                 :            : struct iscsi_cls_session *
    2034                 :          0 : iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
    2035                 :            :                     int dd_size)
    2036                 :            : {
    2037                 :            :         struct iscsi_cls_session *session;
    2038                 :            : 
    2039                 :          0 :         session = kzalloc(sizeof(*session) + dd_size,
    2040                 :            :                           GFP_KERNEL);
    2041                 :          0 :         if (!session)
    2042                 :            :                 return NULL;
    2043                 :            : 
    2044                 :          0 :         session->transport = transport;
    2045                 :          0 :         session->creator = -1;
    2046                 :          0 :         session->recovery_tmo = 120;
    2047                 :          0 :         session->recovery_tmo_sysfs_override = false;
    2048                 :          0 :         session->state = ISCSI_SESSION_FREE;
    2049                 :          0 :         INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
    2050                 :          0 :         INIT_LIST_HEAD(&session->sess_list);
    2051                 :          0 :         INIT_WORK(&session->unblock_work, __iscsi_unblock_session);
    2052                 :          0 :         INIT_WORK(&session->block_work, __iscsi_block_session);
    2053                 :          0 :         INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
    2054                 :          0 :         INIT_WORK(&session->scan_work, iscsi_scan_session);
    2055                 :          0 :         spin_lock_init(&session->lock);
    2056                 :            : 
    2057                 :            :         /* this is released in the dev's release function */
    2058                 :          0 :         scsi_host_get(shost);
    2059                 :          0 :         session->dev.parent = &shost->shost_gendev;
    2060                 :          0 :         session->dev.release = iscsi_session_release;
    2061                 :          0 :         device_initialize(&session->dev);
    2062                 :          0 :         if (dd_size)
    2063                 :          0 :                 session->dd_data = &session[1];
    2064                 :            : 
    2065                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Completed session allocation\n");
    2066                 :          0 :         return session;
    2067                 :            : }
    2068                 :            : EXPORT_SYMBOL_GPL(iscsi_alloc_session);
    2069                 :            : 
    2070                 :          0 : int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
    2071                 :            : {
    2072                 :            :         unsigned long flags;
    2073                 :            :         int id = 0;
    2074                 :            :         int err;
    2075                 :            : 
    2076                 :          0 :         session->sid = atomic_add_return(1, &iscsi_session_nr);
    2077                 :            : 
    2078                 :          0 :         if (target_id == ISCSI_MAX_TARGET) {
    2079                 :          0 :                 id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL);
    2080                 :            : 
    2081                 :          0 :                 if (id < 0) {
    2082                 :          0 :                         iscsi_cls_session_printk(KERN_ERR, session,
    2083                 :            :                                         "Failure in Target ID Allocation\n");
    2084                 :          0 :                         return id;
    2085                 :            :                 }
    2086                 :          0 :                 session->target_id = (unsigned int)id;
    2087                 :          0 :                 session->ida_used = true;
    2088                 :            :         } else
    2089                 :          0 :                 session->target_id = target_id;
    2090                 :            : 
    2091                 :          0 :         dev_set_name(&session->dev, "session%u", session->sid);
    2092                 :          0 :         err = device_add(&session->dev);
    2093                 :          0 :         if (err) {
    2094                 :          0 :                 iscsi_cls_session_printk(KERN_ERR, session,
    2095                 :            :                                          "could not register session's dev\n");
    2096                 :            :                 goto release_ida;
    2097                 :            :         }
    2098                 :            :         transport_register_device(&session->dev);
    2099                 :            : 
    2100                 :          0 :         spin_lock_irqsave(&sesslock, flags);
    2101                 :          0 :         list_add(&session->sess_list, &sesslist);
    2102                 :            :         spin_unlock_irqrestore(&sesslock, flags);
    2103                 :            : 
    2104                 :          0 :         iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);
    2105                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
    2106                 :          0 :         return 0;
    2107                 :            : 
    2108                 :            : release_ida:
    2109                 :          0 :         if (session->ida_used)
    2110                 :          0 :                 ida_simple_remove(&iscsi_sess_ida, session->target_id);
    2111                 :            : 
    2112                 :          0 :         return err;
    2113                 :            : }
    2114                 :            : EXPORT_SYMBOL_GPL(iscsi_add_session);
    2115                 :            : 
    2116                 :            : /**
    2117                 :            :  * iscsi_create_session - create iscsi class session
    2118                 :            :  * @shost: scsi host
    2119                 :            :  * @transport: iscsi transport
    2120                 :            :  * @dd_size: private driver data size
    2121                 :            :  * @target_id: which target
    2122                 :            :  *
    2123                 :            :  * This can be called from a LLD or iscsi_transport.
    2124                 :            :  */
    2125                 :            : struct iscsi_cls_session *
    2126                 :          0 : iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
    2127                 :            :                      int dd_size, unsigned int target_id)
    2128                 :            : {
    2129                 :            :         struct iscsi_cls_session *session;
    2130                 :            : 
    2131                 :          0 :         session = iscsi_alloc_session(shost, transport, dd_size);
    2132                 :          0 :         if (!session)
    2133                 :            :                 return NULL;
    2134                 :            : 
    2135                 :          0 :         if (iscsi_add_session(session, target_id)) {
    2136                 :          0 :                 iscsi_free_session(session);
    2137                 :          0 :                 return NULL;
    2138                 :            :         }
    2139                 :            :         return session;
    2140                 :            : }
    2141                 :            : EXPORT_SYMBOL_GPL(iscsi_create_session);
    2142                 :            : 
    2143                 :          0 : static void iscsi_conn_release(struct device *dev)
    2144                 :            : {
    2145                 :          0 :         struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
    2146                 :          0 :         struct device *parent = conn->dev.parent;
    2147                 :            : 
    2148                 :          0 :         ISCSI_DBG_TRANS_CONN(conn, "Releasing conn\n");
    2149                 :          0 :         kfree(conn);
    2150                 :          0 :         put_device(parent);
    2151                 :          0 : }
    2152                 :            : 
    2153                 :            : static int iscsi_is_conn_dev(const struct device *dev)
    2154                 :            : {
    2155                 :          0 :         return dev->release == iscsi_conn_release;
    2156                 :            : }
    2157                 :            : 
    2158                 :          0 : static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
    2159                 :            : {
    2160                 :          0 :         if (!iscsi_is_conn_dev(dev))
    2161                 :            :                 return 0;
    2162                 :          0 :         return iscsi_destroy_conn(iscsi_dev_to_conn(dev));
    2163                 :            : }
    2164                 :            : 
    2165                 :          0 : void iscsi_remove_session(struct iscsi_cls_session *session)
    2166                 :            : {
    2167                 :            :         unsigned long flags;
    2168                 :            :         int err;
    2169                 :            : 
    2170                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Removing session\n");
    2171                 :            : 
    2172                 :          0 :         spin_lock_irqsave(&sesslock, flags);
    2173                 :            :         list_del(&session->sess_list);
    2174                 :            :         spin_unlock_irqrestore(&sesslock, flags);
    2175                 :            : 
    2176                 :            :         /* make sure there are no blocks/unblocks queued */
    2177                 :          0 :         flush_workqueue(iscsi_eh_timer_workq);
    2178                 :            :         /* make sure the timedout callout is not running */
    2179                 :          0 :         if (!cancel_delayed_work(&session->recovery_work))
    2180                 :          0 :                 flush_workqueue(iscsi_eh_timer_workq);
    2181                 :            :         /*
    2182                 :            :          * If we are blocked let commands flow again. The lld or iscsi
    2183                 :            :          * layer should set up the queuecommand to fail commands.
    2184                 :            :          * We assume that LLD will not be calling block/unblock while
    2185                 :            :          * removing the session.
    2186                 :            :          */
    2187                 :          0 :         spin_lock_irqsave(&session->lock, flags);
    2188                 :          0 :         session->state = ISCSI_SESSION_FREE;
    2189                 :            :         spin_unlock_irqrestore(&session->lock, flags);
    2190                 :            : 
    2191                 :          0 :         scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
    2192                 :            :         /* flush running scans then delete devices */
    2193                 :          0 :         flush_work(&session->scan_work);
    2194                 :            :         /* flush running unbind operations */
    2195                 :          0 :         flush_work(&session->unbind_work);
    2196                 :          0 :         __iscsi_unbind_session(&session->unbind_work);
    2197                 :            : 
    2198                 :            :         /* hw iscsi may not have removed all connections from session */
    2199                 :          0 :         err = device_for_each_child(&session->dev, NULL,
    2200                 :            :                                     iscsi_iter_destroy_conn_fn);
    2201                 :          0 :         if (err)
    2202                 :          0 :                 iscsi_cls_session_printk(KERN_ERR, session,
    2203                 :            :                                          "Could not delete all connections "
    2204                 :            :                                          "for session. Error %d.\n", err);
    2205                 :            : 
    2206                 :            :         transport_unregister_device(&session->dev);
    2207                 :            : 
    2208                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Completing session removal\n");
    2209                 :          0 :         device_del(&session->dev);
    2210                 :          0 : }
    2211                 :            : EXPORT_SYMBOL_GPL(iscsi_remove_session);
    2212                 :            : 
    2213                 :          0 : void iscsi_free_session(struct iscsi_cls_session *session)
    2214                 :            : {
    2215                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Freeing session\n");
    2216                 :          0 :         iscsi_session_event(session, ISCSI_KEVENT_DESTROY_SESSION);
    2217                 :          0 :         put_device(&session->dev);
    2218                 :          0 : }
    2219                 :            : EXPORT_SYMBOL_GPL(iscsi_free_session);
    2220                 :            : 
    2221                 :            : /**
    2222                 :            :  * iscsi_create_conn - create iscsi class connection
    2223                 :            :  * @session: iscsi cls session
    2224                 :            :  * @dd_size: private driver data size
    2225                 :            :  * @cid: connection id
    2226                 :            :  *
    2227                 :            :  * This can be called from a LLD or iscsi_transport. The connection
    2228                 :            :  * is child of the session so cid must be unique for all connections
    2229                 :            :  * on the session.
    2230                 :            :  *
    2231                 :            :  * Since we do not support MCS, cid will normally be zero. In some cases
    2232                 :            :  * for software iscsi we could be trying to preallocate a connection struct
    2233                 :            :  * in which case there could be two connection structs and cid would be
    2234                 :            :  * non-zero.
    2235                 :            :  */
    2236                 :            : struct iscsi_cls_conn *
    2237                 :          0 : iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
    2238                 :            : {
    2239                 :          0 :         struct iscsi_transport *transport = session->transport;
    2240                 :            :         struct iscsi_cls_conn *conn;
    2241                 :            :         unsigned long flags;
    2242                 :            :         int err;
    2243                 :            : 
    2244                 :          0 :         conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL);
    2245                 :          0 :         if (!conn)
    2246                 :            :                 return NULL;
    2247                 :          0 :         if (dd_size)
    2248                 :          0 :                 conn->dd_data = &conn[1];
    2249                 :            : 
    2250                 :          0 :         mutex_init(&conn->ep_mutex);
    2251                 :          0 :         INIT_LIST_HEAD(&conn->conn_list);
    2252                 :          0 :         conn->transport = transport;
    2253                 :          0 :         conn->cid = cid;
    2254                 :            : 
    2255                 :            :         /* this is released in the dev's release function */
    2256                 :          0 :         if (!get_device(&session->dev))
    2257                 :            :                 goto free_conn;
    2258                 :            : 
    2259                 :          0 :         dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid);
    2260                 :          0 :         conn->dev.parent = &session->dev;
    2261                 :          0 :         conn->dev.release = iscsi_conn_release;
    2262                 :          0 :         err = device_register(&conn->dev);
    2263                 :          0 :         if (err) {
    2264                 :          0 :                 iscsi_cls_session_printk(KERN_ERR, session, "could not "
    2265                 :            :                                          "register connection's dev\n");
    2266                 :            :                 goto release_parent_ref;
    2267                 :            :         }
    2268                 :            :         transport_register_device(&conn->dev);
    2269                 :            : 
    2270                 :          0 :         spin_lock_irqsave(&connlock, flags);
    2271                 :            :         list_add(&conn->conn_list, &connlist);
    2272                 :            :         spin_unlock_irqrestore(&connlock, flags);
    2273                 :            : 
    2274                 :          0 :         ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
    2275                 :          0 :         return conn;
    2276                 :            : 
    2277                 :            : release_parent_ref:
    2278                 :          0 :         put_device(&session->dev);
    2279                 :            : free_conn:
    2280                 :          0 :         kfree(conn);
    2281                 :          0 :         return NULL;
    2282                 :            : }
    2283                 :            : 
    2284                 :            : EXPORT_SYMBOL_GPL(iscsi_create_conn);
    2285                 :            : 
    2286                 :            : /**
    2287                 :            :  * iscsi_destroy_conn - destroy iscsi class connection
    2288                 :            :  * @conn: iscsi cls session
    2289                 :            :  *
    2290                 :            :  * This can be called from a LLD or iscsi_transport.
    2291                 :            :  */
    2292                 :          0 : int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
    2293                 :            : {
    2294                 :            :         unsigned long flags;
    2295                 :            : 
    2296                 :          0 :         spin_lock_irqsave(&connlock, flags);
    2297                 :            :         list_del(&conn->conn_list);
    2298                 :            :         spin_unlock_irqrestore(&connlock, flags);
    2299                 :            : 
    2300                 :          0 :         transport_unregister_device(&conn->dev);
    2301                 :          0 :         ISCSI_DBG_TRANS_CONN(conn, "Completing conn destruction\n");
    2302                 :          0 :         device_unregister(&conn->dev);
    2303                 :          0 :         return 0;
    2304                 :            : }
    2305                 :            : EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
    2306                 :            : 
    2307                 :            : /*
    2308                 :            :  * iscsi interface functions
    2309                 :            :  */
    2310                 :            : static struct iscsi_internal *
    2311                 :          0 : iscsi_if_transport_lookup(struct iscsi_transport *tt)
    2312                 :            : {
    2313                 :            :         struct iscsi_internal *priv;
    2314                 :            :         unsigned long flags;
    2315                 :            : 
    2316                 :          0 :         spin_lock_irqsave(&iscsi_transport_lock, flags);
    2317                 :          0 :         list_for_each_entry(priv, &iscsi_transports, list) {
    2318                 :          0 :                 if (tt == priv->iscsi_transport) {
    2319                 :            :                         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
    2320                 :          0 :                         return priv;
    2321                 :            :                 }
    2322                 :            :         }
    2323                 :            :         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
    2324                 :          0 :         return NULL;
    2325                 :            : }
    2326                 :            : 
    2327                 :            : static int
    2328                 :          0 : iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp)
    2329                 :            : {
    2330                 :          0 :         return nlmsg_multicast(nls, skb, 0, group, gfp);
    2331                 :            : }
    2332                 :            : 
    2333                 :            : static int
    2334                 :            : iscsi_unicast_skb(struct sk_buff *skb, u32 portid)
    2335                 :            : {
    2336                 :          0 :         return nlmsg_unicast(nls, skb, portid);
    2337                 :            : }
    2338                 :            : 
    2339                 :          0 : int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
    2340                 :            :                    char *data, uint32_t data_size)
    2341                 :            : {
    2342                 :            :         struct nlmsghdr *nlh;
    2343                 :            :         struct sk_buff *skb;
    2344                 :            :         struct iscsi_uevent *ev;
    2345                 :            :         char *pdu;
    2346                 :            :         struct iscsi_internal *priv;
    2347                 :          0 :         int len = nlmsg_total_size(sizeof(*ev) + sizeof(struct iscsi_hdr) +
    2348                 :            :                                    data_size);
    2349                 :            : 
    2350                 :          0 :         priv = iscsi_if_transport_lookup(conn->transport);
    2351                 :          0 :         if (!priv)
    2352                 :            :                 return -EINVAL;
    2353                 :            : 
    2354                 :          0 :         skb = alloc_skb(len, GFP_ATOMIC);
    2355                 :          0 :         if (!skb) {
    2356                 :          0 :                 iscsi_conn_error_event(conn, ISCSI_ERR_CONN_FAILED);
    2357                 :          0 :                 iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver "
    2358                 :            :                                       "control PDU: OOM\n");
    2359                 :          0 :                 return -ENOMEM;
    2360                 :            :         }
    2361                 :            : 
    2362                 :          0 :         nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
    2363                 :            :         ev = nlmsg_data(nlh);
    2364                 :          0 :         memset(ev, 0, sizeof(*ev));
    2365                 :          0 :         ev->transport_handle = iscsi_handle(conn->transport);
    2366                 :          0 :         ev->type = ISCSI_KEVENT_RECV_PDU;
    2367                 :          0 :         ev->r.recv_req.cid = conn->cid;
    2368                 :          0 :         ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
    2369                 :          0 :         pdu = (char*)ev + sizeof(*ev);
    2370                 :          0 :         memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
    2371                 :          0 :         memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
    2372                 :            : 
    2373                 :          0 :         return iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
    2374                 :            : }
    2375                 :            : EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
    2376                 :            : 
    2377                 :          0 : int iscsi_offload_mesg(struct Scsi_Host *shost,
    2378                 :            :                        struct iscsi_transport *transport, uint32_t type,
    2379                 :            :                        char *data, uint16_t data_size)
    2380                 :            : {
    2381                 :            :         struct nlmsghdr *nlh;
    2382                 :            :         struct sk_buff *skb;
    2383                 :            :         struct iscsi_uevent *ev;
    2384                 :          0 :         int len = nlmsg_total_size(sizeof(*ev) + data_size);
    2385                 :            : 
    2386                 :          0 :         skb = alloc_skb(len, GFP_ATOMIC);
    2387                 :          0 :         if (!skb) {
    2388                 :          0 :                 printk(KERN_ERR "can not deliver iscsi offload message:OOM\n");
    2389                 :          0 :                 return -ENOMEM;
    2390                 :            :         }
    2391                 :            : 
    2392                 :          0 :         nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
    2393                 :            :         ev = nlmsg_data(nlh);
    2394                 :          0 :         memset(ev, 0, sizeof(*ev));
    2395                 :          0 :         ev->type = type;
    2396                 :          0 :         ev->transport_handle = iscsi_handle(transport);
    2397                 :          0 :         switch (type) {
    2398                 :            :         case ISCSI_KEVENT_PATH_REQ:
    2399                 :          0 :                 ev->r.req_path.host_no = shost->host_no;
    2400                 :          0 :                 break;
    2401                 :            :         case ISCSI_KEVENT_IF_DOWN:
    2402                 :          0 :                 ev->r.notify_if_down.host_no = shost->host_no;
    2403                 :          0 :                 break;
    2404                 :            :         }
    2405                 :            : 
    2406                 :          0 :         memcpy((char *)ev + sizeof(*ev), data, data_size);
    2407                 :            : 
    2408                 :          0 :         return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC);
    2409                 :            : }
    2410                 :            : EXPORT_SYMBOL_GPL(iscsi_offload_mesg);
    2411                 :            : 
    2412                 :          0 : void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
    2413                 :            : {
    2414                 :            :         struct nlmsghdr *nlh;
    2415                 :            :         struct sk_buff  *skb;
    2416                 :            :         struct iscsi_uevent *ev;
    2417                 :            :         struct iscsi_internal *priv;
    2418                 :            :         int len = nlmsg_total_size(sizeof(*ev));
    2419                 :            : 
    2420                 :          0 :         priv = iscsi_if_transport_lookup(conn->transport);
    2421                 :          0 :         if (!priv)
    2422                 :            :                 return;
    2423                 :            : 
    2424                 :            :         skb = alloc_skb(len, GFP_ATOMIC);
    2425                 :          0 :         if (!skb) {
    2426                 :          0 :                 iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
    2427                 :            :                                       "conn error (%d)\n", error);
    2428                 :          0 :                 return;
    2429                 :            :         }
    2430                 :            : 
    2431                 :          0 :         nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
    2432                 :            :         ev = nlmsg_data(nlh);
    2433                 :          0 :         ev->transport_handle = iscsi_handle(conn->transport);
    2434                 :          0 :         ev->type = ISCSI_KEVENT_CONN_ERROR;
    2435                 :          0 :         ev->r.connerror.error = error;
    2436                 :          0 :         ev->r.connerror.cid = conn->cid;
    2437                 :          0 :         ev->r.connerror.sid = iscsi_conn_get_sid(conn);
    2438                 :            : 
    2439                 :          0 :         iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
    2440                 :            : 
    2441                 :          0 :         iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n",
    2442                 :            :                               error);
    2443                 :            : }
    2444                 :            : EXPORT_SYMBOL_GPL(iscsi_conn_error_event);
    2445                 :            : 
    2446                 :          0 : void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
    2447                 :            :                             enum iscsi_conn_state state)
    2448                 :            : {
    2449                 :            :         struct nlmsghdr *nlh;
    2450                 :            :         struct sk_buff  *skb;
    2451                 :            :         struct iscsi_uevent *ev;
    2452                 :            :         struct iscsi_internal *priv;
    2453                 :            :         int len = nlmsg_total_size(sizeof(*ev));
    2454                 :            : 
    2455                 :          0 :         priv = iscsi_if_transport_lookup(conn->transport);
    2456                 :          0 :         if (!priv)
    2457                 :            :                 return;
    2458                 :            : 
    2459                 :            :         skb = alloc_skb(len, GFP_ATOMIC);
    2460                 :          0 :         if (!skb) {
    2461                 :          0 :                 iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
    2462                 :            :                                       "conn login (%d)\n", state);
    2463                 :          0 :                 return;
    2464                 :            :         }
    2465                 :            : 
    2466                 :          0 :         nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
    2467                 :            :         ev = nlmsg_data(nlh);
    2468                 :          0 :         ev->transport_handle = iscsi_handle(conn->transport);
    2469                 :          0 :         ev->type = ISCSI_KEVENT_CONN_LOGIN_STATE;
    2470                 :          0 :         ev->r.conn_login.state = state;
    2471                 :          0 :         ev->r.conn_login.cid = conn->cid;
    2472                 :          0 :         ev->r.conn_login.sid = iscsi_conn_get_sid(conn);
    2473                 :          0 :         iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
    2474                 :            : 
    2475                 :          0 :         iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn login (%d)\n",
    2476                 :            :                               state);
    2477                 :            : }
    2478                 :            : EXPORT_SYMBOL_GPL(iscsi_conn_login_event);
    2479                 :            : 
    2480                 :          0 : void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport,
    2481                 :            :                            enum iscsi_host_event_code code, uint32_t data_size,
    2482                 :            :                            uint8_t *data)
    2483                 :            : {
    2484                 :            :         struct nlmsghdr *nlh;
    2485                 :            :         struct sk_buff *skb;
    2486                 :            :         struct iscsi_uevent *ev;
    2487                 :          0 :         int len = nlmsg_total_size(sizeof(*ev) + data_size);
    2488                 :            : 
    2489                 :          0 :         skb = alloc_skb(len, GFP_NOIO);
    2490                 :          0 :         if (!skb) {
    2491                 :          0 :                 printk(KERN_ERR "gracefully ignored host event (%d):%d OOM\n",
    2492                 :            :                        host_no, code);
    2493                 :          0 :                 return;
    2494                 :            :         }
    2495                 :            : 
    2496                 :          0 :         nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
    2497                 :            :         ev = nlmsg_data(nlh);
    2498                 :          0 :         ev->transport_handle = iscsi_handle(transport);
    2499                 :          0 :         ev->type = ISCSI_KEVENT_HOST_EVENT;
    2500                 :          0 :         ev->r.host_event.host_no = host_no;
    2501                 :          0 :         ev->r.host_event.code = code;
    2502                 :          0 :         ev->r.host_event.data_size = data_size;
    2503                 :            : 
    2504                 :          0 :         if (data_size)
    2505                 :          0 :                 memcpy((char *)ev + sizeof(*ev), data, data_size);
    2506                 :            : 
    2507                 :          0 :         iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
    2508                 :            : }
    2509                 :            : EXPORT_SYMBOL_GPL(iscsi_post_host_event);
    2510                 :            : 
    2511                 :          0 : void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport,
    2512                 :            :                            uint32_t status, uint32_t pid, uint32_t data_size,
    2513                 :            :                            uint8_t *data)
    2514                 :            : {
    2515                 :            :         struct nlmsghdr *nlh;
    2516                 :            :         struct sk_buff *skb;
    2517                 :            :         struct iscsi_uevent *ev;
    2518                 :          0 :         int len = nlmsg_total_size(sizeof(*ev) + data_size);
    2519                 :            : 
    2520                 :          0 :         skb = alloc_skb(len, GFP_NOIO);
    2521                 :          0 :         if (!skb) {
    2522                 :          0 :                 printk(KERN_ERR "gracefully ignored ping comp: OOM\n");
    2523                 :          0 :                 return;
    2524                 :            :         }
    2525                 :            : 
    2526                 :          0 :         nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
    2527                 :            :         ev = nlmsg_data(nlh);
    2528                 :          0 :         ev->transport_handle = iscsi_handle(transport);
    2529                 :          0 :         ev->type = ISCSI_KEVENT_PING_COMP;
    2530                 :          0 :         ev->r.ping_comp.host_no = host_no;
    2531                 :          0 :         ev->r.ping_comp.status = status;
    2532                 :          0 :         ev->r.ping_comp.pid = pid;
    2533                 :          0 :         ev->r.ping_comp.data_size = data_size;
    2534                 :          0 :         memcpy((char *)ev + sizeof(*ev), data, data_size);
    2535                 :            : 
    2536                 :          0 :         iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
    2537                 :            : }
    2538                 :            : EXPORT_SYMBOL_GPL(iscsi_ping_comp_event);
    2539                 :            : 
    2540                 :            : static int
    2541                 :          0 : iscsi_if_send_reply(u32 portid, int type, void *payload, int size)
    2542                 :            : {
    2543                 :            :         struct sk_buff  *skb;
    2544                 :            :         struct nlmsghdr *nlh;
    2545                 :            :         int len = nlmsg_total_size(size);
    2546                 :            : 
    2547                 :          0 :         skb = alloc_skb(len, GFP_ATOMIC);
    2548                 :          0 :         if (!skb) {
    2549                 :          0 :                 printk(KERN_ERR "Could not allocate skb to send reply.\n");
    2550                 :          0 :                 return -ENOMEM;
    2551                 :            :         }
    2552                 :            : 
    2553                 :          0 :         nlh = __nlmsg_put(skb, 0, 0, type, (len - sizeof(*nlh)), 0);
    2554                 :          0 :         memcpy(nlmsg_data(nlh), payload, size);
    2555                 :          0 :         return iscsi_unicast_skb(skb, portid);
    2556                 :            : }
    2557                 :            : 
    2558                 :            : static int
    2559                 :          0 : iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
    2560                 :            : {
    2561                 :            :         struct iscsi_uevent *ev = nlmsg_data(nlh);
    2562                 :            :         struct iscsi_stats *stats;
    2563                 :            :         struct sk_buff *skbstat;
    2564                 :            :         struct iscsi_cls_conn *conn;
    2565                 :            :         struct nlmsghdr *nlhstat;
    2566                 :            :         struct iscsi_uevent *evstat;
    2567                 :            :         struct iscsi_internal *priv;
    2568                 :            :         int len = nlmsg_total_size(sizeof(*ev) +
    2569                 :            :                                    sizeof(struct iscsi_stats) +
    2570                 :            :                                    sizeof(struct iscsi_stats_custom) *
    2571                 :            :                                    ISCSI_STATS_CUSTOM_MAX);
    2572                 :            :         int err = 0;
    2573                 :            : 
    2574                 :          0 :         priv = iscsi_if_transport_lookup(transport);
    2575                 :          0 :         if (!priv)
    2576                 :            :                 return -EINVAL;
    2577                 :            : 
    2578                 :          0 :         conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid);
    2579                 :          0 :         if (!conn)
    2580                 :            :                 return -EEXIST;
    2581                 :            : 
    2582                 :            :         do {
    2583                 :            :                 int actual_size;
    2584                 :            : 
    2585                 :            :                 skbstat = alloc_skb(len, GFP_ATOMIC);
    2586                 :          0 :                 if (!skbstat) {
    2587                 :          0 :                         iscsi_cls_conn_printk(KERN_ERR, conn, "can not "
    2588                 :            :                                               "deliver stats: OOM\n");
    2589                 :          0 :                         return -ENOMEM;
    2590                 :            :                 }
    2591                 :            : 
    2592                 :          0 :                 nlhstat = __nlmsg_put(skbstat, 0, 0, 0,
    2593                 :            :                                       (len - sizeof(*nlhstat)), 0);
    2594                 :            :                 evstat = nlmsg_data(nlhstat);
    2595                 :          0 :                 memset(evstat, 0, sizeof(*evstat));
    2596                 :          0 :                 evstat->transport_handle = iscsi_handle(conn->transport);
    2597                 :          0 :                 evstat->type = nlh->nlmsg_type;
    2598                 :          0 :                 evstat->u.get_stats.cid =
    2599                 :          0 :                         ev->u.get_stats.cid;
    2600                 :          0 :                 evstat->u.get_stats.sid =
    2601                 :          0 :                         ev->u.get_stats.sid;
    2602                 :          0 :                 stats = (struct iscsi_stats *)
    2603                 :            :                         ((char*)evstat + sizeof(*evstat));
    2604                 :          0 :                 memset(stats, 0, sizeof(*stats));
    2605                 :            : 
    2606                 :          0 :                 transport->get_stats(conn, stats);
    2607                 :          0 :                 actual_size = nlmsg_total_size(sizeof(struct iscsi_uevent) +
    2608                 :          0 :                                                sizeof(struct iscsi_stats) +
    2609                 :          0 :                                                sizeof(struct iscsi_stats_custom) *
    2610                 :          0 :                                                stats->custom_length);
    2611                 :          0 :                 actual_size -= sizeof(*nlhstat);
    2612                 :            :                 actual_size = nlmsg_msg_size(actual_size);
    2613                 :          0 :                 skb_trim(skbstat, NLMSG_ALIGN(actual_size));
    2614                 :          0 :                 nlhstat->nlmsg_len = actual_size;
    2615                 :            : 
    2616                 :          0 :                 err = iscsi_multicast_skb(skbstat, ISCSI_NL_GRP_ISCSID,
    2617                 :            :                                           GFP_ATOMIC);
    2618                 :          0 :         } while (err < 0 && err != -ECONNREFUSED);
    2619                 :            : 
    2620                 :          0 :         return err;
    2621                 :            : }
    2622                 :            : 
    2623                 :            : /**
    2624                 :            :  * iscsi_session_event - send session destr. completion event
    2625                 :            :  * @session: iscsi class session
    2626                 :            :  * @event: type of event
    2627                 :            :  */
    2628                 :          0 : int iscsi_session_event(struct iscsi_cls_session *session,
    2629                 :            :                         enum iscsi_uevent_e event)
    2630                 :            : {
    2631                 :            :         struct iscsi_internal *priv;
    2632                 :            :         struct Scsi_Host *shost;
    2633                 :            :         struct iscsi_uevent *ev;
    2634                 :            :         struct sk_buff  *skb;
    2635                 :            :         struct nlmsghdr *nlh;
    2636                 :            :         int rc, len = nlmsg_total_size(sizeof(*ev));
    2637                 :            : 
    2638                 :          0 :         priv = iscsi_if_transport_lookup(session->transport);
    2639                 :          0 :         if (!priv)
    2640                 :            :                 return -EINVAL;
    2641                 :          0 :         shost = iscsi_session_to_shost(session);
    2642                 :            : 
    2643                 :            :         skb = alloc_skb(len, GFP_KERNEL);
    2644                 :          0 :         if (!skb) {
    2645                 :          0 :                 iscsi_cls_session_printk(KERN_ERR, session,
    2646                 :            :                                          "Cannot notify userspace of session "
    2647                 :            :                                          "event %u\n", event);
    2648                 :          0 :                 return -ENOMEM;
    2649                 :            :         }
    2650                 :            : 
    2651                 :          0 :         nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
    2652                 :            :         ev = nlmsg_data(nlh);
    2653                 :          0 :         ev->transport_handle = iscsi_handle(session->transport);
    2654                 :            : 
    2655                 :          0 :         ev->type = event;
    2656                 :          0 :         switch (event) {
    2657                 :            :         case ISCSI_KEVENT_DESTROY_SESSION:
    2658                 :          0 :                 ev->r.d_session.host_no = shost->host_no;
    2659                 :          0 :                 ev->r.d_session.sid = session->sid;
    2660                 :          0 :                 break;
    2661                 :            :         case ISCSI_KEVENT_CREATE_SESSION:
    2662                 :          0 :                 ev->r.c_session_ret.host_no = shost->host_no;
    2663                 :          0 :                 ev->r.c_session_ret.sid = session->sid;
    2664                 :          0 :                 break;
    2665                 :            :         case ISCSI_KEVENT_UNBIND_SESSION:
    2666                 :          0 :                 ev->r.unbind_session.host_no = shost->host_no;
    2667                 :          0 :                 ev->r.unbind_session.sid = session->sid;
    2668                 :          0 :                 break;
    2669                 :            :         default:
    2670                 :          0 :                 iscsi_cls_session_printk(KERN_ERR, session, "Invalid event "
    2671                 :            :                                          "%u.\n", event);
    2672                 :          0 :                 kfree_skb(skb);
    2673                 :          0 :                 return -EINVAL;
    2674                 :            :         }
    2675                 :            : 
    2676                 :            :         /*
    2677                 :            :          * this will occur if the daemon is not up, so we just warn
    2678                 :            :          * the user and when the daemon is restarted it will handle it
    2679                 :            :          */
    2680                 :          0 :         rc = iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_KERNEL);
    2681                 :          0 :         if (rc == -ESRCH)
    2682                 :          0 :                 iscsi_cls_session_printk(KERN_ERR, session,
    2683                 :            :                                          "Cannot notify userspace of session "
    2684                 :            :                                          "event %u. Check iscsi daemon\n",
    2685                 :            :                                          event);
    2686                 :            : 
    2687                 :          0 :         ISCSI_DBG_TRANS_SESSION(session, "Completed handling event %d rc %d\n",
    2688                 :            :                                 event, rc);
    2689                 :          0 :         return rc;
    2690                 :            : }
    2691                 :            : EXPORT_SYMBOL_GPL(iscsi_session_event);
    2692                 :            : 
    2693                 :            : static int
    2694                 :          0 : iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
    2695                 :            :                         struct iscsi_uevent *ev, pid_t pid,
    2696                 :            :                         uint32_t initial_cmdsn, uint16_t cmds_max,
    2697                 :            :                         uint16_t queue_depth)
    2698                 :            : {
    2699                 :          0 :         struct iscsi_transport *transport = priv->iscsi_transport;
    2700                 :            :         struct iscsi_cls_session *session;
    2701                 :            :         struct Scsi_Host *shost;
    2702                 :            : 
    2703                 :          0 :         session = transport->create_session(ep, cmds_max, queue_depth,
    2704                 :            :                                             initial_cmdsn);
    2705                 :          0 :         if (!session)
    2706                 :            :                 return -ENOMEM;
    2707                 :            : 
    2708                 :          0 :         session->creator = pid;
    2709                 :          0 :         shost = iscsi_session_to_shost(session);
    2710                 :          0 :         ev->r.c_session_ret.host_no = shost->host_no;
    2711                 :          0 :         ev->r.c_session_ret.sid = session->sid;
    2712                 :          0 :         ISCSI_DBG_TRANS_SESSION(session,
    2713                 :            :                                 "Completed creating transport session\n");
    2714                 :          0 :         return 0;
    2715                 :            : }
    2716                 :            : 
    2717                 :            : static int
    2718                 :          0 : iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
    2719                 :            : {
    2720                 :            :         struct iscsi_cls_conn *conn;
    2721                 :            :         struct iscsi_cls_session *session;
    2722                 :            : 
    2723                 :          0 :         session = iscsi_session_lookup(ev->u.c_conn.sid);
    2724                 :          0 :         if (!session) {
    2725                 :          0 :                 printk(KERN_ERR "iscsi: invalid session %d.\n",
    2726                 :            :                        ev->u.c_conn.sid);
    2727                 :          0 :                 return -EINVAL;
    2728                 :            :         }
    2729                 :            : 
    2730                 :          0 :         conn = transport->create_conn(session, ev->u.c_conn.cid);
    2731                 :          0 :         if (!conn) {
    2732                 :          0 :                 iscsi_cls_session_printk(KERN_ERR, session,
    2733                 :            :                                          "couldn't create a new connection.");
    2734                 :          0 :                 return -ENOMEM;
    2735                 :            :         }
    2736                 :            : 
    2737                 :          0 :         ev->r.c_conn_ret.sid = session->sid;
    2738                 :          0 :         ev->r.c_conn_ret.cid = conn->cid;
    2739                 :            : 
    2740                 :          0 :         ISCSI_DBG_TRANS_CONN(conn, "Completed creating transport conn\n");
    2741                 :          0 :         return 0;
    2742                 :            : }
    2743                 :            : 
    2744                 :            : static int
    2745                 :          0 : iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
    2746                 :            : {
    2747                 :            :         struct iscsi_cls_conn *conn;
    2748                 :            : 
    2749                 :          0 :         conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
    2750                 :          0 :         if (!conn)
    2751                 :            :                 return -EINVAL;
    2752                 :            : 
    2753                 :          0 :         ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n");
    2754                 :          0 :         if (transport->destroy_conn)
    2755                 :          0 :                 transport->destroy_conn(conn);
    2756                 :            : 
    2757                 :            :         return 0;
    2758                 :            : }
    2759                 :            : 
    2760                 :            : static int
    2761                 :          0 : iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
    2762                 :            : {
    2763                 :          0 :         char *data = (char*)ev + sizeof(*ev);
    2764                 :            :         struct iscsi_cls_conn *conn;
    2765                 :            :         struct iscsi_cls_session *session;
    2766                 :          0 :         int err = 0, value = 0;
    2767                 :            : 
    2768                 :          0 :         session = iscsi_session_lookup(ev->u.set_param.sid);
    2769                 :          0 :         conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
    2770                 :          0 :         if (!conn || !session)
    2771                 :            :                 return -EINVAL;
    2772                 :            : 
    2773                 :          0 :         switch (ev->u.set_param.param) {
    2774                 :            :         case ISCSI_PARAM_SESS_RECOVERY_TMO:
    2775                 :          0 :                 sscanf(data, "%d", &value);
    2776                 :          0 :                 if (!session->recovery_tmo_sysfs_override)
    2777                 :          0 :                         session->recovery_tmo = value;
    2778                 :            :                 break;
    2779                 :            :         default:
    2780                 :          0 :                 err = transport->set_param(conn, ev->u.set_param.param,
    2781                 :          0 :                                            data, ev->u.set_param.len);
    2782                 :            :         }
    2783                 :            : 
    2784                 :          0 :         return err;
    2785                 :            : }
    2786                 :            : 
    2787                 :          0 : static int iscsi_if_ep_connect(struct iscsi_transport *transport,
    2788                 :            :                                struct iscsi_uevent *ev, int msg_type)
    2789                 :            : {
    2790                 :            :         struct iscsi_endpoint *ep;
    2791                 :            :         struct sockaddr *dst_addr;
    2792                 :            :         struct Scsi_Host *shost = NULL;
    2793                 :            :         int non_blocking, err = 0;
    2794                 :            : 
    2795                 :          0 :         if (!transport->ep_connect)
    2796                 :            :                 return -EINVAL;
    2797                 :            : 
    2798                 :          0 :         if (msg_type == ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST) {
    2799                 :          0 :                 shost = scsi_host_lookup(ev->u.ep_connect_through_host.host_no);
    2800                 :          0 :                 if (!shost) {
    2801                 :          0 :                         printk(KERN_ERR "ep connect failed. Could not find "
    2802                 :            :                                "host no %u\n",
    2803                 :            :                                ev->u.ep_connect_through_host.host_no);
    2804                 :          0 :                         return -ENODEV;
    2805                 :            :                 }
    2806                 :          0 :                 non_blocking = ev->u.ep_connect_through_host.non_blocking;
    2807                 :            :         } else
    2808                 :          0 :                 non_blocking = ev->u.ep_connect.non_blocking;
    2809                 :            : 
    2810                 :          0 :         dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
    2811                 :          0 :         ep = transport->ep_connect(shost, dst_addr, non_blocking);
    2812                 :          0 :         if (IS_ERR(ep)) {
    2813                 :            :                 err = PTR_ERR(ep);
    2814                 :          0 :                 goto release_host;
    2815                 :            :         }
    2816                 :            : 
    2817                 :          0 :         ev->r.ep_connect_ret.handle = ep->id;
    2818                 :            : release_host:
    2819                 :          0 :         if (shost)
    2820                 :          0 :                 scsi_host_put(shost);
    2821                 :          0 :         return err;
    2822                 :            : }
    2823                 :            : 
    2824                 :          0 : static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
    2825                 :            :                                   u64 ep_handle)
    2826                 :            : {
    2827                 :            :         struct iscsi_cls_conn *conn;
    2828                 :            :         struct iscsi_endpoint *ep;
    2829                 :            : 
    2830                 :          0 :         if (!transport->ep_disconnect)
    2831                 :            :                 return -EINVAL;
    2832                 :            : 
    2833                 :          0 :         ep = iscsi_lookup_endpoint(ep_handle);
    2834                 :          0 :         if (!ep)
    2835                 :            :                 return -EINVAL;
    2836                 :          0 :         conn = ep->conn;
    2837                 :          0 :         if (conn) {
    2838                 :          0 :                 mutex_lock(&conn->ep_mutex);
    2839                 :          0 :                 conn->ep = NULL;
    2840                 :          0 :                 mutex_unlock(&conn->ep_mutex);
    2841                 :            :         }
    2842                 :            : 
    2843                 :          0 :         transport->ep_disconnect(ep);
    2844                 :          0 :         return 0;
    2845                 :            : }
    2846                 :            : 
    2847                 :            : static int
    2848                 :          0 : iscsi_if_transport_ep(struct iscsi_transport *transport,
    2849                 :            :                       struct iscsi_uevent *ev, int msg_type)
    2850                 :            : {
    2851                 :            :         struct iscsi_endpoint *ep;
    2852                 :            :         int rc = 0;
    2853                 :            : 
    2854                 :          0 :         switch (msg_type) {
    2855                 :            :         case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
    2856                 :            :         case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
    2857                 :          0 :                 rc = iscsi_if_ep_connect(transport, ev, msg_type);
    2858                 :          0 :                 break;
    2859                 :            :         case ISCSI_UEVENT_TRANSPORT_EP_POLL:
    2860                 :          0 :                 if (!transport->ep_poll)
    2861                 :            :                         return -EINVAL;
    2862                 :            : 
    2863                 :          0 :                 ep = iscsi_lookup_endpoint(ev->u.ep_poll.ep_handle);
    2864                 :          0 :                 if (!ep)
    2865                 :            :                         return -EINVAL;
    2866                 :            : 
    2867                 :          0 :                 ev->r.retcode = transport->ep_poll(ep,
    2868                 :          0 :                                                    ev->u.ep_poll.timeout_ms);
    2869                 :          0 :                 break;
    2870                 :            :         case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
    2871                 :          0 :                 rc = iscsi_if_ep_disconnect(transport,
    2872                 :            :                                             ev->u.ep_disconnect.ep_handle);
    2873                 :          0 :                 break;
    2874                 :            :         }
    2875                 :          0 :         return rc;
    2876                 :            : }
    2877                 :            : 
    2878                 :            : static int
    2879                 :          0 : iscsi_tgt_dscvr(struct iscsi_transport *transport,
    2880                 :            :                 struct iscsi_uevent *ev)
    2881                 :            : {
    2882                 :            :         struct Scsi_Host *shost;
    2883                 :            :         struct sockaddr *dst_addr;
    2884                 :            :         int err;
    2885                 :            : 
    2886                 :          0 :         if (!transport->tgt_dscvr)
    2887                 :            :                 return -EINVAL;
    2888                 :            : 
    2889                 :          0 :         shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
    2890                 :          0 :         if (!shost) {
    2891                 :          0 :                 printk(KERN_ERR "target discovery could not find host no %u\n",
    2892                 :            :                        ev->u.tgt_dscvr.host_no);
    2893                 :          0 :                 return -ENODEV;
    2894                 :            :         }
    2895                 :            : 
    2896                 :            : 
    2897                 :          0 :         dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
    2898                 :          0 :         err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
    2899                 :            :                                    ev->u.tgt_dscvr.enable, dst_addr);
    2900                 :          0 :         scsi_host_put(shost);
    2901                 :          0 :         return err;
    2902                 :            : }
    2903                 :            : 
    2904                 :            : static int
    2905                 :          0 : iscsi_set_host_param(struct iscsi_transport *transport,
    2906                 :            :                      struct iscsi_uevent *ev)
    2907                 :            : {
    2908                 :          0 :         char *data = (char*)ev + sizeof(*ev);
    2909                 :            :         struct Scsi_Host *shost;
    2910                 :            :         int err;
    2911                 :            : 
    2912                 :          0 :         if (!transport->set_host_param)
    2913                 :            :                 return -ENOSYS;
    2914                 :            : 
    2915                 :          0 :         shost = scsi_host_lookup(ev->u.set_host_param.host_no);
    2916                 :          0 :         if (!shost) {
    2917                 :          0 :                 printk(KERN_ERR "set_host_param could not find host no %u\n",
    2918                 :            :                        ev->u.set_host_param.host_no);
    2919                 :          0 :                 return -ENODEV;
    2920                 :            :         }
    2921                 :            : 
    2922                 :          0 :         err = transport->set_host_param(shost, ev->u.set_host_param.param,
    2923                 :          0 :                                         data, ev->u.set_host_param.len);
    2924                 :          0 :         scsi_host_put(shost);
    2925                 :          0 :         return err;
    2926                 :            : }
    2927                 :            : 
    2928                 :            : static int
    2929                 :          0 : iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
    2930                 :            : {
    2931                 :            :         struct Scsi_Host *shost;
    2932                 :            :         struct iscsi_path *params;
    2933                 :            :         int err;
    2934                 :            : 
    2935                 :          0 :         if (!transport->set_path)
    2936                 :            :                 return -ENOSYS;
    2937                 :            : 
    2938                 :          0 :         shost = scsi_host_lookup(ev->u.set_path.host_no);
    2939                 :          0 :         if (!shost) {
    2940                 :          0 :                 printk(KERN_ERR "set path could not find host no %u\n",
    2941                 :            :                        ev->u.set_path.host_no);
    2942                 :          0 :                 return -ENODEV;
    2943                 :            :         }
    2944                 :            : 
    2945                 :          0 :         params = (struct iscsi_path *)((char *)ev + sizeof(*ev));
    2946                 :          0 :         err = transport->set_path(shost, params);
    2947                 :            : 
    2948                 :          0 :         scsi_host_put(shost);
    2949                 :          0 :         return err;
    2950                 :            : }
    2951                 :            : 
    2952                 :          0 : static int iscsi_session_has_conns(int sid)
    2953                 :            : {
    2954                 :            :         struct iscsi_cls_conn *conn;
    2955                 :            :         unsigned long flags;
    2956                 :            :         int found = 0;
    2957                 :            : 
    2958                 :          0 :         spin_lock_irqsave(&connlock, flags);
    2959                 :          0 :         list_for_each_entry(conn, &connlist, conn_list) {
    2960                 :          0 :                 if (iscsi_conn_get_sid(conn) == sid) {
    2961                 :            :                         found = 1;
    2962                 :            :                         break;
    2963                 :            :                 }
    2964                 :            :         }
    2965                 :            :         spin_unlock_irqrestore(&connlock, flags);
    2966                 :            : 
    2967                 :          0 :         return found;
    2968                 :            : }
    2969                 :            : 
    2970                 :            : static int
    2971                 :          0 : iscsi_set_iface_params(struct iscsi_transport *transport,
    2972                 :            :                        struct iscsi_uevent *ev, uint32_t len)
    2973                 :            : {
    2974                 :          0 :         char *data = (char *)ev + sizeof(*ev);
    2975                 :            :         struct Scsi_Host *shost;
    2976                 :            :         int err;
    2977                 :            : 
    2978                 :          0 :         if (!transport->set_iface_param)
    2979                 :            :                 return -ENOSYS;
    2980                 :            : 
    2981                 :          0 :         shost = scsi_host_lookup(ev->u.set_iface_params.host_no);
    2982                 :          0 :         if (!shost) {
    2983                 :          0 :                 printk(KERN_ERR "set_iface_params could not find host no %u\n",
    2984                 :            :                        ev->u.set_iface_params.host_no);
    2985                 :          0 :                 return -ENODEV;
    2986                 :            :         }
    2987                 :            : 
    2988                 :          0 :         err = transport->set_iface_param(shost, data, len);
    2989                 :          0 :         scsi_host_put(shost);
    2990                 :          0 :         return err;
    2991                 :            : }
    2992                 :            : 
    2993                 :            : static int
    2994                 :          0 : iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev)
    2995                 :            : {
    2996                 :            :         struct Scsi_Host *shost;
    2997                 :            :         struct sockaddr *dst_addr;
    2998                 :            :         int err;
    2999                 :            : 
    3000                 :          0 :         if (!transport->send_ping)
    3001                 :            :                 return -ENOSYS;
    3002                 :            : 
    3003                 :          0 :         shost = scsi_host_lookup(ev->u.iscsi_ping.host_no);
    3004                 :          0 :         if (!shost) {
    3005                 :          0 :                 printk(KERN_ERR "iscsi_ping could not find host no %u\n",
    3006                 :            :                        ev->u.iscsi_ping.host_no);
    3007                 :          0 :                 return -ENODEV;
    3008                 :            :         }
    3009                 :            : 
    3010                 :          0 :         dst_addr = (struct sockaddr *)((char *)ev + sizeof(*ev));
    3011                 :          0 :         err = transport->send_ping(shost, ev->u.iscsi_ping.iface_num,
    3012                 :            :                                    ev->u.iscsi_ping.iface_type,
    3013                 :            :                                    ev->u.iscsi_ping.payload_size,
    3014                 :            :                                    ev->u.iscsi_ping.pid,
    3015                 :            :                                    dst_addr);
    3016                 :          0 :         scsi_host_put(shost);
    3017                 :          0 :         return err;
    3018                 :            : }
    3019                 :            : 
    3020                 :            : static int
    3021                 :          0 : iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
    3022                 :            : {
    3023                 :            :         struct iscsi_uevent *ev = nlmsg_data(nlh);
    3024                 :            :         struct Scsi_Host *shost = NULL;
    3025                 :            :         struct iscsi_chap_rec *chap_rec;
    3026                 :            :         struct iscsi_internal *priv;
    3027                 :            :         struct sk_buff *skbchap;
    3028                 :            :         struct nlmsghdr *nlhchap;
    3029                 :            :         struct iscsi_uevent *evchap;
    3030                 :            :         uint32_t chap_buf_size;
    3031                 :            :         int len, err = 0;
    3032                 :            :         char *buf;
    3033                 :            : 
    3034                 :          0 :         if (!transport->get_chap)
    3035                 :            :                 return -EINVAL;
    3036                 :            : 
    3037                 :          0 :         priv = iscsi_if_transport_lookup(transport);
    3038                 :          0 :         if (!priv)
    3039                 :            :                 return -EINVAL;
    3040                 :            : 
    3041                 :          0 :         chap_buf_size = (ev->u.get_chap.num_entries * sizeof(*chap_rec));
    3042                 :          0 :         len = nlmsg_total_size(sizeof(*ev) + chap_buf_size);
    3043                 :            : 
    3044                 :          0 :         shost = scsi_host_lookup(ev->u.get_chap.host_no);
    3045                 :          0 :         if (!shost) {
    3046                 :          0 :                 printk(KERN_ERR "%s: failed. Could not find host no %u\n",
    3047                 :            :                        __func__, ev->u.get_chap.host_no);
    3048                 :          0 :                 return -ENODEV;
    3049                 :            :         }
    3050                 :            : 
    3051                 :            :         do {
    3052                 :            :                 int actual_size;
    3053                 :            : 
    3054                 :          0 :                 skbchap = alloc_skb(len, GFP_KERNEL);
    3055                 :          0 :                 if (!skbchap) {
    3056                 :          0 :                         printk(KERN_ERR "can not deliver chap: OOM\n");
    3057                 :            :                         err = -ENOMEM;
    3058                 :          0 :                         goto exit_get_chap;
    3059                 :            :                 }
    3060                 :            : 
    3061                 :          0 :                 nlhchap = __nlmsg_put(skbchap, 0, 0, 0,
    3062                 :          0 :                                       (len - sizeof(*nlhchap)), 0);
    3063                 :            :                 evchap = nlmsg_data(nlhchap);
    3064                 :          0 :                 memset(evchap, 0, sizeof(*evchap));
    3065                 :          0 :                 evchap->transport_handle = iscsi_handle(transport);
    3066                 :          0 :                 evchap->type = nlh->nlmsg_type;
    3067                 :          0 :                 evchap->u.get_chap.host_no = ev->u.get_chap.host_no;
    3068                 :          0 :                 evchap->u.get_chap.chap_tbl_idx = ev->u.get_chap.chap_tbl_idx;
    3069                 :          0 :                 evchap->u.get_chap.num_entries = ev->u.get_chap.num_entries;
    3070                 :          0 :                 buf = (char *)evchap + sizeof(*evchap);
    3071                 :          0 :                 memset(buf, 0, chap_buf_size);
    3072                 :            : 
    3073                 :          0 :                 err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx,
    3074                 :            :                                     &evchap->u.get_chap.num_entries, buf);
    3075                 :            : 
    3076                 :            :                 actual_size = nlmsg_total_size(sizeof(*ev) + chap_buf_size);
    3077                 :          0 :                 skb_trim(skbchap, NLMSG_ALIGN(actual_size));
    3078                 :          0 :                 nlhchap->nlmsg_len = actual_size;
    3079                 :            : 
    3080                 :          0 :                 err = iscsi_multicast_skb(skbchap, ISCSI_NL_GRP_ISCSID,
    3081                 :            :                                           GFP_KERNEL);
    3082                 :          0 :         } while (err < 0 && err != -ECONNREFUSED);
    3083                 :            : 
    3084                 :            : exit_get_chap:
    3085                 :          0 :         scsi_host_put(shost);
    3086                 :          0 :         return err;
    3087                 :            : }
    3088                 :            : 
    3089                 :          0 : static int iscsi_set_chap(struct iscsi_transport *transport,
    3090                 :            :                           struct iscsi_uevent *ev, uint32_t len)
    3091                 :            : {
    3092                 :          0 :         char *data = (char *)ev + sizeof(*ev);
    3093                 :            :         struct Scsi_Host *shost;
    3094                 :            :         int err = 0;
    3095                 :            : 
    3096                 :          0 :         if (!transport->set_chap)
    3097                 :            :                 return -ENOSYS;
    3098                 :            : 
    3099                 :          0 :         shost = scsi_host_lookup(ev->u.set_path.host_no);
    3100                 :          0 :         if (!shost) {
    3101                 :          0 :                 pr_err("%s could not find host no %u\n",
    3102                 :            :                        __func__, ev->u.set_path.host_no);
    3103                 :          0 :                 return -ENODEV;
    3104                 :            :         }
    3105                 :            : 
    3106                 :          0 :         err = transport->set_chap(shost, data, len);
    3107                 :          0 :         scsi_host_put(shost);
    3108                 :          0 :         return err;
    3109                 :            : }
    3110                 :            : 
    3111                 :          0 : static int iscsi_delete_chap(struct iscsi_transport *transport,
    3112                 :            :                              struct iscsi_uevent *ev)
    3113                 :            : {
    3114                 :            :         struct Scsi_Host *shost;
    3115                 :            :         int err = 0;
    3116                 :            : 
    3117                 :          0 :         if (!transport->delete_chap)
    3118                 :            :                 return -ENOSYS;
    3119                 :            : 
    3120                 :          0 :         shost = scsi_host_lookup(ev->u.delete_chap.host_no);
    3121                 :          0 :         if (!shost) {
    3122                 :          0 :                 printk(KERN_ERR "%s could not find host no %u\n",
    3123                 :            :                        __func__, ev->u.delete_chap.host_no);
    3124                 :          0 :                 return -ENODEV;
    3125                 :            :         }
    3126                 :            : 
    3127                 :          0 :         err = transport->delete_chap(shost, ev->u.delete_chap.chap_tbl_idx);
    3128                 :          0 :         scsi_host_put(shost);
    3129                 :          0 :         return err;
    3130                 :            : }
    3131                 :            : 
    3132                 :            : static const struct {
    3133                 :            :         enum iscsi_discovery_parent_type value;
    3134                 :            :         char                            *name;
    3135                 :            : } iscsi_discovery_parent_names[] = {
    3136                 :            :         {ISCSI_DISC_PARENT_UNKNOWN,     "Unknown" },
    3137                 :            :         {ISCSI_DISC_PARENT_SENDTGT,     "Sendtarget" },
    3138                 :            :         {ISCSI_DISC_PARENT_ISNS,        "isns" },
    3139                 :            : };
    3140                 :            : 
    3141                 :          0 : char *iscsi_get_discovery_parent_name(int parent_type)
    3142                 :            : {
    3143                 :            :         int i;
    3144                 :            :         char *state = "Unknown!";
    3145                 :            : 
    3146                 :          0 :         for (i = 0; i < ARRAY_SIZE(iscsi_discovery_parent_names); i++) {
    3147                 :          0 :                 if (iscsi_discovery_parent_names[i].value & parent_type) {
    3148                 :          0 :                         state = iscsi_discovery_parent_names[i].name;
    3149                 :          0 :                         break;
    3150                 :            :                 }
    3151                 :            :         }
    3152                 :          0 :         return state;
    3153                 :            : }
    3154                 :            : EXPORT_SYMBOL_GPL(iscsi_get_discovery_parent_name);
    3155                 :            : 
    3156                 :          0 : static int iscsi_set_flashnode_param(struct iscsi_transport *transport,
    3157                 :            :                                      struct iscsi_uevent *ev, uint32_t len)
    3158                 :            : {
    3159                 :          0 :         char *data = (char *)ev + sizeof(*ev);
    3160                 :            :         struct Scsi_Host *shost;
    3161                 :            :         struct iscsi_bus_flash_session *fnode_sess;
    3162                 :            :         struct iscsi_bus_flash_conn *fnode_conn;
    3163                 :            :         struct device *dev;
    3164                 :            :         uint32_t idx;
    3165                 :            :         int err = 0;
    3166                 :            : 
    3167                 :          0 :         if (!transport->set_flashnode_param) {
    3168                 :            :                 err = -ENOSYS;
    3169                 :            :                 goto exit_set_fnode;
    3170                 :            :         }
    3171                 :            : 
    3172                 :          0 :         shost = scsi_host_lookup(ev->u.set_flashnode.host_no);
    3173                 :          0 :         if (!shost) {
    3174                 :          0 :                 pr_err("%s could not find host no %u\n",
    3175                 :            :                        __func__, ev->u.set_flashnode.host_no);
    3176                 :            :                 err = -ENODEV;
    3177                 :          0 :                 goto put_host;
    3178                 :            :         }
    3179                 :            : 
    3180                 :          0 :         idx = ev->u.set_flashnode.flashnode_idx;
    3181                 :            :         fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
    3182                 :          0 :         if (!fnode_sess) {
    3183                 :          0 :                 pr_err("%s could not find flashnode %u for host no %u\n",
    3184                 :            :                        __func__, idx, ev->u.set_flashnode.host_no);
    3185                 :            :                 err = -ENODEV;
    3186                 :          0 :                 goto put_host;
    3187                 :            :         }
    3188                 :            : 
    3189                 :            :         dev = iscsi_find_flashnode_conn(fnode_sess);
    3190                 :          0 :         if (!dev) {
    3191                 :            :                 err = -ENODEV;
    3192                 :            :                 goto put_sess;
    3193                 :            :         }
    3194                 :            : 
    3195                 :          0 :         fnode_conn = iscsi_dev_to_flash_conn(dev);
    3196                 :          0 :         err = transport->set_flashnode_param(fnode_sess, fnode_conn, data, len);
    3197                 :          0 :         put_device(dev);
    3198                 :            : 
    3199                 :            : put_sess:
    3200                 :          0 :         put_device(&fnode_sess->dev);
    3201                 :            : 
    3202                 :            : put_host:
    3203                 :          0 :         scsi_host_put(shost);
    3204                 :            : 
    3205                 :            : exit_set_fnode:
    3206                 :          0 :         return err;
    3207                 :            : }
    3208                 :            : 
    3209                 :          0 : static int iscsi_new_flashnode(struct iscsi_transport *transport,
    3210                 :            :                                struct iscsi_uevent *ev, uint32_t len)
    3211                 :            : {
    3212                 :          0 :         char *data = (char *)ev + sizeof(*ev);
    3213                 :            :         struct Scsi_Host *shost;
    3214                 :            :         int index;
    3215                 :            :         int err = 0;
    3216                 :            : 
    3217                 :          0 :         if (!transport->new_flashnode) {
    3218                 :            :                 err = -ENOSYS;
    3219                 :            :                 goto exit_new_fnode;
    3220                 :            :         }
    3221                 :            : 
    3222                 :          0 :         shost = scsi_host_lookup(ev->u.new_flashnode.host_no);
    3223                 :          0 :         if (!shost) {
    3224                 :          0 :                 pr_err("%s could not find host no %u\n",
    3225                 :            :                        __func__, ev->u.new_flashnode.host_no);
    3226                 :            :                 err = -ENODEV;
    3227                 :          0 :                 goto put_host;
    3228                 :            :         }
    3229                 :            : 
    3230                 :          0 :         index = transport->new_flashnode(shost, data, len);
    3231                 :            : 
    3232                 :          0 :         if (index >= 0)
    3233                 :          0 :                 ev->r.new_flashnode_ret.flashnode_idx = index;
    3234                 :            :         else
    3235                 :            :                 err = -EIO;
    3236                 :            : 
    3237                 :            : put_host:
    3238                 :          0 :         scsi_host_put(shost);
    3239                 :            : 
    3240                 :            : exit_new_fnode:
    3241                 :          0 :         return err;
    3242                 :            : }
    3243                 :            : 
    3244                 :          0 : static int iscsi_del_flashnode(struct iscsi_transport *transport,
    3245                 :            :                                struct iscsi_uevent *ev)
    3246                 :            : {
    3247                 :            :         struct Scsi_Host *shost;
    3248                 :            :         struct iscsi_bus_flash_session *fnode_sess;
    3249                 :            :         uint32_t idx;
    3250                 :            :         int err = 0;
    3251                 :            : 
    3252                 :          0 :         if (!transport->del_flashnode) {
    3253                 :            :                 err = -ENOSYS;
    3254                 :            :                 goto exit_del_fnode;
    3255                 :            :         }
    3256                 :            : 
    3257                 :          0 :         shost = scsi_host_lookup(ev->u.del_flashnode.host_no);
    3258                 :          0 :         if (!shost) {
    3259                 :          0 :                 pr_err("%s could not find host no %u\n",
    3260                 :            :                        __func__, ev->u.del_flashnode.host_no);
    3261                 :            :                 err = -ENODEV;
    3262                 :          0 :                 goto put_host;
    3263                 :            :         }
    3264                 :            : 
    3265                 :          0 :         idx = ev->u.del_flashnode.flashnode_idx;
    3266                 :            :         fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
    3267                 :          0 :         if (!fnode_sess) {
    3268                 :          0 :                 pr_err("%s could not find flashnode %u for host no %u\n",
    3269                 :            :                        __func__, idx, ev->u.del_flashnode.host_no);
    3270                 :            :                 err = -ENODEV;
    3271                 :          0 :                 goto put_host;
    3272                 :            :         }
    3273                 :            : 
    3274                 :          0 :         err = transport->del_flashnode(fnode_sess);
    3275                 :          0 :         put_device(&fnode_sess->dev);
    3276                 :            : 
    3277                 :            : put_host:
    3278                 :          0 :         scsi_host_put(shost);
    3279                 :            : 
    3280                 :            : exit_del_fnode:
    3281                 :          0 :         return err;
    3282                 :            : }
    3283                 :            : 
    3284                 :          0 : static int iscsi_login_flashnode(struct iscsi_transport *transport,
    3285                 :            :                                  struct iscsi_uevent *ev)
    3286                 :            : {
    3287                 :            :         struct Scsi_Host *shost;
    3288                 :            :         struct iscsi_bus_flash_session *fnode_sess;
    3289                 :            :         struct iscsi_bus_flash_conn *fnode_conn;
    3290                 :            :         struct device *dev;
    3291                 :            :         uint32_t idx;
    3292                 :            :         int err = 0;
    3293                 :            : 
    3294                 :          0 :         if (!transport->login_flashnode) {
    3295                 :            :                 err = -ENOSYS;
    3296                 :            :                 goto exit_login_fnode;
    3297                 :            :         }
    3298                 :            : 
    3299                 :          0 :         shost = scsi_host_lookup(ev->u.login_flashnode.host_no);
    3300                 :          0 :         if (!shost) {
    3301                 :          0 :                 pr_err("%s could not find host no %u\n",
    3302                 :            :                        __func__, ev->u.login_flashnode.host_no);
    3303                 :            :                 err = -ENODEV;
    3304                 :          0 :                 goto put_host;
    3305                 :            :         }
    3306                 :            : 
    3307                 :          0 :         idx = ev->u.login_flashnode.flashnode_idx;
    3308                 :            :         fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
    3309                 :          0 :         if (!fnode_sess) {
    3310                 :          0 :                 pr_err("%s could not find flashnode %u for host no %u\n",
    3311                 :            :                        __func__, idx, ev->u.login_flashnode.host_no);
    3312                 :            :                 err = -ENODEV;
    3313                 :          0 :                 goto put_host;
    3314                 :            :         }
    3315                 :            : 
    3316                 :            :         dev = iscsi_find_flashnode_conn(fnode_sess);
    3317                 :          0 :         if (!dev) {
    3318                 :            :                 err = -ENODEV;
    3319                 :            :                 goto put_sess;
    3320                 :            :         }
    3321                 :            : 
    3322                 :          0 :         fnode_conn = iscsi_dev_to_flash_conn(dev);
    3323                 :          0 :         err = transport->login_flashnode(fnode_sess, fnode_conn);
    3324                 :          0 :         put_device(dev);
    3325                 :            : 
    3326                 :            : put_sess:
    3327                 :          0 :         put_device(&fnode_sess->dev);
    3328                 :            : 
    3329                 :            : put_host:
    3330                 :          0 :         scsi_host_put(shost);
    3331                 :            : 
    3332                 :            : exit_login_fnode:
    3333                 :          0 :         return err;
    3334                 :            : }
    3335                 :            : 
    3336                 :          0 : static int iscsi_logout_flashnode(struct iscsi_transport *transport,
    3337                 :            :                                   struct iscsi_uevent *ev)
    3338                 :            : {
    3339                 :            :         struct Scsi_Host *shost;
    3340                 :            :         struct iscsi_bus_flash_session *fnode_sess;
    3341                 :            :         struct iscsi_bus_flash_conn *fnode_conn;
    3342                 :            :         struct device *dev;
    3343                 :            :         uint32_t idx;
    3344                 :            :         int err = 0;
    3345                 :            : 
    3346                 :          0 :         if (!transport->logout_flashnode) {
    3347                 :            :                 err = -ENOSYS;
    3348                 :            :                 goto exit_logout_fnode;
    3349                 :            :         }
    3350                 :            : 
    3351                 :          0 :         shost = scsi_host_lookup(ev->u.logout_flashnode.host_no);
    3352                 :          0 :         if (!shost) {
    3353                 :          0 :                 pr_err("%s could not find host no %u\n",
    3354                 :            :                        __func__, ev->u.logout_flashnode.host_no);
    3355                 :            :                 err = -ENODEV;
    3356                 :          0 :                 goto put_host;
    3357                 :            :         }
    3358                 :            : 
    3359                 :          0 :         idx = ev->u.logout_flashnode.flashnode_idx;
    3360                 :            :         fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
    3361                 :          0 :         if (!fnode_sess) {
    3362                 :          0 :                 pr_err("%s could not find flashnode %u for host no %u\n",
    3363                 :            :                        __func__, idx, ev->u.logout_flashnode.host_no);
    3364                 :            :                 err = -ENODEV;
    3365                 :          0 :                 goto put_host;
    3366                 :            :         }
    3367                 :            : 
    3368                 :            :         dev = iscsi_find_flashnode_conn(fnode_sess);
    3369                 :          0 :         if (!dev) {
    3370                 :            :                 err = -ENODEV;
    3371                 :            :                 goto put_sess;
    3372                 :            :         }
    3373                 :            : 
    3374                 :          0 :         fnode_conn = iscsi_dev_to_flash_conn(dev);
    3375                 :            : 
    3376                 :          0 :         err = transport->logout_flashnode(fnode_sess, fnode_conn);
    3377                 :          0 :         put_device(dev);
    3378                 :            : 
    3379                 :            : put_sess:
    3380                 :          0 :         put_device(&fnode_sess->dev);
    3381                 :            : 
    3382                 :            : put_host:
    3383                 :          0 :         scsi_host_put(shost);
    3384                 :            : 
    3385                 :            : exit_logout_fnode:
    3386                 :          0 :         return err;
    3387                 :            : }
    3388                 :            : 
    3389                 :          0 : static int iscsi_logout_flashnode_sid(struct iscsi_transport *transport,
    3390                 :            :                                       struct iscsi_uevent *ev)
    3391                 :            : {
    3392                 :            :         struct Scsi_Host *shost;
    3393                 :            :         struct iscsi_cls_session *session;
    3394                 :            :         int err = 0;
    3395                 :            : 
    3396                 :          0 :         if (!transport->logout_flashnode_sid) {
    3397                 :            :                 err = -ENOSYS;
    3398                 :            :                 goto exit_logout_sid;
    3399                 :            :         }
    3400                 :            : 
    3401                 :          0 :         shost = scsi_host_lookup(ev->u.logout_flashnode_sid.host_no);
    3402                 :          0 :         if (!shost) {
    3403                 :          0 :                 pr_err("%s could not find host no %u\n",
    3404                 :            :                        __func__, ev->u.logout_flashnode.host_no);
    3405                 :            :                 err = -ENODEV;
    3406                 :          0 :                 goto put_host;
    3407                 :            :         }
    3408                 :            : 
    3409                 :          0 :         session = iscsi_session_lookup(ev->u.logout_flashnode_sid.sid);
    3410                 :          0 :         if (!session) {
    3411                 :          0 :                 pr_err("%s could not find session id %u\n",
    3412                 :            :                        __func__, ev->u.logout_flashnode_sid.sid);
    3413                 :            :                 err = -EINVAL;
    3414                 :          0 :                 goto put_host;
    3415                 :            :         }
    3416                 :            : 
    3417                 :          0 :         err = transport->logout_flashnode_sid(session);
    3418                 :            : 
    3419                 :            : put_host:
    3420                 :          0 :         scsi_host_put(shost);
    3421                 :            : 
    3422                 :            : exit_logout_sid:
    3423                 :          0 :         return err;
    3424                 :            : }
    3425                 :            : 
    3426                 :            : static int
    3427                 :          0 : iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
    3428                 :            : {
    3429                 :            :         struct iscsi_uevent *ev = nlmsg_data(nlh);
    3430                 :            :         struct Scsi_Host *shost = NULL;
    3431                 :            :         struct iscsi_internal *priv;
    3432                 :            :         struct sk_buff *skbhost_stats;
    3433                 :            :         struct nlmsghdr *nlhhost_stats;
    3434                 :            :         struct iscsi_uevent *evhost_stats;
    3435                 :            :         int host_stats_size = 0;
    3436                 :            :         int len, err = 0;
    3437                 :            :         char *buf;
    3438                 :            : 
    3439                 :          0 :         if (!transport->get_host_stats)
    3440                 :            :                 return -ENOSYS;
    3441                 :            : 
    3442                 :          0 :         priv = iscsi_if_transport_lookup(transport);
    3443                 :          0 :         if (!priv)
    3444                 :            :                 return -EINVAL;
    3445                 :            : 
    3446                 :            :         host_stats_size = sizeof(struct iscsi_offload_host_stats);
    3447                 :            :         len = nlmsg_total_size(sizeof(*ev) + host_stats_size);
    3448                 :            : 
    3449                 :          0 :         shost = scsi_host_lookup(ev->u.get_host_stats.host_no);
    3450                 :          0 :         if (!shost) {
    3451                 :          0 :                 pr_err("%s: failed. Could not find host no %u\n",
    3452                 :            :                        __func__, ev->u.get_host_stats.host_no);
    3453                 :          0 :                 return -ENODEV;
    3454                 :            :         }
    3455                 :            : 
    3456                 :            :         do {
    3457                 :            :                 int actual_size;
    3458                 :            : 
    3459                 :            :                 skbhost_stats = alloc_skb(len, GFP_KERNEL);
    3460                 :          0 :                 if (!skbhost_stats) {
    3461                 :          0 :                         pr_err("cannot deliver host stats: OOM\n");
    3462                 :            :                         err = -ENOMEM;
    3463                 :          0 :                         goto exit_host_stats;
    3464                 :            :                 }
    3465                 :            : 
    3466                 :          0 :                 nlhhost_stats = __nlmsg_put(skbhost_stats, 0, 0, 0,
    3467                 :            :                                       (len - sizeof(*nlhhost_stats)), 0);
    3468                 :            :                 evhost_stats = nlmsg_data(nlhhost_stats);
    3469                 :          0 :                 memset(evhost_stats, 0, sizeof(*evhost_stats));
    3470                 :          0 :                 evhost_stats->transport_handle = iscsi_handle(transport);
    3471                 :          0 :                 evhost_stats->type = nlh->nlmsg_type;
    3472                 :          0 :                 evhost_stats->u.get_host_stats.host_no =
    3473                 :          0 :                                         ev->u.get_host_stats.host_no;
    3474                 :          0 :                 buf = (char *)evhost_stats + sizeof(*evhost_stats);
    3475                 :          0 :                 memset(buf, 0, host_stats_size);
    3476                 :            : 
    3477                 :          0 :                 err = transport->get_host_stats(shost, buf, host_stats_size);
    3478                 :          0 :                 if (err) {
    3479                 :          0 :                         kfree_skb(skbhost_stats);
    3480                 :          0 :                         goto exit_host_stats;
    3481                 :            :                 }
    3482                 :            : 
    3483                 :            :                 actual_size = nlmsg_total_size(sizeof(*ev) + host_stats_size);
    3484                 :          0 :                 skb_trim(skbhost_stats, NLMSG_ALIGN(actual_size));
    3485                 :          0 :                 nlhhost_stats->nlmsg_len = actual_size;
    3486                 :            : 
    3487                 :          0 :                 err = iscsi_multicast_skb(skbhost_stats, ISCSI_NL_GRP_ISCSID,
    3488                 :            :                                           GFP_KERNEL);
    3489                 :          0 :         } while (err < 0 && err != -ECONNREFUSED);
    3490                 :            : 
    3491                 :            : exit_host_stats:
    3492                 :          0 :         scsi_host_put(shost);
    3493                 :          0 :         return err;
    3494                 :            : }
    3495                 :            : 
    3496                 :            : 
    3497                 :            : static int
    3498                 :          0 : iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
    3499                 :            : {
    3500                 :            :         int err = 0;
    3501                 :            :         u32 portid;
    3502                 :            :         struct iscsi_uevent *ev = nlmsg_data(nlh);
    3503                 :            :         struct iscsi_transport *transport = NULL;
    3504                 :            :         struct iscsi_internal *priv;
    3505                 :            :         struct iscsi_cls_session *session;
    3506                 :            :         struct iscsi_cls_conn *conn;
    3507                 :            :         struct iscsi_endpoint *ep = NULL;
    3508                 :            : 
    3509                 :          0 :         if (nlh->nlmsg_type == ISCSI_UEVENT_PATH_UPDATE)
    3510                 :          0 :                 *group = ISCSI_NL_GRP_UIP;
    3511                 :            :         else
    3512                 :          0 :                 *group = ISCSI_NL_GRP_ISCSID;
    3513                 :            : 
    3514                 :          0 :         priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
    3515                 :          0 :         if (!priv)
    3516                 :            :                 return -EINVAL;
    3517                 :          0 :         transport = priv->iscsi_transport;
    3518                 :            : 
    3519                 :          0 :         if (!try_module_get(transport->owner))
    3520                 :            :                 return -EINVAL;
    3521                 :            : 
    3522                 :          0 :         portid = NETLINK_CB(skb).portid;
    3523                 :            : 
    3524                 :          0 :         switch (nlh->nlmsg_type) {
    3525                 :            :         case ISCSI_UEVENT_CREATE_SESSION:
    3526                 :          0 :                 err = iscsi_if_create_session(priv, ep, ev,
    3527                 :            :                                               portid,
    3528                 :            :                                               ev->u.c_session.initial_cmdsn,
    3529                 :            :                                               ev->u.c_session.cmds_max,
    3530                 :            :                                               ev->u.c_session.queue_depth);
    3531                 :          0 :                 break;
    3532                 :            :         case ISCSI_UEVENT_CREATE_BOUND_SESSION:
    3533                 :          0 :                 ep = iscsi_lookup_endpoint(ev->u.c_bound_session.ep_handle);
    3534                 :          0 :                 if (!ep) {
    3535                 :            :                         err = -EINVAL;
    3536                 :            :                         break;
    3537                 :            :                 }
    3538                 :            : 
    3539                 :          0 :                 err = iscsi_if_create_session(priv, ep, ev,
    3540                 :            :                                         portid,
    3541                 :            :                                         ev->u.c_bound_session.initial_cmdsn,
    3542                 :            :                                         ev->u.c_bound_session.cmds_max,
    3543                 :            :                                         ev->u.c_bound_session.queue_depth);
    3544                 :          0 :                 break;
    3545                 :            :         case ISCSI_UEVENT_DESTROY_SESSION:
    3546                 :          0 :                 session = iscsi_session_lookup(ev->u.d_session.sid);
    3547                 :          0 :                 if (!session)
    3548                 :            :                         err = -EINVAL;
    3549                 :          0 :                 else if (iscsi_session_has_conns(ev->u.d_session.sid))
    3550                 :            :                         err = -EBUSY;
    3551                 :            :                 else
    3552                 :          0 :                         transport->destroy_session(session);
    3553                 :            :                 break;
    3554                 :            :         case ISCSI_UEVENT_UNBIND_SESSION:
    3555                 :          0 :                 session = iscsi_session_lookup(ev->u.d_session.sid);
    3556                 :          0 :                 if (session)
    3557                 :          0 :                         scsi_queue_work(iscsi_session_to_shost(session),
    3558                 :            :                                         &session->unbind_work);
    3559                 :            :                 else
    3560                 :            :                         err = -EINVAL;
    3561                 :            :                 break;
    3562                 :            :         case ISCSI_UEVENT_CREATE_CONN:
    3563                 :          0 :                 err = iscsi_if_create_conn(transport, ev);
    3564                 :          0 :                 break;
    3565                 :            :         case ISCSI_UEVENT_DESTROY_CONN:
    3566                 :          0 :                 err = iscsi_if_destroy_conn(transport, ev);
    3567                 :          0 :                 break;
    3568                 :            :         case ISCSI_UEVENT_BIND_CONN:
    3569                 :          0 :                 session = iscsi_session_lookup(ev->u.b_conn.sid);
    3570                 :          0 :                 conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
    3571                 :            : 
    3572                 :          0 :                 if (conn && conn->ep)
    3573                 :          0 :                         iscsi_if_ep_disconnect(transport, conn->ep->id);
    3574                 :            : 
    3575                 :          0 :                 if (!session || !conn) {
    3576                 :            :                         err = -EINVAL;
    3577                 :            :                         break;
    3578                 :            :                 }
    3579                 :            : 
    3580                 :          0 :                 ev->r.retcode =      transport->bind_conn(session, conn,
    3581                 :            :                                                 ev->u.b_conn.transport_eph,
    3582                 :          0 :                                                 ev->u.b_conn.is_leading);
    3583                 :          0 :                 if (ev->r.retcode || !transport->ep_connect)
    3584                 :            :                         break;
    3585                 :            : 
    3586                 :          0 :                 ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
    3587                 :          0 :                 if (ep) {
    3588                 :          0 :                         ep->conn = conn;
    3589                 :            : 
    3590                 :          0 :                         mutex_lock(&conn->ep_mutex);
    3591                 :          0 :                         conn->ep = ep;
    3592                 :          0 :                         mutex_unlock(&conn->ep_mutex);
    3593                 :            :                 } else
    3594                 :          0 :                         iscsi_cls_conn_printk(KERN_ERR, conn,
    3595                 :            :                                               "Could not set ep conn "
    3596                 :            :                                               "binding\n");
    3597                 :            :                 break;
    3598                 :            :         case ISCSI_UEVENT_SET_PARAM:
    3599                 :          0 :                 err = iscsi_set_param(transport, ev);
    3600                 :          0 :                 break;
    3601                 :            :         case ISCSI_UEVENT_START_CONN:
    3602                 :          0 :                 conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
    3603                 :          0 :                 if (conn)
    3604                 :          0 :                         ev->r.retcode = transport->start_conn(conn);
    3605                 :            :                 else
    3606                 :            :                         err = -EINVAL;
    3607                 :            :                 break;
    3608                 :            :         case ISCSI_UEVENT_STOP_CONN:
    3609                 :          0 :                 conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
    3610                 :          0 :                 if (conn)
    3611                 :          0 :                         transport->stop_conn(conn, ev->u.stop_conn.flag);
    3612                 :            :                 else
    3613                 :            :                         err = -EINVAL;
    3614                 :            :                 break;
    3615                 :            :         case ISCSI_UEVENT_SEND_PDU:
    3616                 :          0 :                 conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
    3617                 :          0 :                 if (conn)
    3618                 :          0 :                         ev->r.retcode =      transport->send_pdu(conn,
    3619                 :            :                                 (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
    3620                 :          0 :                                 (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
    3621                 :            :                                 ev->u.send_pdu.data_size);
    3622                 :            :                 else
    3623                 :            :                         err = -EINVAL;
    3624                 :            :                 break;
    3625                 :            :         case ISCSI_UEVENT_GET_STATS:
    3626                 :          0 :                 err = iscsi_if_get_stats(transport, nlh);
    3627                 :          0 :                 break;
    3628                 :            :         case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
    3629                 :            :         case ISCSI_UEVENT_TRANSPORT_EP_POLL:
    3630                 :            :         case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
    3631                 :            :         case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
    3632                 :          0 :                 err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
    3633                 :          0 :                 break;
    3634                 :            :         case ISCSI_UEVENT_TGT_DSCVR:
    3635                 :          0 :                 err = iscsi_tgt_dscvr(transport, ev);
    3636                 :          0 :                 break;
    3637                 :            :         case ISCSI_UEVENT_SET_HOST_PARAM:
    3638                 :          0 :                 err = iscsi_set_host_param(transport, ev);
    3639                 :          0 :                 break;
    3640                 :            :         case ISCSI_UEVENT_PATH_UPDATE:
    3641                 :          0 :                 err = iscsi_set_path(transport, ev);
    3642                 :          0 :                 break;
    3643                 :            :         case ISCSI_UEVENT_SET_IFACE_PARAMS:
    3644                 :          0 :                 err = iscsi_set_iface_params(transport, ev,
    3645                 :            :                                              nlmsg_attrlen(nlh, sizeof(*ev)));
    3646                 :          0 :                 break;
    3647                 :            :         case ISCSI_UEVENT_PING:
    3648                 :          0 :                 err = iscsi_send_ping(transport, ev);
    3649                 :          0 :                 break;
    3650                 :            :         case ISCSI_UEVENT_GET_CHAP:
    3651                 :          0 :                 err = iscsi_get_chap(transport, nlh);
    3652                 :          0 :                 break;
    3653                 :            :         case ISCSI_UEVENT_DELETE_CHAP:
    3654                 :          0 :                 err = iscsi_delete_chap(transport, ev);
    3655                 :          0 :                 break;
    3656                 :            :         case ISCSI_UEVENT_SET_FLASHNODE_PARAMS:
    3657                 :          0 :                 err = iscsi_set_flashnode_param(transport, ev,
    3658                 :            :                                                 nlmsg_attrlen(nlh,
    3659                 :            :                                                               sizeof(*ev)));
    3660                 :          0 :                 break;
    3661                 :            :         case ISCSI_UEVENT_NEW_FLASHNODE:
    3662                 :          0 :                 err = iscsi_new_flashnode(transport, ev,
    3663                 :            :                                           nlmsg_attrlen(nlh, sizeof(*ev)));
    3664                 :          0 :                 break;
    3665                 :            :         case ISCSI_UEVENT_DEL_FLASHNODE:
    3666                 :          0 :                 err = iscsi_del_flashnode(transport, ev);
    3667                 :          0 :                 break;
    3668                 :            :         case ISCSI_UEVENT_LOGIN_FLASHNODE:
    3669                 :          0 :                 err = iscsi_login_flashnode(transport, ev);
    3670                 :          0 :                 break;
    3671                 :            :         case ISCSI_UEVENT_LOGOUT_FLASHNODE:
    3672                 :          0 :                 err = iscsi_logout_flashnode(transport, ev);
    3673                 :          0 :                 break;
    3674                 :            :         case ISCSI_UEVENT_LOGOUT_FLASHNODE_SID:
    3675                 :          0 :                 err = iscsi_logout_flashnode_sid(transport, ev);
    3676                 :          0 :                 break;
    3677                 :            :         case ISCSI_UEVENT_SET_CHAP:
    3678                 :          0 :                 err = iscsi_set_chap(transport, ev,
    3679                 :            :                                      nlmsg_attrlen(nlh, sizeof(*ev)));
    3680                 :          0 :                 break;
    3681                 :            :         case ISCSI_UEVENT_GET_HOST_STATS:
    3682                 :          0 :                 err = iscsi_get_host_stats(transport, nlh);
    3683                 :          0 :                 break;
    3684                 :            :         default:
    3685                 :            :                 err = -ENOSYS;
    3686                 :            :                 break;
    3687                 :            :         }
    3688                 :            : 
    3689                 :          0 :         module_put(transport->owner);
    3690                 :          0 :         return err;
    3691                 :            : }
    3692                 :            : 
    3693                 :            : /*
    3694                 :            :  * Get message from skb.  Each message is processed by iscsi_if_recv_msg.
    3695                 :            :  * Malformed skbs with wrong lengths or invalid creds are not processed.
    3696                 :            :  */
    3697                 :            : static void
    3698                 :          0 : iscsi_if_rx(struct sk_buff *skb)
    3699                 :            : {
    3700                 :          0 :         u32 portid = NETLINK_CB(skb).portid;
    3701                 :            : 
    3702                 :          0 :         mutex_lock(&rx_queue_mutex);
    3703                 :          0 :         while (skb->len >= NLMSG_HDRLEN) {
    3704                 :            :                 int err;
    3705                 :            :                 uint32_t rlen;
    3706                 :            :                 struct nlmsghdr *nlh;
    3707                 :            :                 struct iscsi_uevent *ev;
    3708                 :            :                 uint32_t group;
    3709                 :            :                 int retries = ISCSI_SEND_MAX_ALLOWED;
    3710                 :            : 
    3711                 :            :                 nlh = nlmsg_hdr(skb);
    3712                 :          0 :                 if (nlh->nlmsg_len < sizeof(*nlh) + sizeof(*ev) ||
    3713                 :            :                     skb->len < nlh->nlmsg_len) {
    3714                 :            :                         break;
    3715                 :            :                 }
    3716                 :            : 
    3717                 :            :                 ev = nlmsg_data(nlh);
    3718                 :          0 :                 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
    3719                 :          0 :                 if (rlen > skb->len)
    3720                 :            :                         rlen = skb->len;
    3721                 :            : 
    3722                 :          0 :                 err = iscsi_if_recv_msg(skb, nlh, &group);
    3723                 :          0 :                 if (err) {
    3724                 :          0 :                         ev->type = ISCSI_KEVENT_IF_ERROR;
    3725                 :          0 :                         ev->iferror = err;
    3726                 :            :                 }
    3727                 :            :                 do {
    3728                 :            :                         /*
    3729                 :            :                          * special case for GET_STATS:
    3730                 :            :                          * on success - sending reply and stats from
    3731                 :            :                          * inside of if_recv_msg(),
    3732                 :            :                          * on error - fall through.
    3733                 :            :                          */
    3734                 :          0 :                         if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
    3735                 :            :                                 break;
    3736                 :          0 :                         if (ev->type == ISCSI_UEVENT_GET_CHAP && !err)
    3737                 :            :                                 break;
    3738                 :          0 :                         err = iscsi_if_send_reply(portid, nlh->nlmsg_type,
    3739                 :            :                                                   ev, sizeof(*ev));
    3740                 :          0 :                         if (err == -EAGAIN && --retries < 0) {
    3741                 :          0 :                                 printk(KERN_WARNING "Send reply failed, error %d\n", err);
    3742                 :          0 :                                 break;
    3743                 :            :                         }
    3744                 :          0 :                 } while (err < 0 && err != -ECONNREFUSED && err != -ESRCH);
    3745                 :          0 :                 skb_pull(skb, rlen);
    3746                 :            :         }
    3747                 :          0 :         mutex_unlock(&rx_queue_mutex);
    3748                 :          0 : }
    3749                 :            : 
    3750                 :            : #define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store)              \
    3751                 :            : struct device_attribute dev_attr_##_prefix##_##_name =  \
    3752                 :            :         __ATTR(_name,_mode,_show,_store)
    3753                 :            : 
    3754                 :            : /*
    3755                 :            :  * iSCSI connection attrs
    3756                 :            :  */
    3757                 :            : #define iscsi_conn_attr_show(param)                                     \
    3758                 :            : static ssize_t                                                          \
    3759                 :            : show_conn_param_##param(struct device *dev,                             \
    3760                 :            :                         struct device_attribute *attr, char *buf)       \
    3761                 :            : {                                                                       \
    3762                 :            :         struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);        \
    3763                 :            :         struct iscsi_transport *t = conn->transport;                 \
    3764                 :            :         return t->get_conn_param(conn, param, buf);                  \
    3765                 :            : }
    3766                 :            : 
    3767                 :            : #define iscsi_conn_attr(field, param)                                   \
    3768                 :            :         iscsi_conn_attr_show(param)                                     \
    3769                 :            : static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param,  \
    3770                 :            :                         NULL);
    3771                 :            : 
    3772                 :          0 : iscsi_conn_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
    3773                 :          0 : iscsi_conn_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
    3774                 :          0 : iscsi_conn_attr(header_digest, ISCSI_PARAM_HDRDGST_EN);
    3775                 :          0 : iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
    3776                 :          0 : iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
    3777                 :          0 : iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
    3778                 :          0 : iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
    3779                 :          0 : iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
    3780                 :          0 : iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
    3781                 :          0 : iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
    3782                 :          0 : iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
    3783                 :          0 : iscsi_conn_attr(local_port, ISCSI_PARAM_LOCAL_PORT);
    3784                 :          0 : iscsi_conn_attr(statsn, ISCSI_PARAM_STATSN);
    3785                 :          0 : iscsi_conn_attr(keepalive_tmo, ISCSI_PARAM_KEEPALIVE_TMO);
    3786                 :          0 : iscsi_conn_attr(max_segment_size, ISCSI_PARAM_MAX_SEGMENT_SIZE);
    3787                 :          0 : iscsi_conn_attr(tcp_timestamp_stat, ISCSI_PARAM_TCP_TIMESTAMP_STAT);
    3788                 :          0 : iscsi_conn_attr(tcp_wsf_disable, ISCSI_PARAM_TCP_WSF_DISABLE);
    3789                 :          0 : iscsi_conn_attr(tcp_nagle_disable, ISCSI_PARAM_TCP_NAGLE_DISABLE);
    3790                 :          0 : iscsi_conn_attr(tcp_timer_scale, ISCSI_PARAM_TCP_TIMER_SCALE);
    3791                 :          0 : iscsi_conn_attr(tcp_timestamp_enable, ISCSI_PARAM_TCP_TIMESTAMP_EN);
    3792                 :          0 : iscsi_conn_attr(fragment_disable, ISCSI_PARAM_IP_FRAGMENT_DISABLE);
    3793                 :          0 : iscsi_conn_attr(ipv4_tos, ISCSI_PARAM_IPV4_TOS);
    3794                 :          0 : iscsi_conn_attr(ipv6_traffic_class, ISCSI_PARAM_IPV6_TC);
    3795                 :          0 : iscsi_conn_attr(ipv6_flow_label, ISCSI_PARAM_IPV6_FLOW_LABEL);
    3796                 :          0 : iscsi_conn_attr(is_fw_assigned_ipv6, ISCSI_PARAM_IS_FW_ASSIGNED_IPV6);
    3797                 :          0 : iscsi_conn_attr(tcp_xmit_wsf, ISCSI_PARAM_TCP_XMIT_WSF);
    3798                 :          0 : iscsi_conn_attr(tcp_recv_wsf, ISCSI_PARAM_TCP_RECV_WSF);
    3799                 :          0 : iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR);
    3800                 :            : 
    3801                 :            : 
    3802                 :            : #define iscsi_conn_ep_attr_show(param)                                  \
    3803                 :            : static ssize_t show_conn_ep_param_##param(struct device *dev,           \
    3804                 :            :                                           struct device_attribute *attr,\
    3805                 :            :                                           char *buf)                    \
    3806                 :            : {                                                                       \
    3807                 :            :         struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);        \
    3808                 :            :         struct iscsi_transport *t = conn->transport;                 \
    3809                 :            :         struct iscsi_endpoint *ep;                                      \
    3810                 :            :         ssize_t rc;                                                     \
    3811                 :            :                                                                         \
    3812                 :            :         /*                                                              \
    3813                 :            :          * Need to make sure ep_disconnect does not free the LLD's      \
    3814                 :            :          * interconnect resources while we are trying to read them.     \
    3815                 :            :          */                                                             \
    3816                 :            :         mutex_lock(&conn->ep_mutex);                                     \
    3817                 :            :         ep = conn->ep;                                                       \
    3818                 :            :         if (!ep && t->ep_connect) {                                  \
    3819                 :            :                 mutex_unlock(&conn->ep_mutex);                           \
    3820                 :            :                 return -ENOTCONN;                                       \
    3821                 :            :         }                                                               \
    3822                 :            :                                                                         \
    3823                 :            :         if (ep)                                                         \
    3824                 :            :                 rc = t->get_ep_param(ep, param, buf);                        \
    3825                 :            :         else                                                            \
    3826                 :            :                 rc = t->get_conn_param(conn, param, buf);            \
    3827                 :            :         mutex_unlock(&conn->ep_mutex);                                   \
    3828                 :            :         return rc;                                                      \
    3829                 :            : }
    3830                 :            : 
    3831                 :            : #define iscsi_conn_ep_attr(field, param)                                \
    3832                 :            :         iscsi_conn_ep_attr_show(param)                                  \
    3833                 :            : static ISCSI_CLASS_ATTR(conn, field, S_IRUGO,                           \
    3834                 :            :                         show_conn_ep_param_##param, NULL);
    3835                 :            : 
    3836                 :          0 : iscsi_conn_ep_attr(address, ISCSI_PARAM_CONN_ADDRESS);
    3837                 :          0 : iscsi_conn_ep_attr(port, ISCSI_PARAM_CONN_PORT);
    3838                 :            : 
    3839                 :            : static struct attribute *iscsi_conn_attrs[] = {
    3840                 :            :         &dev_attr_conn_max_recv_dlength.attr,
    3841                 :            :         &dev_attr_conn_max_xmit_dlength.attr,
    3842                 :            :         &dev_attr_conn_header_digest.attr,
    3843                 :            :         &dev_attr_conn_data_digest.attr,
    3844                 :            :         &dev_attr_conn_ifmarker.attr,
    3845                 :            :         &dev_attr_conn_ofmarker.attr,
    3846                 :            :         &dev_attr_conn_address.attr,
    3847                 :            :         &dev_attr_conn_port.attr,
    3848                 :            :         &dev_attr_conn_exp_statsn.attr,
    3849                 :            :         &dev_attr_conn_persistent_address.attr,
    3850                 :            :         &dev_attr_conn_persistent_port.attr,
    3851                 :            :         &dev_attr_conn_ping_tmo.attr,
    3852                 :            :         &dev_attr_conn_recv_tmo.attr,
    3853                 :            :         &dev_attr_conn_local_port.attr,
    3854                 :            :         &dev_attr_conn_statsn.attr,
    3855                 :            :         &dev_attr_conn_keepalive_tmo.attr,
    3856                 :            :         &dev_attr_conn_max_segment_size.attr,
    3857                 :            :         &dev_attr_conn_tcp_timestamp_stat.attr,
    3858                 :            :         &dev_attr_conn_tcp_wsf_disable.attr,
    3859                 :            :         &dev_attr_conn_tcp_nagle_disable.attr,
    3860                 :            :         &dev_attr_conn_tcp_timer_scale.attr,
    3861                 :            :         &dev_attr_conn_tcp_timestamp_enable.attr,
    3862                 :            :         &dev_attr_conn_fragment_disable.attr,
    3863                 :            :         &dev_attr_conn_ipv4_tos.attr,
    3864                 :            :         &dev_attr_conn_ipv6_traffic_class.attr,
    3865                 :            :         &dev_attr_conn_ipv6_flow_label.attr,
    3866                 :            :         &dev_attr_conn_is_fw_assigned_ipv6.attr,
    3867                 :            :         &dev_attr_conn_tcp_xmit_wsf.attr,
    3868                 :            :         &dev_attr_conn_tcp_recv_wsf.attr,
    3869                 :            :         &dev_attr_conn_local_ipaddr.attr,
    3870                 :            :         NULL,
    3871                 :            : };
    3872                 :            : 
    3873                 :          0 : static umode_t iscsi_conn_attr_is_visible(struct kobject *kobj,
    3874                 :            :                                          struct attribute *attr, int i)
    3875                 :            : {
    3876                 :            :         struct device *cdev = container_of(kobj, struct device, kobj);
    3877                 :          0 :         struct iscsi_cls_conn *conn = transport_class_to_conn(cdev);
    3878                 :          0 :         struct iscsi_transport *t = conn->transport;
    3879                 :            :         int param;
    3880                 :            : 
    3881                 :          0 :         if (attr == &dev_attr_conn_max_recv_dlength.attr)
    3882                 :            :                 param = ISCSI_PARAM_MAX_RECV_DLENGTH;
    3883                 :          0 :         else if (attr == &dev_attr_conn_max_xmit_dlength.attr)
    3884                 :            :                 param = ISCSI_PARAM_MAX_XMIT_DLENGTH;
    3885                 :          0 :         else if (attr == &dev_attr_conn_header_digest.attr)
    3886                 :            :                 param = ISCSI_PARAM_HDRDGST_EN;
    3887                 :          0 :         else if (attr == &dev_attr_conn_data_digest.attr)
    3888                 :            :                 param = ISCSI_PARAM_DATADGST_EN;
    3889                 :          0 :         else if (attr == &dev_attr_conn_ifmarker.attr)
    3890                 :            :                 param = ISCSI_PARAM_IFMARKER_EN;
    3891                 :          0 :         else if (attr == &dev_attr_conn_ofmarker.attr)
    3892                 :            :                 param = ISCSI_PARAM_OFMARKER_EN;
    3893                 :          0 :         else if (attr == &dev_attr_conn_address.attr)
    3894                 :            :                 param = ISCSI_PARAM_CONN_ADDRESS;
    3895                 :          0 :         else if (attr == &dev_attr_conn_port.attr)
    3896                 :            :                 param = ISCSI_PARAM_CONN_PORT;
    3897                 :          0 :         else if (attr == &dev_attr_conn_exp_statsn.attr)
    3898                 :            :                 param = ISCSI_PARAM_EXP_STATSN;
    3899                 :          0 :         else if (attr == &dev_attr_conn_persistent_address.attr)
    3900                 :            :                 param = ISCSI_PARAM_PERSISTENT_ADDRESS;
    3901                 :          0 :         else if (attr == &dev_attr_conn_persistent_port.attr)
    3902                 :            :                 param = ISCSI_PARAM_PERSISTENT_PORT;
    3903                 :          0 :         else if (attr == &dev_attr_conn_ping_tmo.attr)
    3904                 :            :                 param = ISCSI_PARAM_PING_TMO;
    3905                 :          0 :         else if (attr == &dev_attr_conn_recv_tmo.attr)
    3906                 :            :                 param = ISCSI_PARAM_RECV_TMO;
    3907                 :          0 :         else if (attr == &dev_attr_conn_local_port.attr)
    3908                 :            :                 param = ISCSI_PARAM_LOCAL_PORT;
    3909                 :          0 :         else if (attr == &dev_attr_conn_statsn.attr)
    3910                 :            :                 param = ISCSI_PARAM_STATSN;
    3911                 :          0 :         else if (attr == &dev_attr_conn_keepalive_tmo.attr)
    3912                 :            :                 param = ISCSI_PARAM_KEEPALIVE_TMO;
    3913                 :          0 :         else if (attr == &dev_attr_conn_max_segment_size.attr)
    3914                 :            :                 param = ISCSI_PARAM_MAX_SEGMENT_SIZE;
    3915                 :          0 :         else if (attr == &dev_attr_conn_tcp_timestamp_stat.attr)
    3916                 :            :                 param = ISCSI_PARAM_TCP_TIMESTAMP_STAT;
    3917                 :          0 :         else if (attr == &dev_attr_conn_tcp_wsf_disable.attr)
    3918                 :            :                 param = ISCSI_PARAM_TCP_WSF_DISABLE;
    3919                 :          0 :         else if (attr == &dev_attr_conn_tcp_nagle_disable.attr)
    3920                 :            :                 param = ISCSI_PARAM_TCP_NAGLE_DISABLE;
    3921                 :          0 :         else if (attr == &dev_attr_conn_tcp_timer_scale.attr)
    3922                 :            :                 param = ISCSI_PARAM_TCP_TIMER_SCALE;
    3923                 :          0 :         else if (attr == &dev_attr_conn_tcp_timestamp_enable.attr)
    3924                 :            :                 param = ISCSI_PARAM_TCP_TIMESTAMP_EN;
    3925                 :          0 :         else if (attr == &dev_attr_conn_fragment_disable.attr)
    3926                 :            :                 param = ISCSI_PARAM_IP_FRAGMENT_DISABLE;
    3927                 :          0 :         else if (attr == &dev_attr_conn_ipv4_tos.attr)
    3928                 :            :                 param = ISCSI_PARAM_IPV4_TOS;
    3929                 :          0 :         else if (attr == &dev_attr_conn_ipv6_traffic_class.attr)
    3930                 :            :                 param = ISCSI_PARAM_IPV6_TC;
    3931                 :          0 :         else if (attr == &dev_attr_conn_ipv6_flow_label.attr)
    3932                 :            :                 param = ISCSI_PARAM_IPV6_FLOW_LABEL;
    3933                 :          0 :         else if (attr == &dev_attr_conn_is_fw_assigned_ipv6.attr)
    3934                 :            :                 param = ISCSI_PARAM_IS_FW_ASSIGNED_IPV6;
    3935                 :          0 :         else if (attr == &dev_attr_conn_tcp_xmit_wsf.attr)
    3936                 :            :                 param = ISCSI_PARAM_TCP_XMIT_WSF;
    3937                 :          0 :         else if (attr == &dev_attr_conn_tcp_recv_wsf.attr)
    3938                 :            :                 param = ISCSI_PARAM_TCP_RECV_WSF;
    3939                 :          0 :         else if (attr == &dev_attr_conn_local_ipaddr.attr)
    3940                 :            :                 param = ISCSI_PARAM_LOCAL_IPADDR;
    3941                 :            :         else {
    3942                 :          0 :                 WARN_ONCE(1, "Invalid conn attr");
    3943                 :            :                 return 0;
    3944                 :            :         }
    3945                 :            : 
    3946                 :          0 :         return t->attr_is_visible(ISCSI_PARAM, param);
    3947                 :            : }
    3948                 :            : 
    3949                 :            : static struct attribute_group iscsi_conn_group = {
    3950                 :            :         .attrs = iscsi_conn_attrs,
    3951                 :            :         .is_visible = iscsi_conn_attr_is_visible,
    3952                 :            : };
    3953                 :            : 
    3954                 :            : /*
    3955                 :            :  * iSCSI session attrs
    3956                 :            :  */
    3957                 :            : #define iscsi_session_attr_show(param, perm)                            \
    3958                 :            : static ssize_t                                                          \
    3959                 :            : show_session_param_##param(struct device *dev,                          \
    3960                 :            :                            struct device_attribute *attr, char *buf)    \
    3961                 :            : {                                                                       \
    3962                 :            :         struct iscsi_cls_session *session =                             \
    3963                 :            :                 iscsi_dev_to_session(dev->parent);                   \
    3964                 :            :         struct iscsi_transport *t = session->transport;                      \
    3965                 :            :                                                                         \
    3966                 :            :         if (perm && !capable(CAP_SYS_ADMIN))                            \
    3967                 :            :                 return -EACCES;                                         \
    3968                 :            :         return t->get_session_param(session, param, buf);            \
    3969                 :            : }
    3970                 :            : 
    3971                 :            : #define iscsi_session_attr(field, param, perm)                          \
    3972                 :            :         iscsi_session_attr_show(param, perm)                            \
    3973                 :            : static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
    3974                 :            :                         NULL);
    3975                 :          0 : iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
    3976                 :          0 : iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
    3977                 :          0 : iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
    3978                 :          0 : iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
    3979                 :          0 : iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
    3980                 :          0 : iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
    3981                 :          0 : iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
    3982                 :          0 : iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
    3983                 :          0 : iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
    3984                 :          0 : iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
    3985                 :          0 : iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
    3986                 :          0 : iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
    3987                 :          0 : iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
    3988                 :          0 : iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
    3989                 :          0 : iscsi_session_attr(chap_out_idx, ISCSI_PARAM_CHAP_OUT_IDX, 1);
    3990                 :          0 : iscsi_session_attr(chap_in_idx, ISCSI_PARAM_CHAP_IN_IDX, 1);
    3991                 :          0 : iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
    3992                 :          0 : iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
    3993                 :          0 : iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
    3994                 :          0 : iscsi_session_attr(tgt_reset_tmo, ISCSI_PARAM_TGT_RESET_TMO, 0);
    3995                 :          0 : iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0);
    3996                 :          0 : iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0);
    3997                 :          0 : iscsi_session_attr(targetalias, ISCSI_PARAM_TARGET_ALIAS, 0);
    3998                 :          0 : iscsi_session_attr(boot_root, ISCSI_PARAM_BOOT_ROOT, 0);
    3999                 :          0 : iscsi_session_attr(boot_nic, ISCSI_PARAM_BOOT_NIC, 0);
    4000                 :          0 : iscsi_session_attr(boot_target, ISCSI_PARAM_BOOT_TARGET, 0);
    4001                 :          0 : iscsi_session_attr(auto_snd_tgt_disable, ISCSI_PARAM_AUTO_SND_TGT_DISABLE, 0);
    4002                 :          0 : iscsi_session_attr(discovery_session, ISCSI_PARAM_DISCOVERY_SESS, 0);
    4003                 :          0 : iscsi_session_attr(portal_type, ISCSI_PARAM_PORTAL_TYPE, 0);
    4004                 :          0 : iscsi_session_attr(chap_auth, ISCSI_PARAM_CHAP_AUTH_EN, 0);
    4005                 :          0 : iscsi_session_attr(discovery_logout, ISCSI_PARAM_DISCOVERY_LOGOUT_EN, 0);
    4006                 :          0 : iscsi_session_attr(bidi_chap, ISCSI_PARAM_BIDI_CHAP_EN, 0);
    4007                 :          0 : iscsi_session_attr(discovery_auth_optional,
    4008                 :            :                    ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL, 0);
    4009                 :          0 : iscsi_session_attr(def_time2wait, ISCSI_PARAM_DEF_TIME2WAIT, 0);
    4010                 :          0 : iscsi_session_attr(def_time2retain, ISCSI_PARAM_DEF_TIME2RETAIN, 0);
    4011                 :          0 : iscsi_session_attr(isid, ISCSI_PARAM_ISID, 0);
    4012                 :          0 : iscsi_session_attr(tsid, ISCSI_PARAM_TSID, 0);
    4013                 :          0 : iscsi_session_attr(def_taskmgmt_tmo, ISCSI_PARAM_DEF_TASKMGMT_TMO, 0);
    4014                 :          0 : iscsi_session_attr(discovery_parent_idx, ISCSI_PARAM_DISCOVERY_PARENT_IDX, 0);
    4015                 :          0 : iscsi_session_attr(discovery_parent_type, ISCSI_PARAM_DISCOVERY_PARENT_TYPE, 0);
    4016                 :            : 
    4017                 :            : static ssize_t
    4018                 :          0 : show_priv_session_state(struct device *dev, struct device_attribute *attr,
    4019                 :            :                         char *buf)
    4020                 :            : {
    4021                 :          0 :         struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
    4022                 :          0 :         return sprintf(buf, "%s\n", iscsi_session_state_name(session->state));
    4023                 :            : }
    4024                 :            : static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
    4025                 :            :                         NULL);
    4026                 :            : static ssize_t
    4027                 :          0 : show_priv_session_creator(struct device *dev, struct device_attribute *attr,
    4028                 :            :                         char *buf)
    4029                 :            : {
    4030                 :          0 :         struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
    4031                 :          0 :         return sprintf(buf, "%d\n", session->creator);
    4032                 :            : }
    4033                 :            : static ISCSI_CLASS_ATTR(priv_sess, creator, S_IRUGO, show_priv_session_creator,
    4034                 :            :                         NULL);
    4035                 :            : static ssize_t
    4036                 :          0 : show_priv_session_target_id(struct device *dev, struct device_attribute *attr,
    4037                 :            :                             char *buf)
    4038                 :            : {
    4039                 :          0 :         struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
    4040                 :          0 :         return sprintf(buf, "%d\n", session->target_id);
    4041                 :            : }
    4042                 :            : static ISCSI_CLASS_ATTR(priv_sess, target_id, S_IRUGO,
    4043                 :            :                         show_priv_session_target_id, NULL);
    4044                 :            : 
    4045                 :            : #define iscsi_priv_session_attr_show(field, format)                     \
    4046                 :            : static ssize_t                                                          \
    4047                 :            : show_priv_session_##field(struct device *dev,                           \
    4048                 :            :                           struct device_attribute *attr, char *buf)     \
    4049                 :            : {                                                                       \
    4050                 :            :         struct iscsi_cls_session *session =                             \
    4051                 :            :                         iscsi_dev_to_session(dev->parent);           \
    4052                 :            :         if (session->field == -1)                                    \
    4053                 :            :                 return sprintf(buf, "off\n");                         \
    4054                 :            :         return sprintf(buf, format"\n", session->field);           \
    4055                 :            : }
    4056                 :            : 
    4057                 :            : #define iscsi_priv_session_attr_store(field)                            \
    4058                 :            : static ssize_t                                                          \
    4059                 :            : store_priv_session_##field(struct device *dev,                          \
    4060                 :            :                            struct device_attribute *attr,               \
    4061                 :            :                            const char *buf, size_t count)               \
    4062                 :            : {                                                                       \
    4063                 :            :         int val;                                                        \
    4064                 :            :         char *cp;                                                       \
    4065                 :            :         struct iscsi_cls_session *session =                             \
    4066                 :            :                 iscsi_dev_to_session(dev->parent);                   \
    4067                 :            :         if ((session->state == ISCSI_SESSION_FREE) ||                        \
    4068                 :            :             (session->state == ISCSI_SESSION_FAILED))                        \
    4069                 :            :                 return -EBUSY;                                          \
    4070                 :            :         if (strncmp(buf, "off", 3) == 0) {                            \
    4071                 :            :                 session->field = -1;                                 \
    4072                 :            :                 session->field##_sysfs_override = true;                      \
    4073                 :            :         } else {                                                        \
    4074                 :            :                 val = simple_strtoul(buf, &cp, 0);                  \
    4075                 :            :                 if (*cp != '\0' && *cp != '\n')                         \
    4076                 :            :                         return -EINVAL;                                 \
    4077                 :            :                 session->field = val;                                        \
    4078                 :            :                 session->field##_sysfs_override = true;                      \
    4079                 :            :         }                                                               \
    4080                 :            :         return count;                                                   \
    4081                 :            : }
    4082                 :            : 
    4083                 :            : #define iscsi_priv_session_rw_attr(field, format)                       \
    4084                 :            :         iscsi_priv_session_attr_show(field, format)                     \
    4085                 :            :         iscsi_priv_session_attr_store(field)                            \
    4086                 :            : static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR,            \
    4087                 :            :                         show_priv_session_##field,                      \
    4088                 :            :                         store_priv_session_##field)
    4089                 :            : 
    4090                 :          0 : iscsi_priv_session_rw_attr(recovery_tmo, "%d");
    4091                 :            : 
    4092                 :            : static struct attribute *iscsi_session_attrs[] = {
    4093                 :            :         &dev_attr_sess_initial_r2t.attr,
    4094                 :            :         &dev_attr_sess_max_outstanding_r2t.attr,
    4095                 :            :         &dev_attr_sess_immediate_data.attr,
    4096                 :            :         &dev_attr_sess_first_burst_len.attr,
    4097                 :            :         &dev_attr_sess_max_burst_len.attr,
    4098                 :            :         &dev_attr_sess_data_pdu_in_order.attr,
    4099                 :            :         &dev_attr_sess_data_seq_in_order.attr,
    4100                 :            :         &dev_attr_sess_erl.attr,
    4101                 :            :         &dev_attr_sess_targetname.attr,
    4102                 :            :         &dev_attr_sess_tpgt.attr,
    4103                 :            :         &dev_attr_sess_password.attr,
    4104                 :            :         &dev_attr_sess_password_in.attr,
    4105                 :            :         &dev_attr_sess_username.attr,
    4106                 :            :         &dev_attr_sess_username_in.attr,
    4107                 :            :         &dev_attr_sess_fast_abort.attr,
    4108                 :            :         &dev_attr_sess_abort_tmo.attr,
    4109                 :            :         &dev_attr_sess_lu_reset_tmo.attr,
    4110                 :            :         &dev_attr_sess_tgt_reset_tmo.attr,
    4111                 :            :         &dev_attr_sess_ifacename.attr,
    4112                 :            :         &dev_attr_sess_initiatorname.attr,
    4113                 :            :         &dev_attr_sess_targetalias.attr,
    4114                 :            :         &dev_attr_sess_boot_root.attr,
    4115                 :            :         &dev_attr_sess_boot_nic.attr,
    4116                 :            :         &dev_attr_sess_boot_target.attr,
    4117                 :            :         &dev_attr_priv_sess_recovery_tmo.attr,
    4118                 :            :         &dev_attr_priv_sess_state.attr,
    4119                 :            :         &dev_attr_priv_sess_creator.attr,
    4120                 :            :         &dev_attr_sess_chap_out_idx.attr,
    4121                 :            :         &dev_attr_sess_chap_in_idx.attr,
    4122                 :            :         &dev_attr_priv_sess_target_id.attr,
    4123                 :            :         &dev_attr_sess_auto_snd_tgt_disable.attr,
    4124                 :            :         &dev_attr_sess_discovery_session.attr,
    4125                 :            :         &dev_attr_sess_portal_type.attr,
    4126                 :            :         &dev_attr_sess_chap_auth.attr,
    4127                 :            :         &dev_attr_sess_discovery_logout.attr,
    4128                 :            :         &dev_attr_sess_bidi_chap.attr,
    4129                 :            :         &dev_attr_sess_discovery_auth_optional.attr,
    4130                 :            :         &dev_attr_sess_def_time2wait.attr,
    4131                 :            :         &dev_attr_sess_def_time2retain.attr,
    4132                 :            :         &dev_attr_sess_isid.attr,
    4133                 :            :         &dev_attr_sess_tsid.attr,
    4134                 :            :         &dev_attr_sess_def_taskmgmt_tmo.attr,
    4135                 :            :         &dev_attr_sess_discovery_parent_idx.attr,
    4136                 :            :         &dev_attr_sess_discovery_parent_type.attr,
    4137                 :            :         NULL,
    4138                 :            : };
    4139                 :            : 
    4140                 :          0 : static umode_t iscsi_session_attr_is_visible(struct kobject *kobj,
    4141                 :            :                                             struct attribute *attr, int i)
    4142                 :            : {
    4143                 :            :         struct device *cdev = container_of(kobj, struct device, kobj);
    4144                 :          0 :         struct iscsi_cls_session *session = transport_class_to_session(cdev);
    4145                 :          0 :         struct iscsi_transport *t = session->transport;
    4146                 :            :         int param;
    4147                 :            : 
    4148                 :          0 :         if (attr == &dev_attr_sess_initial_r2t.attr)
    4149                 :            :                 param = ISCSI_PARAM_INITIAL_R2T_EN;
    4150                 :          0 :         else if (attr == &dev_attr_sess_max_outstanding_r2t.attr)
    4151                 :            :                 param = ISCSI_PARAM_MAX_R2T;
    4152                 :          0 :         else if (attr == &dev_attr_sess_immediate_data.attr)
    4153                 :            :                 param = ISCSI_PARAM_IMM_DATA_EN;
    4154                 :          0 :         else if (attr == &dev_attr_sess_first_burst_len.attr)
    4155                 :            :                 param = ISCSI_PARAM_FIRST_BURST;
    4156                 :          0 :         else if (attr == &dev_attr_sess_max_burst_len.attr)
    4157                 :            :                 param = ISCSI_PARAM_MAX_BURST;
    4158                 :          0 :         else if (attr == &dev_attr_sess_data_pdu_in_order.attr)
    4159                 :            :                 param = ISCSI_PARAM_PDU_INORDER_EN;
    4160                 :          0 :         else if (attr == &dev_attr_sess_data_seq_in_order.attr)
    4161                 :            :                 param = ISCSI_PARAM_DATASEQ_INORDER_EN;
    4162                 :          0 :         else if (attr == &dev_attr_sess_erl.attr)
    4163                 :            :                 param = ISCSI_PARAM_ERL;
    4164                 :          0 :         else if (attr == &dev_attr_sess_targetname.attr)
    4165                 :            :                 param = ISCSI_PARAM_TARGET_NAME;
    4166                 :          0 :         else if (attr == &dev_attr_sess_tpgt.attr)
    4167                 :            :                 param = ISCSI_PARAM_TPGT;
    4168                 :          0 :         else if (attr == &dev_attr_sess_chap_in_idx.attr)
    4169                 :            :                 param = ISCSI_PARAM_CHAP_IN_IDX;
    4170                 :          0 :         else if (attr == &dev_attr_sess_chap_out_idx.attr)
    4171                 :            :                 param = ISCSI_PARAM_CHAP_OUT_IDX;
    4172                 :          0 :         else if (attr == &dev_attr_sess_password.attr)
    4173                 :            :                 param = ISCSI_PARAM_USERNAME;
    4174                 :          0 :         else if (attr == &dev_attr_sess_password_in.attr)
    4175                 :            :                 param = ISCSI_PARAM_USERNAME_IN;
    4176                 :          0 :         else if (attr == &dev_attr_sess_username.attr)
    4177                 :            :                 param = ISCSI_PARAM_PASSWORD;
    4178                 :          0 :         else if (attr == &dev_attr_sess_username_in.attr)
    4179                 :            :                 param = ISCSI_PARAM_PASSWORD_IN;
    4180                 :          0 :         else if (attr == &dev_attr_sess_fast_abort.attr)
    4181                 :            :                 param = ISCSI_PARAM_FAST_ABORT;
    4182                 :          0 :         else if (attr == &dev_attr_sess_abort_tmo.attr)
    4183                 :            :                 param = ISCSI_PARAM_ABORT_TMO;
    4184                 :          0 :         else if (attr == &dev_attr_sess_lu_reset_tmo.attr)
    4185                 :            :                 param = ISCSI_PARAM_LU_RESET_TMO;
    4186                 :          0 :         else if (attr == &dev_attr_sess_tgt_reset_tmo.attr)
    4187                 :            :                 param = ISCSI_PARAM_TGT_RESET_TMO;
    4188                 :          0 :         else if (attr == &dev_attr_sess_ifacename.attr)
    4189                 :            :                 param = ISCSI_PARAM_IFACE_NAME;
    4190                 :          0 :         else if (attr == &dev_attr_sess_initiatorname.attr)
    4191                 :            :                 param = ISCSI_PARAM_INITIATOR_NAME;
    4192                 :          0 :         else if (attr == &dev_attr_sess_targetalias.attr)
    4193                 :            :                 param = ISCSI_PARAM_TARGET_ALIAS;
    4194                 :          0 :         else if (attr == &dev_attr_sess_boot_root.attr)
    4195                 :            :                 param = ISCSI_PARAM_BOOT_ROOT;
    4196                 :          0 :         else if (attr == &dev_attr_sess_boot_nic.attr)
    4197                 :            :                 param = ISCSI_PARAM_BOOT_NIC;
    4198                 :          0 :         else if (attr == &dev_attr_sess_boot_target.attr)
    4199                 :            :                 param = ISCSI_PARAM_BOOT_TARGET;
    4200                 :          0 :         else if (attr == &dev_attr_sess_auto_snd_tgt_disable.attr)
    4201                 :            :                 param = ISCSI_PARAM_AUTO_SND_TGT_DISABLE;
    4202                 :          0 :         else if (attr == &dev_attr_sess_discovery_session.attr)
    4203                 :            :                 param = ISCSI_PARAM_DISCOVERY_SESS;
    4204                 :          0 :         else if (attr == &dev_attr_sess_portal_type.attr)
    4205                 :            :                 param = ISCSI_PARAM_PORTAL_TYPE;
    4206                 :          0 :         else if (attr == &dev_attr_sess_chap_auth.attr)
    4207                 :            :                 param = ISCSI_PARAM_CHAP_AUTH_EN;
    4208                 :          0 :         else if (attr == &dev_attr_sess_discovery_logout.attr)
    4209                 :            :                 param = ISCSI_PARAM_DISCOVERY_LOGOUT_EN;
    4210                 :          0 :         else if (attr == &dev_attr_sess_bidi_chap.attr)
    4211                 :            :                 param = ISCSI_PARAM_BIDI_CHAP_EN;
    4212                 :          0 :         else if (attr == &dev_attr_sess_discovery_auth_optional.attr)
    4213                 :            :                 param = ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL;
    4214                 :          0 :         else if (attr == &dev_attr_sess_def_time2wait.attr)
    4215                 :            :                 param = ISCSI_PARAM_DEF_TIME2WAIT;
    4216                 :          0 :         else if (attr == &dev_attr_sess_def_time2retain.attr)
    4217                 :            :                 param = ISCSI_PARAM_DEF_TIME2RETAIN;
    4218                 :          0 :         else if (attr == &dev_attr_sess_isid.attr)
    4219                 :            :                 param = ISCSI_PARAM_ISID;
    4220                 :          0 :         else if (attr == &dev_attr_sess_tsid.attr)
    4221                 :            :                 param = ISCSI_PARAM_TSID;
    4222                 :          0 :         else if (attr == &dev_attr_sess_def_taskmgmt_tmo.attr)
    4223                 :            :                 param = ISCSI_PARAM_DEF_TASKMGMT_TMO;
    4224                 :          0 :         else if (attr == &dev_attr_sess_discovery_parent_idx.attr)
    4225                 :            :                 param = ISCSI_PARAM_DISCOVERY_PARENT_IDX;
    4226                 :          0 :         else if (attr == &dev_attr_sess_discovery_parent_type.attr)
    4227                 :            :                 param = ISCSI_PARAM_DISCOVERY_PARENT_TYPE;
    4228                 :          0 :         else if (attr == &dev_attr_priv_sess_recovery_tmo.attr)
    4229                 :            :                 return S_IRUGO | S_IWUSR;
    4230                 :          0 :         else if (attr == &dev_attr_priv_sess_state.attr)
    4231                 :            :                 return S_IRUGO;
    4232                 :          0 :         else if (attr == &dev_attr_priv_sess_creator.attr)
    4233                 :            :                 return S_IRUGO;
    4234                 :          0 :         else if (attr == &dev_attr_priv_sess_target_id.attr)
    4235                 :            :                 return S_IRUGO;
    4236                 :            :         else {
    4237                 :          0 :                 WARN_ONCE(1, "Invalid session attr");
    4238                 :            :                 return 0;
    4239                 :            :         }
    4240                 :            : 
    4241                 :          0 :         return t->attr_is_visible(ISCSI_PARAM, param);
    4242                 :            : }
    4243                 :            : 
    4244                 :            : static struct attribute_group iscsi_session_group = {
    4245                 :            :         .attrs = iscsi_session_attrs,
    4246                 :            :         .is_visible = iscsi_session_attr_is_visible,
    4247                 :            : };
    4248                 :            : 
    4249                 :            : /*
    4250                 :            :  * iSCSI host attrs
    4251                 :            :  */
    4252                 :            : #define iscsi_host_attr_show(param)                                     \
    4253                 :            : static ssize_t                                                          \
    4254                 :            : show_host_param_##param(struct device *dev,                             \
    4255                 :            :                         struct device_attribute *attr, char *buf)       \
    4256                 :            : {                                                                       \
    4257                 :            :         struct Scsi_Host *shost = transport_class_to_shost(dev);        \
    4258                 :            :         struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
    4259                 :            :         return priv->iscsi_transport->get_host_param(shost, param, buf); \
    4260                 :            : }
    4261                 :            : 
    4262                 :            : #define iscsi_host_attr(field, param)                                   \
    4263                 :            :         iscsi_host_attr_show(param)                                     \
    4264                 :            : static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param,  \
    4265                 :            :                         NULL);
    4266                 :            : 
    4267                 :          0 : iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
    4268                 :          0 : iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
    4269                 :          0 : iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
    4270                 :          0 : iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
    4271                 :          0 : iscsi_host_attr(port_state, ISCSI_HOST_PARAM_PORT_STATE);
    4272                 :          0 : iscsi_host_attr(port_speed, ISCSI_HOST_PARAM_PORT_SPEED);
    4273                 :            : 
    4274                 :            : static struct attribute *iscsi_host_attrs[] = {
    4275                 :            :         &dev_attr_host_netdev.attr,
    4276                 :            :         &dev_attr_host_hwaddress.attr,
    4277                 :            :         &dev_attr_host_ipaddress.attr,
    4278                 :            :         &dev_attr_host_initiatorname.attr,
    4279                 :            :         &dev_attr_host_port_state.attr,
    4280                 :            :         &dev_attr_host_port_speed.attr,
    4281                 :            :         NULL,
    4282                 :            : };
    4283                 :            : 
    4284                 :          0 : static umode_t iscsi_host_attr_is_visible(struct kobject *kobj,
    4285                 :            :                                          struct attribute *attr, int i)
    4286                 :            : {
    4287                 :            :         struct device *cdev = container_of(kobj, struct device, kobj);
    4288                 :          0 :         struct Scsi_Host *shost = transport_class_to_shost(cdev);
    4289                 :          0 :         struct iscsi_internal *priv = to_iscsi_internal(shost->transportt);
    4290                 :            :         int param;
    4291                 :            : 
    4292                 :          0 :         if (attr == &dev_attr_host_netdev.attr)
    4293                 :            :                 param = ISCSI_HOST_PARAM_NETDEV_NAME;
    4294                 :          0 :         else if (attr == &dev_attr_host_hwaddress.attr)
    4295                 :            :                 param = ISCSI_HOST_PARAM_HWADDRESS;
    4296                 :          0 :         else if (attr == &dev_attr_host_ipaddress.attr)
    4297                 :            :                 param = ISCSI_HOST_PARAM_IPADDRESS;
    4298                 :          0 :         else if (attr == &dev_attr_host_initiatorname.attr)
    4299                 :            :                 param = ISCSI_HOST_PARAM_INITIATOR_NAME;
    4300                 :          0 :         else if (attr == &dev_attr_host_port_state.attr)
    4301                 :            :                 param = ISCSI_HOST_PARAM_PORT_STATE;
    4302                 :          0 :         else if (attr == &dev_attr_host_port_speed.attr)
    4303                 :            :                 param = ISCSI_HOST_PARAM_PORT_SPEED;
    4304                 :            :         else {
    4305                 :          0 :                 WARN_ONCE(1, "Invalid host attr");
    4306                 :            :                 return 0;
    4307                 :            :         }
    4308                 :            : 
    4309                 :          0 :         return priv->iscsi_transport->attr_is_visible(ISCSI_HOST_PARAM, param);
    4310                 :            : }
    4311                 :            : 
    4312                 :            : static struct attribute_group iscsi_host_group = {
    4313                 :            :         .attrs = iscsi_host_attrs,
    4314                 :            :         .is_visible = iscsi_host_attr_is_visible,
    4315                 :            : };
    4316                 :            : 
    4317                 :            : /* convert iscsi_port_speed values to ascii string name */
    4318                 :            : static const struct {
    4319                 :            :         enum iscsi_port_speed   value;
    4320                 :            :         char                    *name;
    4321                 :            : } iscsi_port_speed_names[] = {
    4322                 :            :         {ISCSI_PORT_SPEED_UNKNOWN,      "Unknown" },
    4323                 :            :         {ISCSI_PORT_SPEED_10MBPS,       "10 Mbps" },
    4324                 :            :         {ISCSI_PORT_SPEED_100MBPS,      "100 Mbps" },
    4325                 :            :         {ISCSI_PORT_SPEED_1GBPS,        "1 Gbps" },
    4326                 :            :         {ISCSI_PORT_SPEED_10GBPS,       "10 Gbps" },
    4327                 :            :         {ISCSI_PORT_SPEED_25GBPS,       "25 Gbps" },
    4328                 :            :         {ISCSI_PORT_SPEED_40GBPS,       "40 Gbps" },
    4329                 :            : };
    4330                 :            : 
    4331                 :          0 : char *iscsi_get_port_speed_name(struct Scsi_Host *shost)
    4332                 :            : {
    4333                 :            :         int i;
    4334                 :            :         char *speed = "Unknown!";
    4335                 :          0 :         struct iscsi_cls_host *ihost = shost->shost_data;
    4336                 :          0 :         uint32_t port_speed = ihost->port_speed;
    4337                 :            : 
    4338                 :          0 :         for (i = 0; i < ARRAY_SIZE(iscsi_port_speed_names); i++) {
    4339                 :          0 :                 if (iscsi_port_speed_names[i].value & port_speed) {
    4340                 :          0 :                         speed = iscsi_port_speed_names[i].name;
    4341                 :          0 :                         break;
    4342                 :            :                 }
    4343                 :            :         }
    4344                 :          0 :         return speed;
    4345                 :            : }
    4346                 :            : EXPORT_SYMBOL_GPL(iscsi_get_port_speed_name);
    4347                 :            : 
    4348                 :            : /* convert iscsi_port_state values to ascii string name */
    4349                 :            : static const struct {
    4350                 :            :         enum iscsi_port_state   value;
    4351                 :            :         char                    *name;
    4352                 :            : } iscsi_port_state_names[] = {
    4353                 :            :         {ISCSI_PORT_STATE_DOWN,         "LINK DOWN" },
    4354                 :            :         {ISCSI_PORT_STATE_UP,           "LINK UP" },
    4355                 :            : };
    4356                 :            : 
    4357                 :          0 : char *iscsi_get_port_state_name(struct Scsi_Host *shost)
    4358                 :            : {
    4359                 :            :         int i;
    4360                 :            :         char *state = "Unknown!";
    4361                 :          0 :         struct iscsi_cls_host *ihost = shost->shost_data;
    4362                 :          0 :         uint32_t port_state = ihost->port_state;
    4363                 :            : 
    4364                 :          0 :         for (i = 0; i < ARRAY_SIZE(iscsi_port_state_names); i++) {
    4365                 :          0 :                 if (iscsi_port_state_names[i].value & port_state) {
    4366                 :          0 :                         state = iscsi_port_state_names[i].name;
    4367                 :          0 :                         break;
    4368                 :            :                 }
    4369                 :            :         }
    4370                 :          0 :         return state;
    4371                 :            : }
    4372                 :            : EXPORT_SYMBOL_GPL(iscsi_get_port_state_name);
    4373                 :            : 
    4374                 :          0 : static int iscsi_session_match(struct attribute_container *cont,
    4375                 :            :                            struct device *dev)
    4376                 :            : {
    4377                 :            :         struct iscsi_cls_session *session;
    4378                 :            :         struct Scsi_Host *shost;
    4379                 :            :         struct iscsi_internal *priv;
    4380                 :            : 
    4381                 :          0 :         if (!iscsi_is_session_dev(dev))
    4382                 :            :                 return 0;
    4383                 :            : 
    4384                 :            :         session = iscsi_dev_to_session(dev);
    4385                 :          0 :         shost = iscsi_session_to_shost(session);
    4386                 :          0 :         if (!shost->transportt)
    4387                 :            :                 return 0;
    4388                 :            : 
    4389                 :            :         priv = to_iscsi_internal(shost->transportt);
    4390                 :          0 :         if (priv->session_cont.ac.class != &iscsi_session_class.class)
    4391                 :            :                 return 0;
    4392                 :            : 
    4393                 :          0 :         return &priv->session_cont.ac == cont;
    4394                 :            : }
    4395                 :            : 
    4396                 :          0 : static int iscsi_conn_match(struct attribute_container *cont,
    4397                 :            :                            struct device *dev)
    4398                 :            : {
    4399                 :            :         struct iscsi_cls_session *session;
    4400                 :            :         struct iscsi_cls_conn *conn;
    4401                 :            :         struct Scsi_Host *shost;
    4402                 :            :         struct iscsi_internal *priv;
    4403                 :            : 
    4404                 :          0 :         if (!iscsi_is_conn_dev(dev))
    4405                 :            :                 return 0;
    4406                 :            : 
    4407                 :            :         conn = iscsi_dev_to_conn(dev);
    4408                 :          0 :         session = iscsi_dev_to_session(conn->dev.parent);
    4409                 :          0 :         shost = iscsi_session_to_shost(session);
    4410                 :            : 
    4411                 :          0 :         if (!shost->transportt)
    4412                 :            :                 return 0;
    4413                 :            : 
    4414                 :            :         priv = to_iscsi_internal(shost->transportt);
    4415                 :          0 :         if (priv->conn_cont.ac.class != &iscsi_connection_class.class)
    4416                 :            :                 return 0;
    4417                 :            : 
    4418                 :          0 :         return &priv->conn_cont.ac == cont;
    4419                 :            : }
    4420                 :            : 
    4421                 :          0 : static int iscsi_host_match(struct attribute_container *cont,
    4422                 :            :                             struct device *dev)
    4423                 :            : {
    4424                 :            :         struct Scsi_Host *shost;
    4425                 :            :         struct iscsi_internal *priv;
    4426                 :            : 
    4427                 :          0 :         if (!scsi_is_host_device(dev))
    4428                 :            :                 return 0;
    4429                 :            : 
    4430                 :          0 :         shost = dev_to_shost(dev);
    4431                 :          0 :         if (!shost->transportt  ||
    4432                 :          0 :             shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
    4433                 :            :                 return 0;
    4434                 :            : 
    4435                 :            :         priv = to_iscsi_internal(shost->transportt);
    4436                 :          0 :         return &priv->t.host_attrs.ac == cont;
    4437                 :            : }
    4438                 :            : 
    4439                 :            : struct scsi_transport_template *
    4440                 :          0 : iscsi_register_transport(struct iscsi_transport *tt)
    4441                 :            : {
    4442                 :            :         struct iscsi_internal *priv;
    4443                 :            :         unsigned long flags;
    4444                 :            :         int err;
    4445                 :            : 
    4446                 :          0 :         BUG_ON(!tt);
    4447                 :            : 
    4448                 :          0 :         priv = iscsi_if_transport_lookup(tt);
    4449                 :          0 :         if (priv)
    4450                 :            :                 return NULL;
    4451                 :            : 
    4452                 :          0 :         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    4453                 :          0 :         if (!priv)
    4454                 :            :                 return NULL;
    4455                 :          0 :         INIT_LIST_HEAD(&priv->list);
    4456                 :          0 :         priv->iscsi_transport = tt;
    4457                 :          0 :         priv->t.user_scan = iscsi_user_scan;
    4458                 :          0 :         priv->t.create_work_queue = 1;
    4459                 :            : 
    4460                 :          0 :         priv->dev.class = &iscsi_transport_class;
    4461                 :          0 :         dev_set_name(&priv->dev, "%s", tt->name);
    4462                 :          0 :         err = device_register(&priv->dev);
    4463                 :          0 :         if (err)
    4464                 :            :                 goto free_priv;
    4465                 :            : 
    4466                 :          0 :         err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group);
    4467                 :          0 :         if (err)
    4468                 :            :                 goto unregister_dev;
    4469                 :            : 
    4470                 :            :         /* host parameters */
    4471                 :          0 :         priv->t.host_attrs.ac.class = &iscsi_host_class.class;
    4472                 :          0 :         priv->t.host_attrs.ac.match = iscsi_host_match;
    4473                 :          0 :         priv->t.host_attrs.ac.grp = &iscsi_host_group;
    4474                 :          0 :         priv->t.host_size = sizeof(struct iscsi_cls_host);
    4475                 :            :         transport_container_register(&priv->t.host_attrs);
    4476                 :            : 
    4477                 :            :         /* connection parameters */
    4478                 :          0 :         priv->conn_cont.ac.class = &iscsi_connection_class.class;
    4479                 :          0 :         priv->conn_cont.ac.match = iscsi_conn_match;
    4480                 :          0 :         priv->conn_cont.ac.grp = &iscsi_conn_group;
    4481                 :            :         transport_container_register(&priv->conn_cont);
    4482                 :            : 
    4483                 :            :         /* session parameters */
    4484                 :          0 :         priv->session_cont.ac.class = &iscsi_session_class.class;
    4485                 :          0 :         priv->session_cont.ac.match = iscsi_session_match;
    4486                 :          0 :         priv->session_cont.ac.grp = &iscsi_session_group;
    4487                 :            :         transport_container_register(&priv->session_cont);
    4488                 :            : 
    4489                 :          0 :         spin_lock_irqsave(&iscsi_transport_lock, flags);
    4490                 :            :         list_add(&priv->list, &iscsi_transports);
    4491                 :            :         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
    4492                 :            : 
    4493                 :          0 :         printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
    4494                 :          0 :         return &priv->t;
    4495                 :            : 
    4496                 :            : unregister_dev:
    4497                 :          0 :         device_unregister(&priv->dev);
    4498                 :          0 :         return NULL;
    4499                 :            : free_priv:
    4500                 :          0 :         kfree(priv);
    4501                 :          0 :         return NULL;
    4502                 :            : }
    4503                 :            : EXPORT_SYMBOL_GPL(iscsi_register_transport);
    4504                 :            : 
    4505                 :          0 : int iscsi_unregister_transport(struct iscsi_transport *tt)
    4506                 :            : {
    4507                 :            :         struct iscsi_internal *priv;
    4508                 :            :         unsigned long flags;
    4509                 :            : 
    4510                 :          0 :         BUG_ON(!tt);
    4511                 :            : 
    4512                 :          0 :         mutex_lock(&rx_queue_mutex);
    4513                 :            : 
    4514                 :          0 :         priv = iscsi_if_transport_lookup(tt);
    4515                 :          0 :         BUG_ON (!priv);
    4516                 :            : 
    4517                 :          0 :         spin_lock_irqsave(&iscsi_transport_lock, flags);
    4518                 :            :         list_del(&priv->list);
    4519                 :            :         spin_unlock_irqrestore(&iscsi_transport_lock, flags);
    4520                 :            : 
    4521                 :          0 :         transport_container_unregister(&priv->conn_cont);
    4522                 :          0 :         transport_container_unregister(&priv->session_cont);
    4523                 :          0 :         transport_container_unregister(&priv->t.host_attrs);
    4524                 :            : 
    4525                 :          0 :         sysfs_remove_group(&priv->dev.kobj, &iscsi_transport_group);
    4526                 :          0 :         device_unregister(&priv->dev);
    4527                 :          0 :         mutex_unlock(&rx_queue_mutex);
    4528                 :            : 
    4529                 :          0 :         return 0;
    4530                 :            : }
    4531                 :            : EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
    4532                 :            : 
    4533                 :          0 : void iscsi_dbg_trace(void (*trace)(struct device *dev, struct va_format *),
    4534                 :            :                      struct device *dev, const char *fmt, ...)
    4535                 :            : {
    4536                 :            :         struct va_format vaf;
    4537                 :            :         va_list args;
    4538                 :            : 
    4539                 :          0 :         va_start(args, fmt);
    4540                 :          0 :         vaf.fmt = fmt;
    4541                 :          0 :         vaf.va = &args;
    4542                 :          0 :         trace(dev, &vaf);
    4543                 :          0 :         va_end(args);
    4544                 :          0 : }
    4545                 :            : EXPORT_SYMBOL_GPL(iscsi_dbg_trace);
    4546                 :            : 
    4547                 :          3 : static __init int iscsi_transport_init(void)
    4548                 :            : {
    4549                 :            :         int err;
    4550                 :          3 :         struct netlink_kernel_cfg cfg = {
    4551                 :            :                 .groups = 1,
    4552                 :            :                 .input  = iscsi_if_rx,
    4553                 :            :         };
    4554                 :          3 :         printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
    4555                 :            :                 ISCSI_TRANSPORT_VERSION);
    4556                 :            : 
    4557                 :            :         atomic_set(&iscsi_session_nr, 0);
    4558                 :            : 
    4559                 :          3 :         err = class_register(&iscsi_transport_class);
    4560                 :          3 :         if (err)
    4561                 :            :                 return err;
    4562                 :            : 
    4563                 :          3 :         err = class_register(&iscsi_endpoint_class);
    4564                 :          3 :         if (err)
    4565                 :            :                 goto unregister_transport_class;
    4566                 :            : 
    4567                 :          3 :         err = class_register(&iscsi_iface_class);
    4568                 :          3 :         if (err)
    4569                 :            :                 goto unregister_endpoint_class;
    4570                 :            : 
    4571                 :          3 :         err = transport_class_register(&iscsi_host_class);
    4572                 :          3 :         if (err)
    4573                 :            :                 goto unregister_iface_class;
    4574                 :            : 
    4575                 :          3 :         err = transport_class_register(&iscsi_connection_class);
    4576                 :          3 :         if (err)
    4577                 :            :                 goto unregister_host_class;
    4578                 :            : 
    4579                 :          3 :         err = transport_class_register(&iscsi_session_class);
    4580                 :          3 :         if (err)
    4581                 :            :                 goto unregister_conn_class;
    4582                 :            : 
    4583                 :          3 :         err = bus_register(&iscsi_flashnode_bus);
    4584                 :          3 :         if (err)
    4585                 :            :                 goto unregister_session_class;
    4586                 :            : 
    4587                 :          3 :         nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, &cfg);
    4588                 :          3 :         if (!nls) {
    4589                 :            :                 err = -ENOBUFS;
    4590                 :            :                 goto unregister_flashnode_bus;
    4591                 :            :         }
    4592                 :            : 
    4593                 :          3 :         iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
    4594                 :          3 :         if (!iscsi_eh_timer_workq) {
    4595                 :            :                 err = -ENOMEM;
    4596                 :            :                 goto release_nls;
    4597                 :            :         }
    4598                 :            : 
    4599                 :            :         return 0;
    4600                 :            : 
    4601                 :            : release_nls:
    4602                 :          0 :         netlink_kernel_release(nls);
    4603                 :            : unregister_flashnode_bus:
    4604                 :          0 :         bus_unregister(&iscsi_flashnode_bus);
    4605                 :            : unregister_session_class:
    4606                 :          0 :         transport_class_unregister(&iscsi_session_class);
    4607                 :            : unregister_conn_class:
    4608                 :          0 :         transport_class_unregister(&iscsi_connection_class);
    4609                 :            : unregister_host_class:
    4610                 :          0 :         transport_class_unregister(&iscsi_host_class);
    4611                 :            : unregister_iface_class:
    4612                 :          0 :         class_unregister(&iscsi_iface_class);
    4613                 :            : unregister_endpoint_class:
    4614                 :          0 :         class_unregister(&iscsi_endpoint_class);
    4615                 :            : unregister_transport_class:
    4616                 :          0 :         class_unregister(&iscsi_transport_class);
    4617                 :          0 :         return err;
    4618                 :            : }
    4619                 :            : 
    4620                 :          0 : static void __exit iscsi_transport_exit(void)
    4621                 :            : {
    4622                 :          0 :         destroy_workqueue(iscsi_eh_timer_workq);
    4623                 :          0 :         netlink_kernel_release(nls);
    4624                 :          0 :         bus_unregister(&iscsi_flashnode_bus);
    4625                 :          0 :         transport_class_unregister(&iscsi_connection_class);
    4626                 :          0 :         transport_class_unregister(&iscsi_session_class);
    4627                 :          0 :         transport_class_unregister(&iscsi_host_class);
    4628                 :          0 :         class_unregister(&iscsi_endpoint_class);
    4629                 :          0 :         class_unregister(&iscsi_iface_class);
    4630                 :          0 :         class_unregister(&iscsi_transport_class);
    4631                 :          0 : }
    4632                 :            : 
    4633                 :            : module_init(iscsi_transport_init);
    4634                 :            : module_exit(iscsi_transport_exit);
    4635                 :            : 
    4636                 :            : MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
    4637                 :            :               "Dmitry Yusupov <dmitry_yus@yahoo.com>, "
    4638                 :            :               "Alex Aizman <itn780@yahoo.com>");
    4639                 :            : MODULE_DESCRIPTION("iSCSI Transport Interface");
    4640                 :            : MODULE_LICENSE("GPL");
    4641                 :            : MODULE_VERSION(ISCSI_TRANSPORT_VERSION);
    4642                 :            : MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_ISCSI);
    

Generated by: LCOV version 1.14