16733b39aSJayamohan Kallickal /** 260f36e04SJitendra Bhivare * Copyright (C) 2005 - 2016 Broadcom 36733b39aSJayamohan Kallickal * All rights reserved. 46733b39aSJayamohan Kallickal * 56733b39aSJayamohan Kallickal * This program is free software; you can redistribute it and/or 66733b39aSJayamohan Kallickal * modify it under the terms of the GNU General Public License version 2 76733b39aSJayamohan Kallickal * as published by the Free Software Foundation. The full GNU General 86733b39aSJayamohan Kallickal * Public License is included in this distribution in the file called COPYING. 96733b39aSJayamohan Kallickal * 1060f36e04SJitendra Bhivare * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) 116733b39aSJayamohan Kallickal * 126733b39aSJayamohan Kallickal * Contact Information: 1360f36e04SJitendra Bhivare * linux-drivers@broadcom.com 146733b39aSJayamohan Kallickal * 15c4f39bdaSKetan Mukadam * Emulex 16255fa9a3SJayamohan Kallickal * 3333 Susan Street 17255fa9a3SJayamohan Kallickal * Costa Mesa, CA 92626 186733b39aSJayamohan Kallickal */ 196733b39aSJayamohan Kallickal 206733b39aSJayamohan Kallickal #include <scsi/libiscsi.h> 216733b39aSJayamohan Kallickal #include <scsi/scsi_transport_iscsi.h> 226733b39aSJayamohan Kallickal #include <scsi/scsi_transport.h> 236733b39aSJayamohan Kallickal #include <scsi/scsi_cmnd.h> 246733b39aSJayamohan Kallickal #include <scsi/scsi_device.h> 256733b39aSJayamohan Kallickal #include <scsi/scsi_host.h> 260e43895eSMike Christie #include <scsi/scsi_netlink.h> 270e43895eSMike Christie #include <net/netlink.h> 286733b39aSJayamohan Kallickal #include <scsi/scsi.h> 296733b39aSJayamohan Kallickal 306733b39aSJayamohan Kallickal #include "be_iscsi.h" 316733b39aSJayamohan Kallickal 326733b39aSJayamohan Kallickal extern struct iscsi_transport beiscsi_iscsi_transport; 336733b39aSJayamohan Kallickal 346733b39aSJayamohan Kallickal /** 356733b39aSJayamohan Kallickal * beiscsi_session_create - creates a new iscsi session 366733b39aSJayamohan Kallickal * @cmds_max: max commands supported 376733b39aSJayamohan Kallickal * @qdepth: max queue depth supported 386733b39aSJayamohan Kallickal * @initial_cmdsn: initial iscsi CMDSN 396733b39aSJayamohan Kallickal */ 406733b39aSJayamohan Kallickal struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, 416733b39aSJayamohan Kallickal u16 cmds_max, 426733b39aSJayamohan Kallickal u16 qdepth, 436733b39aSJayamohan Kallickal u32 initial_cmdsn) 446733b39aSJayamohan Kallickal { 456733b39aSJayamohan Kallickal struct Scsi_Host *shost; 466733b39aSJayamohan Kallickal struct beiscsi_endpoint *beiscsi_ep; 476733b39aSJayamohan Kallickal struct iscsi_cls_session *cls_session; 486733b39aSJayamohan Kallickal struct beiscsi_hba *phba; 49b8b9e1b8SJayamohan Kallickal struct iscsi_session *sess; 50b8b9e1b8SJayamohan Kallickal struct beiscsi_session *beiscsi_sess; 516733b39aSJayamohan Kallickal struct beiscsi_io_task *io_task; 526733b39aSJayamohan Kallickal 536733b39aSJayamohan Kallickal 546733b39aSJayamohan Kallickal if (!ep) { 559122e991SJitendra Bhivare pr_err("beiscsi_session_create: invalid ep\n"); 566733b39aSJayamohan Kallickal return NULL; 576733b39aSJayamohan Kallickal } 586733b39aSJayamohan Kallickal beiscsi_ep = ep->dd_data; 596733b39aSJayamohan Kallickal phba = beiscsi_ep->phba; 6099bc5d55SJohn Soni Jose 61d1d5ca88SJitendra Bhivare if (!beiscsi_hba_is_online(phba)) { 6299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 639122e991SJitendra Bhivare "BS_%d : HBA in error 0x%lx\n", phba->state); 649122e991SJitendra Bhivare return NULL; 653567f36aSJayamohan Kallickal } 6699bc5d55SJohn Soni Jose 679122e991SJitendra Bhivare beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 689122e991SJitendra Bhivare "BS_%d : In beiscsi_session_create\n"); 696733b39aSJayamohan Kallickal if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { 7099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 7199bc5d55SJohn Soni Jose "BS_%d : Cannot handle %d cmds." 726733b39aSJayamohan Kallickal "Max cmds per session supported is %d. Using %d." 736733b39aSJayamohan Kallickal "\n", cmds_max, 746733b39aSJayamohan Kallickal beiscsi_ep->phba->params.wrbs_per_cxn, 756733b39aSJayamohan Kallickal beiscsi_ep->phba->params.wrbs_per_cxn); 7699bc5d55SJohn Soni Jose 776733b39aSJayamohan Kallickal cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; 786733b39aSJayamohan Kallickal } 796733b39aSJayamohan Kallickal 803567f36aSJayamohan Kallickal shost = phba->shost; 816733b39aSJayamohan Kallickal cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, 826733b39aSJayamohan Kallickal shost, cmds_max, 83b8b9e1b8SJayamohan Kallickal sizeof(*beiscsi_sess), 84b8b9e1b8SJayamohan Kallickal sizeof(*io_task), 856733b39aSJayamohan Kallickal initial_cmdsn, ISCSI_MAX_TARGET); 866733b39aSJayamohan Kallickal if (!cls_session) 876733b39aSJayamohan Kallickal return NULL; 886733b39aSJayamohan Kallickal sess = cls_session->dd_data; 892afc95bfSJayamohan Kallickal beiscsi_sess = sess->dd_data; 902afc95bfSJayamohan Kallickal beiscsi_sess->bhs_pool = pci_pool_create("beiscsi_bhs_pool", 912afc95bfSJayamohan Kallickal phba->pcidev, 922afc95bfSJayamohan Kallickal sizeof(struct be_cmd_bhs), 932afc95bfSJayamohan Kallickal 64, 0); 942afc95bfSJayamohan Kallickal if (!beiscsi_sess->bhs_pool) 952afc95bfSJayamohan Kallickal goto destroy_sess; 966733b39aSJayamohan Kallickal 976733b39aSJayamohan Kallickal return cls_session; 982afc95bfSJayamohan Kallickal destroy_sess: 992afc95bfSJayamohan Kallickal iscsi_session_teardown(cls_session); 1002afc95bfSJayamohan Kallickal return NULL; 1016733b39aSJayamohan Kallickal } 1026733b39aSJayamohan Kallickal 1036733b39aSJayamohan Kallickal /** 1046733b39aSJayamohan Kallickal * beiscsi_session_destroy - destroys iscsi session 1056733b39aSJayamohan Kallickal * @cls_session: pointer to iscsi cls session 1066733b39aSJayamohan Kallickal * 1076733b39aSJayamohan Kallickal * Destroys iSCSI session instance and releases 1086733b39aSJayamohan Kallickal * resources allocated for it. 1096733b39aSJayamohan Kallickal */ 1106733b39aSJayamohan Kallickal void beiscsi_session_destroy(struct iscsi_cls_session *cls_session) 1116733b39aSJayamohan Kallickal { 1126733b39aSJayamohan Kallickal struct iscsi_session *sess = cls_session->dd_data; 1132afc95bfSJayamohan Kallickal struct beiscsi_session *beiscsi_sess = sess->dd_data; 1146733b39aSJayamohan Kallickal 11599bc5d55SJohn Soni Jose printk(KERN_INFO "In beiscsi_session_destroy\n"); 1162afc95bfSJayamohan Kallickal pci_pool_destroy(beiscsi_sess->bhs_pool); 1176733b39aSJayamohan Kallickal iscsi_session_teardown(cls_session); 1186733b39aSJayamohan Kallickal } 1196733b39aSJayamohan Kallickal 1206733b39aSJayamohan Kallickal /** 121480195c2SJitendra Bhivare * beiscsi_session_fail(): Closing session with appropriate error 122480195c2SJitendra Bhivare * @cls_session: ptr to session 123480195c2SJitendra Bhivare **/ 124480195c2SJitendra Bhivare void beiscsi_session_fail(struct iscsi_cls_session *cls_session) 125480195c2SJitendra Bhivare { 126480195c2SJitendra Bhivare iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); 127480195c2SJitendra Bhivare } 128480195c2SJitendra Bhivare 129480195c2SJitendra Bhivare 130480195c2SJitendra Bhivare /** 1316733b39aSJayamohan Kallickal * beiscsi_conn_create - create an instance of iscsi connection 1326733b39aSJayamohan Kallickal * @cls_session: ptr to iscsi_cls_session 1336733b39aSJayamohan Kallickal * @cid: iscsi cid 1346733b39aSJayamohan Kallickal */ 1356733b39aSJayamohan Kallickal struct iscsi_cls_conn * 1366733b39aSJayamohan Kallickal beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid) 1376733b39aSJayamohan Kallickal { 1386733b39aSJayamohan Kallickal struct beiscsi_hba *phba; 1396733b39aSJayamohan Kallickal struct Scsi_Host *shost; 1406733b39aSJayamohan Kallickal struct iscsi_cls_conn *cls_conn; 1416733b39aSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn; 1426733b39aSJayamohan Kallickal struct iscsi_conn *conn; 1432afc95bfSJayamohan Kallickal struct iscsi_session *sess; 1442afc95bfSJayamohan Kallickal struct beiscsi_session *beiscsi_sess; 1456733b39aSJayamohan Kallickal 1466733b39aSJayamohan Kallickal shost = iscsi_session_to_shost(cls_session); 1476733b39aSJayamohan Kallickal phba = iscsi_host_priv(shost); 1486733b39aSJayamohan Kallickal 14999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 15099bc5d55SJohn Soni Jose "BS_%d : In beiscsi_conn_create ,cid" 15199bc5d55SJohn Soni Jose "from iscsi layer=%d\n", cid); 15299bc5d55SJohn Soni Jose 1536733b39aSJayamohan Kallickal cls_conn = iscsi_conn_setup(cls_session, sizeof(*beiscsi_conn), cid); 1546733b39aSJayamohan Kallickal if (!cls_conn) 1556733b39aSJayamohan Kallickal return NULL; 1566733b39aSJayamohan Kallickal 1576733b39aSJayamohan Kallickal conn = cls_conn->dd_data; 1586733b39aSJayamohan Kallickal beiscsi_conn = conn->dd_data; 1596733b39aSJayamohan Kallickal beiscsi_conn->ep = NULL; 1606733b39aSJayamohan Kallickal beiscsi_conn->phba = phba; 1616733b39aSJayamohan Kallickal beiscsi_conn->conn = conn; 1622afc95bfSJayamohan Kallickal sess = cls_session->dd_data; 1632afc95bfSJayamohan Kallickal beiscsi_sess = sess->dd_data; 1642afc95bfSJayamohan Kallickal beiscsi_conn->beiscsi_sess = beiscsi_sess; 1656733b39aSJayamohan Kallickal return cls_conn; 1666733b39aSJayamohan Kallickal } 1676733b39aSJayamohan Kallickal 1686733b39aSJayamohan Kallickal /** 1696733b39aSJayamohan Kallickal * beiscsi_conn_bind - Binds iscsi session/connection with TCP connection 1706733b39aSJayamohan Kallickal * @cls_session: pointer to iscsi cls session 1716733b39aSJayamohan Kallickal * @cls_conn: pointer to iscsi cls conn 1726733b39aSJayamohan Kallickal * @transport_fd: EP handle(64 bit) 1736733b39aSJayamohan Kallickal * 1746733b39aSJayamohan Kallickal * This function binds the TCP Conn with iSCSI Connection and Session. 1756733b39aSJayamohan Kallickal */ 1766733b39aSJayamohan Kallickal int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, 1776733b39aSJayamohan Kallickal struct iscsi_cls_conn *cls_conn, 1786733b39aSJayamohan Kallickal u64 transport_fd, int is_leading) 1796733b39aSJayamohan Kallickal { 1806733b39aSJayamohan Kallickal struct iscsi_conn *conn = cls_conn->dd_data; 1816733b39aSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn = conn->dd_data; 1823093b048SMike Christie struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); 1833093b048SMike Christie struct beiscsi_hba *phba = iscsi_host_priv(shost); 1841e4be6ffSJayamohan Kallickal struct hwi_controller *phwi_ctrlr = phba->phwi_ctrlr; 1851e4be6ffSJayamohan Kallickal struct hwi_wrb_context *pwrb_context; 1866733b39aSJayamohan Kallickal struct beiscsi_endpoint *beiscsi_ep; 1876733b39aSJayamohan Kallickal struct iscsi_endpoint *ep; 188*413f3656SJitendra Bhivare uint16_t cri_index; 1896733b39aSJayamohan Kallickal 1906733b39aSJayamohan Kallickal ep = iscsi_lookup_endpoint(transport_fd); 1916733b39aSJayamohan Kallickal if (!ep) 1926733b39aSJayamohan Kallickal return -EINVAL; 1936733b39aSJayamohan Kallickal 1946733b39aSJayamohan Kallickal beiscsi_ep = ep->dd_data; 1956733b39aSJayamohan Kallickal 1966733b39aSJayamohan Kallickal if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) 1976733b39aSJayamohan Kallickal return -EINVAL; 1986733b39aSJayamohan Kallickal 1996733b39aSJayamohan Kallickal if (beiscsi_ep->phba != phba) { 20099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 20199bc5d55SJohn Soni Jose "BS_%d : beiscsi_ep->hba=%p not equal to phba=%p\n", 2026733b39aSJayamohan Kallickal beiscsi_ep->phba, phba); 20399bc5d55SJohn Soni Jose 2046733b39aSJayamohan Kallickal return -EEXIST; 2056733b39aSJayamohan Kallickal } 206*413f3656SJitendra Bhivare cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid); 207*413f3656SJitendra Bhivare if (phba->conn_table[cri_index]) { 208*413f3656SJitendra Bhivare if (beiscsi_conn != phba->conn_table[cri_index] || 209*413f3656SJitendra Bhivare beiscsi_ep != phba->conn_table[cri_index]->ep) { 210*413f3656SJitendra Bhivare __beiscsi_log(phba, KERN_ERR, 211*413f3656SJitendra Bhivare "BS_%d : conn_table not empty at %u: cid %u conn %p:%p\n", 212*413f3656SJitendra Bhivare cri_index, 213*413f3656SJitendra Bhivare beiscsi_ep->ep_cid, 214*413f3656SJitendra Bhivare beiscsi_conn, 215*413f3656SJitendra Bhivare phba->conn_table[cri_index]); 216*413f3656SJitendra Bhivare return -EINVAL; 217*413f3656SJitendra Bhivare } 218*413f3656SJitendra Bhivare } 2191e4be6ffSJayamohan Kallickal 2206733b39aSJayamohan Kallickal beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid; 2216733b39aSJayamohan Kallickal beiscsi_conn->ep = beiscsi_ep; 2226733b39aSJayamohan Kallickal beiscsi_ep->conn = beiscsi_conn; 223*413f3656SJitendra Bhivare /** 224*413f3656SJitendra Bhivare * Each connection is associated with a WRBQ kept in wrb_context. 225*413f3656SJitendra Bhivare * Store doorbell offset for transmit path. 226*413f3656SJitendra Bhivare */ 227*413f3656SJitendra Bhivare pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; 2281e4be6ffSJayamohan Kallickal beiscsi_conn->doorbell_offset = pwrb_context->doorbell_offset; 22999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 230*413f3656SJitendra Bhivare "BS_%d : cid %d phba->conn_table[%u]=%p\n", 231*413f3656SJitendra Bhivare beiscsi_ep->ep_cid, cri_index, beiscsi_conn); 232*413f3656SJitendra Bhivare phba->conn_table[cri_index] = beiscsi_conn; 233*413f3656SJitendra Bhivare return 0; 2346733b39aSJayamohan Kallickal } 2356733b39aSJayamohan Kallickal 23696b48b92SJitendra Bhivare static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba) 2370e43895eSMike Christie { 2380e43895eSMike Christie if (phba->ipv4_iface) 2390e43895eSMike Christie return 0; 2400e43895eSMike Christie 2410e43895eSMike Christie phba->ipv4_iface = iscsi_create_iface(phba->shost, 2420e43895eSMike Christie &beiscsi_iscsi_transport, 2430e43895eSMike Christie ISCSI_IFACE_TYPE_IPV4, 2440e43895eSMike Christie 0, 0); 2450e43895eSMike Christie if (!phba->ipv4_iface) { 24699bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 24799bc5d55SJohn Soni Jose "BS_%d : Could not " 2480e43895eSMike Christie "create default IPv4 address.\n"); 2490e43895eSMike Christie return -ENODEV; 2500e43895eSMike Christie } 2510e43895eSMike Christie 2520e43895eSMike Christie return 0; 2530e43895eSMike Christie } 2540e43895eSMike Christie 25596b48b92SJitendra Bhivare static int beiscsi_iface_create_ipv6(struct beiscsi_hba *phba) 2560e43895eSMike Christie { 2570e43895eSMike Christie if (phba->ipv6_iface) 2580e43895eSMike Christie return 0; 2590e43895eSMike Christie 2600e43895eSMike Christie phba->ipv6_iface = iscsi_create_iface(phba->shost, 2610e43895eSMike Christie &beiscsi_iscsi_transport, 2620e43895eSMike Christie ISCSI_IFACE_TYPE_IPV6, 2630e43895eSMike Christie 0, 0); 2640e43895eSMike Christie if (!phba->ipv6_iface) { 26599bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 26699bc5d55SJohn Soni Jose "BS_%d : Could not " 2670e43895eSMike Christie "create default IPv6 address.\n"); 2680e43895eSMike Christie return -ENODEV; 2690e43895eSMike Christie } 2700e43895eSMike Christie 2710e43895eSMike Christie return 0; 2720e43895eSMike Christie } 2730e43895eSMike Christie 27496b48b92SJitendra Bhivare void beiscsi_iface_create_default(struct beiscsi_hba *phba) 2750e43895eSMike Christie { 2761f536d49SJayamohan Kallickal struct be_cmd_get_if_info_resp *if_info; 2770e43895eSMike Christie 278290aa376SJitendra Bhivare if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V4, &if_info)) { 27996b48b92SJitendra Bhivare beiscsi_iface_create_ipv4(phba); 2801f536d49SJayamohan Kallickal kfree(if_info); 2811f536d49SJayamohan Kallickal } 2820e43895eSMike Christie 283290aa376SJitendra Bhivare if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V6, &if_info)) { 28496b48b92SJitendra Bhivare beiscsi_iface_create_ipv6(phba); 2851f536d49SJayamohan Kallickal kfree(if_info); 2861f536d49SJayamohan Kallickal } 2870e43895eSMike Christie } 2880e43895eSMike Christie 28996b48b92SJitendra Bhivare void beiscsi_iface_destroy_default(struct beiscsi_hba *phba) 2900e43895eSMike Christie { 291f7dd017eSJitendra Bhivare if (phba->ipv6_iface) { 2920e43895eSMike Christie iscsi_destroy_iface(phba->ipv6_iface); 293f7dd017eSJitendra Bhivare phba->ipv6_iface = NULL; 294f7dd017eSJitendra Bhivare } 295f7dd017eSJitendra Bhivare if (phba->ipv4_iface) { 2960e43895eSMike Christie iscsi_destroy_iface(phba->ipv4_iface); 297f7dd017eSJitendra Bhivare phba->ipv4_iface = NULL; 298f7dd017eSJitendra Bhivare } 2990e43895eSMike Christie } 3000e43895eSMike Christie 3016f72238eSJohn Soni Jose /** 3026f72238eSJohn Soni Jose * beiscsi_set_vlan_tag()- Set the VLAN TAG 3036f72238eSJohn Soni Jose * @shost: Scsi Host for the driver instance 3046f72238eSJohn Soni Jose * @iface_param: Interface paramters 3056f72238eSJohn Soni Jose * 3066f72238eSJohn Soni Jose * Set the VLAN TAG for the adapter or disable 3076f72238eSJohn Soni Jose * the VLAN config 3086f72238eSJohn Soni Jose * 3096f72238eSJohn Soni Jose * returns 3106f72238eSJohn Soni Jose * Success: 0 3116f72238eSJohn Soni Jose * Failure: Non-Zero Value 3126f72238eSJohn Soni Jose **/ 3136f72238eSJohn Soni Jose static int 314db02aea9SJitendra Bhivare beiscsi_iface_config_vlan(struct Scsi_Host *shost, 3156f72238eSJohn Soni Jose struct iscsi_iface_param_info *iface_param) 3166f72238eSJohn Soni Jose { 3176f72238eSJohn Soni Jose struct beiscsi_hba *phba = iscsi_host_priv(shost); 318c5bf8889SJitendra Bhivare int ret = -EPERM; 3196f72238eSJohn Soni Jose 3206f72238eSJohn Soni Jose switch (iface_param->param) { 3216f72238eSJohn Soni Jose case ISCSI_NET_PARAM_VLAN_ENABLED: 322db02aea9SJitendra Bhivare ret = 0; 3236f72238eSJohn Soni Jose if (iface_param->value[0] != ISCSI_VLAN_ENABLE) 324db02aea9SJitendra Bhivare ret = beiscsi_if_set_vlan(phba, BEISCSI_VLAN_DISABLE); 3256f72238eSJohn Soni Jose break; 3266f72238eSJohn Soni Jose case ISCSI_NET_PARAM_VLAN_TAG: 327db02aea9SJitendra Bhivare ret = beiscsi_if_set_vlan(phba, 3286f72238eSJohn Soni Jose *((uint16_t *)iface_param->value)); 3296f72238eSJohn Soni Jose break; 3306f72238eSJohn Soni Jose } 3316f72238eSJohn Soni Jose return ret; 3326f72238eSJohn Soni Jose } 3336f72238eSJohn Soni Jose 3346f72238eSJohn Soni Jose 3350e43895eSMike Christie static int 3360152a7e9SJitendra Bhivare beiscsi_iface_config_ipv4(struct Scsi_Host *shost, 3370152a7e9SJitendra Bhivare struct iscsi_iface_param_info *info, 3380e43895eSMike Christie void *data, uint32_t dt_len) 3390e43895eSMike Christie { 3400e43895eSMike Christie struct beiscsi_hba *phba = iscsi_host_priv(shost); 3410152a7e9SJitendra Bhivare u8 *ip = NULL, *subnet = NULL, *gw; 3420152a7e9SJitendra Bhivare struct nlattr *nla; 343db02aea9SJitendra Bhivare int ret = -EPERM; 3440e43895eSMike Christie 3450e43895eSMike Christie /* Check the param */ 3460152a7e9SJitendra Bhivare switch (info->param) { 347f7dd017eSJitendra Bhivare case ISCSI_NET_PARAM_IFACE_ENABLE: 3480152a7e9SJitendra Bhivare if (info->value[0] == ISCSI_IFACE_ENABLE) 34996b48b92SJitendra Bhivare ret = beiscsi_iface_create_ipv4(phba); 350f7dd017eSJitendra Bhivare else { 351f7dd017eSJitendra Bhivare iscsi_destroy_iface(phba->ipv4_iface); 352f7dd017eSJitendra Bhivare phba->ipv4_iface = NULL; 353f7dd017eSJitendra Bhivare } 354f7dd017eSJitendra Bhivare break; 3550e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_GW: 3560152a7e9SJitendra Bhivare gw = info->value; 357290aa376SJitendra Bhivare ret = beiscsi_if_set_gw(phba, BEISCSI_IP_TYPE_V4, gw); 3580e43895eSMike Christie break; 3590e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_BOOTPROTO: 3600152a7e9SJitendra Bhivare if (info->value[0] == ISCSI_BOOTPROTO_DHCP) 361290aa376SJitendra Bhivare ret = beiscsi_if_en_dhcp(phba, BEISCSI_IP_TYPE_V4); 3620152a7e9SJitendra Bhivare else if (info->value[0] == ISCSI_BOOTPROTO_STATIC) 3630152a7e9SJitendra Bhivare /* release DHCP IP address */ 364290aa376SJitendra Bhivare ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4, 365290aa376SJitendra Bhivare NULL, NULL); 3660e43895eSMike Christie else 36799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 36899bc5d55SJohn Soni Jose "BS_%d : Invalid BOOTPROTO: %d\n", 3690152a7e9SJitendra Bhivare info->value[0]); 3700152a7e9SJitendra Bhivare break; 3710152a7e9SJitendra Bhivare case ISCSI_NET_PARAM_IPV4_ADDR: 3720152a7e9SJitendra Bhivare ip = info->value; 3730152a7e9SJitendra Bhivare nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET); 3740152a7e9SJitendra Bhivare if (nla) { 3750152a7e9SJitendra Bhivare info = nla_data(nla); 3760152a7e9SJitendra Bhivare subnet = info->value; 3770152a7e9SJitendra Bhivare } 378290aa376SJitendra Bhivare ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4, 379290aa376SJitendra Bhivare ip, subnet); 3800e43895eSMike Christie break; 3810e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_SUBNET: 3820152a7e9SJitendra Bhivare /* 3830152a7e9SJitendra Bhivare * OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR ioctl needs IP 3840152a7e9SJitendra Bhivare * and subnet both. Find IP to be applied for this subnet. 3850152a7e9SJitendra Bhivare */ 3860152a7e9SJitendra Bhivare subnet = info->value; 3870152a7e9SJitendra Bhivare nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR); 3880152a7e9SJitendra Bhivare if (nla) { 3890152a7e9SJitendra Bhivare info = nla_data(nla); 3900152a7e9SJitendra Bhivare ip = info->value; 3910152a7e9SJitendra Bhivare } 392290aa376SJitendra Bhivare ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4, 393290aa376SJitendra Bhivare ip, subnet); 3940e43895eSMike Christie break; 3950e43895eSMike Christie } 3960e43895eSMike Christie 3970e43895eSMike Christie return ret; 3980e43895eSMike Christie } 3990e43895eSMike Christie 4000e43895eSMike Christie static int 4010152a7e9SJitendra Bhivare beiscsi_iface_config_ipv6(struct Scsi_Host *shost, 4020e43895eSMike Christie struct iscsi_iface_param_info *iface_param, 4030e43895eSMike Christie void *data, uint32_t dt_len) 4040e43895eSMike Christie { 4050e43895eSMike Christie struct beiscsi_hba *phba = iscsi_host_priv(shost); 406db02aea9SJitendra Bhivare int ret = -EPERM; 4070e43895eSMike Christie 4080e43895eSMike Christie switch (iface_param->param) { 4090e43895eSMike Christie case ISCSI_NET_PARAM_IFACE_ENABLE: 4100e43895eSMike Christie if (iface_param->value[0] == ISCSI_IFACE_ENABLE) 41196b48b92SJitendra Bhivare ret = beiscsi_iface_create_ipv6(phba); 4120e43895eSMike Christie else { 4130e43895eSMike Christie iscsi_destroy_iface(phba->ipv6_iface); 414f7dd017eSJitendra Bhivare phba->ipv6_iface = NULL; 4150e43895eSMike Christie } 4160e43895eSMike Christie break; 4170e43895eSMike Christie case ISCSI_NET_PARAM_IPV6_ADDR: 418290aa376SJitendra Bhivare ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V6, 4190152a7e9SJitendra Bhivare iface_param->value, NULL); 4200e43895eSMike Christie break; 4210e43895eSMike Christie } 4220e43895eSMike Christie 4230e43895eSMike Christie return ret; 4240e43895eSMike Christie } 4250e43895eSMike Christie 42696b48b92SJitendra Bhivare int beiscsi_iface_set_param(struct Scsi_Host *shost, 4270e43895eSMike Christie void *data, uint32_t dt_len) 4280e43895eSMike Christie { 4290e43895eSMike Christie struct iscsi_iface_param_info *iface_param = NULL; 43099bc5d55SJohn Soni Jose struct beiscsi_hba *phba = iscsi_host_priv(shost); 4310e43895eSMike Christie struct nlattr *attrib; 4320e43895eSMike Christie uint32_t rm_len = dt_len; 433c5bf8889SJitendra Bhivare int ret; 4340e43895eSMike Christie 435d1d5ca88SJitendra Bhivare if (!beiscsi_hba_is_online(phba)) { 4369122e991SJitendra Bhivare beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 4379122e991SJitendra Bhivare "BS_%d : HBA in error 0x%lx\n", phba->state); 4383567f36aSJayamohan Kallickal return -EBUSY; 4393567f36aSJayamohan Kallickal } 4403567f36aSJayamohan Kallickal 441c5bf8889SJitendra Bhivare /* update interface_handle */ 442c5bf8889SJitendra Bhivare ret = beiscsi_if_get_handle(phba); 443c5bf8889SJitendra Bhivare if (ret) { 444c5bf8889SJitendra Bhivare beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 445c5bf8889SJitendra Bhivare "BS_%d : Getting Interface Handle Failed\n"); 446c5bf8889SJitendra Bhivare return ret; 447c5bf8889SJitendra Bhivare } 448c5bf8889SJitendra Bhivare 4490e43895eSMike Christie nla_for_each_attr(attrib, data, dt_len, rm_len) { 4500e43895eSMike Christie iface_param = nla_data(attrib); 4510e43895eSMike Christie 4520e43895eSMike Christie if (iface_param->param_type != ISCSI_NET_PARAM) 4530e43895eSMike Christie continue; 4540e43895eSMike Christie 4550e43895eSMike Christie /* 4560e43895eSMike Christie * BE2ISCSI only supports 1 interface 4570e43895eSMike Christie */ 4580e43895eSMike Christie if (iface_param->iface_num) { 45999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 46099bc5d55SJohn Soni Jose "BS_%d : Invalid iface_num %d." 4610e43895eSMike Christie "Only iface_num 0 is supported.\n", 4620e43895eSMike Christie iface_param->iface_num); 46399bc5d55SJohn Soni Jose 4640e43895eSMike Christie return -EINVAL; 4650e43895eSMike Christie } 4660e43895eSMike Christie 467db02aea9SJitendra Bhivare beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 468db02aea9SJitendra Bhivare "BS_%d : %s.0 set param %d", 469db02aea9SJitendra Bhivare (iface_param->iface_type == ISCSI_IFACE_TYPE_IPV4) ? 470db02aea9SJitendra Bhivare "ipv4" : "ipv6", iface_param->param); 471db02aea9SJitendra Bhivare 472db02aea9SJitendra Bhivare ret = -EPERM; 473db02aea9SJitendra Bhivare switch (iface_param->param) { 474db02aea9SJitendra Bhivare case ISCSI_NET_PARAM_VLAN_ENABLED: 475db02aea9SJitendra Bhivare case ISCSI_NET_PARAM_VLAN_TAG: 476db02aea9SJitendra Bhivare ret = beiscsi_iface_config_vlan(shost, iface_param); 477db02aea9SJitendra Bhivare break; 478db02aea9SJitendra Bhivare default: 4790e43895eSMike Christie switch (iface_param->iface_type) { 4800e43895eSMike Christie case ISCSI_IFACE_TYPE_IPV4: 481db02aea9SJitendra Bhivare ret = beiscsi_iface_config_ipv4(shost, 482db02aea9SJitendra Bhivare iface_param, 4830e43895eSMike Christie data, dt_len); 4840e43895eSMike Christie break; 4850e43895eSMike Christie case ISCSI_IFACE_TYPE_IPV6: 486db02aea9SJitendra Bhivare ret = beiscsi_iface_config_ipv6(shost, 487db02aea9SJitendra Bhivare iface_param, 4880e43895eSMike Christie data, dt_len); 4890e43895eSMike Christie break; 490db02aea9SJitendra Bhivare } 4910e43895eSMike Christie } 4920e43895eSMike Christie 493db02aea9SJitendra Bhivare if (ret == -EPERM) { 494db02aea9SJitendra Bhivare __beiscsi_log(phba, KERN_ERR, 495db02aea9SJitendra Bhivare "BS_%d : %s.0 set param %d not permitted", 496db02aea9SJitendra Bhivare (iface_param->iface_type == 497db02aea9SJitendra Bhivare ISCSI_IFACE_TYPE_IPV4) ? "ipv4" : "ipv6", 498db02aea9SJitendra Bhivare iface_param->param); 499db02aea9SJitendra Bhivare ret = 0; 500db02aea9SJitendra Bhivare } 5010e43895eSMike Christie if (ret) 502db02aea9SJitendra Bhivare break; 5030e43895eSMike Christie } 5040e43895eSMike Christie 5050e43895eSMike Christie return ret; 5060e43895eSMike Christie } 5070e43895eSMike Christie 50896b48b92SJitendra Bhivare static int __beiscsi_iface_get_param(struct beiscsi_hba *phba, 50996b48b92SJitendra Bhivare struct iscsi_iface *iface, 51096b48b92SJitendra Bhivare int param, char *buf) 5110e43895eSMike Christie { 5121f536d49SJayamohan Kallickal struct be_cmd_get_if_info_resp *if_info; 513290aa376SJitendra Bhivare int len, ip_type = BEISCSI_IP_TYPE_V4; 5140e43895eSMike Christie 5150e43895eSMike Christie if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) 516290aa376SJitendra Bhivare ip_type = BEISCSI_IP_TYPE_V6; 5170e43895eSMike Christie 51896b48b92SJitendra Bhivare len = beiscsi_if_get_info(phba, ip_type, &if_info); 5190e7c60cbSGeyslan G. Bem if (len) 5200e43895eSMike Christie return len; 5210e43895eSMike Christie 5220e43895eSMike Christie switch (param) { 5230e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_ADDR: 5241f536d49SJayamohan Kallickal len = sprintf(buf, "%pI4\n", if_info->ip_addr.addr); 5250e43895eSMike Christie break; 5260e43895eSMike Christie case ISCSI_NET_PARAM_IPV6_ADDR: 5271f536d49SJayamohan Kallickal len = sprintf(buf, "%pI6\n", if_info->ip_addr.addr); 5280e43895eSMike Christie break; 5290e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_BOOTPROTO: 5301f536d49SJayamohan Kallickal if (!if_info->dhcp_state) 5318359c79bSJohn Soni Jose len = sprintf(buf, "static\n"); 5320e43895eSMike Christie else 5338359c79bSJohn Soni Jose len = sprintf(buf, "dhcp\n"); 5340e43895eSMike Christie break; 5350e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_SUBNET: 5361f536d49SJayamohan Kallickal len = sprintf(buf, "%pI4\n", if_info->ip_addr.subnet_mask); 5370e43895eSMike Christie break; 5386f72238eSJohn Soni Jose case ISCSI_NET_PARAM_VLAN_ENABLED: 5396f72238eSJohn Soni Jose len = sprintf(buf, "%s\n", 540ea89604fSJitendra Bhivare (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) ? 541ea89604fSJitendra Bhivare "disable" : "enable"); 5426f72238eSJohn Soni Jose break; 5436f72238eSJohn Soni Jose case ISCSI_NET_PARAM_VLAN_ID: 5441f536d49SJayamohan Kallickal if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) 5450e7c60cbSGeyslan G. Bem len = -EINVAL; 5466f72238eSJohn Soni Jose else 5476f72238eSJohn Soni Jose len = sprintf(buf, "%d\n", 5481f536d49SJayamohan Kallickal (if_info->vlan_priority & 5496f72238eSJohn Soni Jose ISCSI_MAX_VLAN_ID)); 5506f72238eSJohn Soni Jose break; 5516f72238eSJohn Soni Jose case ISCSI_NET_PARAM_VLAN_PRIORITY: 5521f536d49SJayamohan Kallickal if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) 5530e7c60cbSGeyslan G. Bem len = -EINVAL; 5546f72238eSJohn Soni Jose else 5556f72238eSJohn Soni Jose len = sprintf(buf, "%d\n", 5561f536d49SJayamohan Kallickal ((if_info->vlan_priority >> 13) & 5576f72238eSJohn Soni Jose ISCSI_MAX_VLAN_PRIORITY)); 5586f72238eSJohn Soni Jose break; 5590e43895eSMike Christie default: 5600e43895eSMike Christie WARN_ON(1); 5610e43895eSMike Christie } 5620e43895eSMike Christie 5631f536d49SJayamohan Kallickal kfree(if_info); 5640e43895eSMike Christie return len; 5650e43895eSMike Christie } 5660e43895eSMike Christie 56796b48b92SJitendra Bhivare int beiscsi_iface_get_param(struct iscsi_iface *iface, 5680e43895eSMike Christie enum iscsi_param_type param_type, 5690e43895eSMike Christie int param, char *buf) 5700e43895eSMike Christie { 5710e43895eSMike Christie struct Scsi_Host *shost = iscsi_iface_to_shost(iface); 5720e43895eSMike Christie struct beiscsi_hba *phba = iscsi_host_priv(shost); 5730e43895eSMike Christie struct be_cmd_get_def_gateway_resp gateway; 574c5bf8889SJitendra Bhivare int len = -EPERM; 5750e43895eSMike Christie 576d8383b34SJitendra Bhivare if (param_type != ISCSI_NET_PARAM) 577d8383b34SJitendra Bhivare return 0; 578d1d5ca88SJitendra Bhivare if (!beiscsi_hba_is_online(phba)) { 5799122e991SJitendra Bhivare beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 5809122e991SJitendra Bhivare "BS_%d : HBA in error 0x%lx\n", phba->state); 5813567f36aSJayamohan Kallickal return -EBUSY; 5823567f36aSJayamohan Kallickal } 5833567f36aSJayamohan Kallickal 5840e43895eSMike Christie switch (param) { 5850e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_ADDR: 5860e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_SUBNET: 5870e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_BOOTPROTO: 5880e43895eSMike Christie case ISCSI_NET_PARAM_IPV6_ADDR: 5896f72238eSJohn Soni Jose case ISCSI_NET_PARAM_VLAN_ENABLED: 5906f72238eSJohn Soni Jose case ISCSI_NET_PARAM_VLAN_ID: 5916f72238eSJohn Soni Jose case ISCSI_NET_PARAM_VLAN_PRIORITY: 59296b48b92SJitendra Bhivare len = __beiscsi_iface_get_param(phba, iface, param, buf); 5930e43895eSMike Christie break; 5940e43895eSMike Christie case ISCSI_NET_PARAM_IFACE_ENABLE: 595f7dd017eSJitendra Bhivare if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) 596f7dd017eSJitendra Bhivare len = sprintf(buf, "%s\n", 597f7dd017eSJitendra Bhivare phba->ipv4_iface ? "enable" : "disable"); 598f7dd017eSJitendra Bhivare else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) 599f7dd017eSJitendra Bhivare len = sprintf(buf, "%s\n", 600f7dd017eSJitendra Bhivare phba->ipv6_iface ? "enable" : "disable"); 6010e43895eSMike Christie break; 6020e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_GW: 6030e43895eSMike Christie memset(&gateway, 0, sizeof(gateway)); 604290aa376SJitendra Bhivare len = beiscsi_if_get_gw(phba, BEISCSI_IP_TYPE_V4, &gateway); 6050e43895eSMike Christie if (!len) 6060e43895eSMike Christie len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr); 6070e43895eSMike Christie break; 6080e43895eSMike Christie } 6090e43895eSMike Christie 6100e43895eSMike Christie return len; 6110e43895eSMike Christie } 6120e43895eSMike Christie 6136733b39aSJayamohan Kallickal /** 614c7f7fd5bSMike Christie * beiscsi_ep_get_param - get the iscsi parameter 615c7f7fd5bSMike Christie * @ep: pointer to iscsi ep 6166733b39aSJayamohan Kallickal * @param: parameter type identifier 6176733b39aSJayamohan Kallickal * @buf: buffer pointer 6186733b39aSJayamohan Kallickal * 6196733b39aSJayamohan Kallickal * returns iscsi parameter 6206733b39aSJayamohan Kallickal */ 621c7f7fd5bSMike Christie int beiscsi_ep_get_param(struct iscsi_endpoint *ep, 6226733b39aSJayamohan Kallickal enum iscsi_param param, char *buf) 6236733b39aSJayamohan Kallickal { 624c7f7fd5bSMike Christie struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; 625c5bf8889SJitendra Bhivare int len; 6266733b39aSJayamohan Kallickal 62799bc5d55SJohn Soni Jose beiscsi_log(beiscsi_ep->phba, KERN_INFO, 62899bc5d55SJohn Soni Jose BEISCSI_LOG_CONFIG, 62999bc5d55SJohn Soni Jose "BS_%d : In beiscsi_ep_get_param," 63099bc5d55SJohn Soni Jose " param= %d\n", param); 6316733b39aSJayamohan Kallickal 6326733b39aSJayamohan Kallickal switch (param) { 6336733b39aSJayamohan Kallickal case ISCSI_PARAM_CONN_PORT: 6346733b39aSJayamohan Kallickal len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport); 6356733b39aSJayamohan Kallickal break; 6366733b39aSJayamohan Kallickal case ISCSI_PARAM_CONN_ADDRESS: 637290aa376SJitendra Bhivare if (beiscsi_ep->ip_type == BEISCSI_IP_TYPE_V4) 6386733b39aSJayamohan Kallickal len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr); 6396733b39aSJayamohan Kallickal else 6406733b39aSJayamohan Kallickal len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr); 6416733b39aSJayamohan Kallickal break; 6426733b39aSJayamohan Kallickal default: 643c5bf8889SJitendra Bhivare len = -EPERM; 6446733b39aSJayamohan Kallickal } 6456733b39aSJayamohan Kallickal return len; 6466733b39aSJayamohan Kallickal } 6476733b39aSJayamohan Kallickal 6486733b39aSJayamohan Kallickal int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, 6496733b39aSJayamohan Kallickal enum iscsi_param param, char *buf, int buflen) 6506733b39aSJayamohan Kallickal { 6516733b39aSJayamohan Kallickal struct iscsi_conn *conn = cls_conn->dd_data; 6526733b39aSJayamohan Kallickal struct iscsi_session *session = conn->session; 65399bc5d55SJohn Soni Jose struct beiscsi_hba *phba = NULL; 6546733b39aSJayamohan Kallickal int ret; 6556733b39aSJayamohan Kallickal 65699bc5d55SJohn Soni Jose phba = ((struct beiscsi_conn *)conn->dd_data)->phba; 65799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 65899bc5d55SJohn Soni Jose "BS_%d : In beiscsi_conn_set_param," 65999bc5d55SJohn Soni Jose " param= %d\n", param); 66099bc5d55SJohn Soni Jose 6616733b39aSJayamohan Kallickal ret = iscsi_set_param(cls_conn, param, buf, buflen); 6626733b39aSJayamohan Kallickal if (ret) 6636733b39aSJayamohan Kallickal return ret; 6646733b39aSJayamohan Kallickal /* 6656733b39aSJayamohan Kallickal * If userspace tried to set the value to higher than we can 6666733b39aSJayamohan Kallickal * support override here. 6676733b39aSJayamohan Kallickal */ 6686733b39aSJayamohan Kallickal switch (param) { 6696733b39aSJayamohan Kallickal case ISCSI_PARAM_FIRST_BURST: 6706733b39aSJayamohan Kallickal if (session->first_burst > 8192) 6716733b39aSJayamohan Kallickal session->first_burst = 8192; 6726733b39aSJayamohan Kallickal break; 6736733b39aSJayamohan Kallickal case ISCSI_PARAM_MAX_RECV_DLENGTH: 6746733b39aSJayamohan Kallickal if (conn->max_recv_dlength > 65536) 6756733b39aSJayamohan Kallickal conn->max_recv_dlength = 65536; 6766733b39aSJayamohan Kallickal break; 6776733b39aSJayamohan Kallickal case ISCSI_PARAM_MAX_BURST: 678230dceb4SJayamohan Kallickal if (session->max_burst > 262144) 679230dceb4SJayamohan Kallickal session->max_burst = 262144; 6806733b39aSJayamohan Kallickal break; 68142f43c41SJayamohan Kallickal case ISCSI_PARAM_MAX_XMIT_DLENGTH: 6827331613eSJayamohan Kallickal if (conn->max_xmit_dlength > 65536) 68342f43c41SJayamohan Kallickal conn->max_xmit_dlength = 65536; 6846733b39aSJayamohan Kallickal default: 6856733b39aSJayamohan Kallickal return 0; 6866733b39aSJayamohan Kallickal } 6876733b39aSJayamohan Kallickal 6886733b39aSJayamohan Kallickal return 0; 6896733b39aSJayamohan Kallickal } 6906733b39aSJayamohan Kallickal 6916733b39aSJayamohan Kallickal /** 6922177199dSJohn Soni Jose * beiscsi_get_initname - Read Initiator Name from flash 6932177199dSJohn Soni Jose * @buf: buffer bointer 6942177199dSJohn Soni Jose * @phba: The device priv structure instance 6952177199dSJohn Soni Jose * 6962177199dSJohn Soni Jose * returns number of bytes 6972177199dSJohn Soni Jose */ 6982177199dSJohn Soni Jose static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba) 6992177199dSJohn Soni Jose { 7002177199dSJohn Soni Jose int rc; 701e175defeSJohn Soni Jose unsigned int tag; 7022177199dSJohn Soni Jose struct be_mcc_wrb *wrb; 7032177199dSJohn Soni Jose struct be_cmd_hba_name *resp; 7042177199dSJohn Soni Jose 7052177199dSJohn Soni Jose tag = be_cmd_get_initname(phba); 7062177199dSJohn Soni Jose if (!tag) { 70799bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 70899bc5d55SJohn Soni Jose "BS_%d : Getting Initiator Name Failed\n"); 70999bc5d55SJohn Soni Jose 7102177199dSJohn Soni Jose return -EBUSY; 711e175defeSJohn Soni Jose } 7122177199dSJohn Soni Jose 71388840332SJitendra Bhivare rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); 714e175defeSJohn Soni Jose if (rc) { 71599bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 71699bc5d55SJohn Soni Jose BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, 717e175defeSJohn Soni Jose "BS_%d : Initiator Name MBX Failed\n"); 718e175defeSJohn Soni Jose return rc; 7192177199dSJohn Soni Jose } 720e175defeSJohn Soni Jose 7212177199dSJohn Soni Jose resp = embedded_payload(wrb); 7222177199dSJohn Soni Jose rc = sprintf(buf, "%s\n", resp->initiator_name); 7232177199dSJohn Soni Jose return rc; 7242177199dSJohn Soni Jose } 7252177199dSJohn Soni Jose 7262177199dSJohn Soni Jose /** 727c62eef0dSJohn Soni Jose * beiscsi_get_port_state - Get the Port State 728c62eef0dSJohn Soni Jose * @shost : pointer to scsi_host structure 729c62eef0dSJohn Soni Jose * 730c62eef0dSJohn Soni Jose */ 731c62eef0dSJohn Soni Jose static void beiscsi_get_port_state(struct Scsi_Host *shost) 732c62eef0dSJohn Soni Jose { 733c62eef0dSJohn Soni Jose struct beiscsi_hba *phba = iscsi_host_priv(shost); 734c62eef0dSJohn Soni Jose struct iscsi_cls_host *ihost = shost->shost_data; 735c62eef0dSJohn Soni Jose 7369122e991SJitendra Bhivare ihost->port_state = test_bit(BEISCSI_HBA_LINK_UP, &phba->state) ? 737c62eef0dSJohn Soni Jose ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN; 738c62eef0dSJohn Soni Jose } 739c62eef0dSJohn Soni Jose 740c62eef0dSJohn Soni Jose /** 741c62eef0dSJohn Soni Jose * beiscsi_get_port_speed - Get the Port Speed from Adapter 742c62eef0dSJohn Soni Jose * @shost : pointer to scsi_host structure 743c62eef0dSJohn Soni Jose * 744c62eef0dSJohn Soni Jose */ 745048084c2SJitendra Bhivare static void beiscsi_get_port_speed(struct Scsi_Host *shost) 746c62eef0dSJohn Soni Jose { 747c62eef0dSJohn Soni Jose struct beiscsi_hba *phba = iscsi_host_priv(shost); 748c62eef0dSJohn Soni Jose struct iscsi_cls_host *ihost = shost->shost_data; 749c62eef0dSJohn Soni Jose 750048084c2SJitendra Bhivare switch (phba->port_speed) { 751c62eef0dSJohn Soni Jose case BE2ISCSI_LINK_SPEED_10MBPS: 752c62eef0dSJohn Soni Jose ihost->port_speed = ISCSI_PORT_SPEED_10MBPS; 753c62eef0dSJohn Soni Jose break; 754c62eef0dSJohn Soni Jose case BE2ISCSI_LINK_SPEED_100MBPS: 7553e393172SJayamohan Kallickal ihost->port_speed = ISCSI_PORT_SPEED_100MBPS; 756c62eef0dSJohn Soni Jose break; 757c62eef0dSJohn Soni Jose case BE2ISCSI_LINK_SPEED_1GBPS: 758c62eef0dSJohn Soni Jose ihost->port_speed = ISCSI_PORT_SPEED_1GBPS; 759c62eef0dSJohn Soni Jose break; 760c62eef0dSJohn Soni Jose case BE2ISCSI_LINK_SPEED_10GBPS: 761c62eef0dSJohn Soni Jose ihost->port_speed = ISCSI_PORT_SPEED_10GBPS; 762c62eef0dSJohn Soni Jose break; 763048084c2SJitendra Bhivare case BE2ISCSI_LINK_SPEED_25GBPS: 764048084c2SJitendra Bhivare ihost->port_speed = ISCSI_PORT_SPEED_25GBPS; 765048084c2SJitendra Bhivare break; 766048084c2SJitendra Bhivare case BE2ISCSI_LINK_SPEED_40GBPS: 767048084c2SJitendra Bhivare ihost->port_speed = ISCSI_PORT_SPEED_40GBPS; 768048084c2SJitendra Bhivare break; 769c62eef0dSJohn Soni Jose default: 770c62eef0dSJohn Soni Jose ihost->port_speed = ISCSI_PORT_SPEED_UNKNOWN; 771c62eef0dSJohn Soni Jose } 772c62eef0dSJohn Soni Jose } 773c62eef0dSJohn Soni Jose 774c62eef0dSJohn Soni Jose /** 7756733b39aSJayamohan Kallickal * beiscsi_get_host_param - get the iscsi parameter 7766733b39aSJayamohan Kallickal * @shost: pointer to scsi_host structure 7776733b39aSJayamohan Kallickal * @param: parameter type identifier 7786733b39aSJayamohan Kallickal * @buf: buffer pointer 7796733b39aSJayamohan Kallickal * 7806733b39aSJayamohan Kallickal * returns host parameter 7816733b39aSJayamohan Kallickal */ 7826733b39aSJayamohan Kallickal int beiscsi_get_host_param(struct Scsi_Host *shost, 7836733b39aSJayamohan Kallickal enum iscsi_host_param param, char *buf) 7846733b39aSJayamohan Kallickal { 7853093b048SMike Christie struct beiscsi_hba *phba = iscsi_host_priv(shost); 786b15d05b0SJayamohan Kallickal int status = 0; 7876733b39aSJayamohan Kallickal 788d1d5ca88SJitendra Bhivare if (!beiscsi_hba_is_online(phba)) { 78999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 7909122e991SJitendra Bhivare "BS_%d : HBA in error 0x%lx\n", phba->state); 7919122e991SJitendra Bhivare return -EBUSY; 7923567f36aSJayamohan Kallickal } 7939122e991SJitendra Bhivare beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 7949122e991SJitendra Bhivare "BS_%d : In beiscsi_get_host_param, param = %d\n", param); 79599bc5d55SJohn Soni Jose 7966733b39aSJayamohan Kallickal switch (param) { 7976733b39aSJayamohan Kallickal case ISCSI_HOST_PARAM_HWADDRESS: 798c7acc5b8SJayamohan Kallickal status = beiscsi_get_macaddr(buf, phba); 799c7acc5b8SJayamohan Kallickal if (status < 0) { 80099bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 80199bc5d55SJohn Soni Jose "BS_%d : beiscsi_get_macaddr Failed\n"); 802c7acc5b8SJayamohan Kallickal return status; 803c7acc5b8SJayamohan Kallickal } 804c7acc5b8SJayamohan Kallickal break; 8052177199dSJohn Soni Jose case ISCSI_HOST_PARAM_INITIATOR_NAME: 8062177199dSJohn Soni Jose status = beiscsi_get_initname(buf, phba); 8072177199dSJohn Soni Jose if (status < 0) { 80899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 80999bc5d55SJohn Soni Jose "BS_%d : Retreiving Initiator Name Failed\n"); 8102177199dSJohn Soni Jose return status; 8112177199dSJohn Soni Jose } 8122177199dSJohn Soni Jose break; 813c62eef0dSJohn Soni Jose case ISCSI_HOST_PARAM_PORT_STATE: 814c62eef0dSJohn Soni Jose beiscsi_get_port_state(shost); 815c62eef0dSJohn Soni Jose status = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost)); 816c62eef0dSJohn Soni Jose break; 817c62eef0dSJohn Soni Jose case ISCSI_HOST_PARAM_PORT_SPEED: 818048084c2SJitendra Bhivare beiscsi_get_port_speed(shost); 819c62eef0dSJohn Soni Jose status = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost)); 820c62eef0dSJohn Soni Jose break; 821c7acc5b8SJayamohan Kallickal default: 822c7acc5b8SJayamohan Kallickal return iscsi_host_get_param(shost, param, buf); 823c7acc5b8SJayamohan Kallickal } 824b15d05b0SJayamohan Kallickal return status; 825c7acc5b8SJayamohan Kallickal } 826c7acc5b8SJayamohan Kallickal 827c7acc5b8SJayamohan Kallickal int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) 828c7acc5b8SJayamohan Kallickal { 8290e43895eSMike Christie struct be_cmd_get_nic_conf_resp resp; 830c7acc5b8SJayamohan Kallickal int rc; 831c7acc5b8SJayamohan Kallickal 8326c83185aSJayamohan Kallickal if (phba->mac_addr_set) 833df5d0e6eSJohn Soni Jose return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); 834c7acc5b8SJayamohan Kallickal 8350e43895eSMike Christie memset(&resp, 0, sizeof(resp)); 8360e43895eSMike Christie rc = mgmt_get_nic_conf(phba, &resp); 8370e43895eSMike Christie if (rc) 838c7acc5b8SJayamohan Kallickal return rc; 839c7acc5b8SJayamohan Kallickal 8406c83185aSJayamohan Kallickal phba->mac_addr_set = true; 8410e43895eSMike Christie memcpy(phba->mac_address, resp.mac_address, ETH_ALEN); 8420e43895eSMike Christie return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); 8430e43895eSMike Christie } 8446733b39aSJayamohan Kallickal 8456733b39aSJayamohan Kallickal /** 8466733b39aSJayamohan Kallickal * beiscsi_conn_get_stats - get the iscsi stats 8476733b39aSJayamohan Kallickal * @cls_conn: pointer to iscsi cls conn 8486733b39aSJayamohan Kallickal * @stats: pointer to iscsi_stats structure 8496733b39aSJayamohan Kallickal * 8506733b39aSJayamohan Kallickal * returns iscsi stats 8516733b39aSJayamohan Kallickal */ 8526733b39aSJayamohan Kallickal void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, 8536733b39aSJayamohan Kallickal struct iscsi_stats *stats) 8546733b39aSJayamohan Kallickal { 8556733b39aSJayamohan Kallickal struct iscsi_conn *conn = cls_conn->dd_data; 85699bc5d55SJohn Soni Jose struct beiscsi_hba *phba = NULL; 8576733b39aSJayamohan Kallickal 85899bc5d55SJohn Soni Jose phba = ((struct beiscsi_conn *)conn->dd_data)->phba; 85999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 86099bc5d55SJohn Soni Jose "BS_%d : In beiscsi_conn_get_stats\n"); 86199bc5d55SJohn Soni Jose 8626733b39aSJayamohan Kallickal stats->txdata_octets = conn->txdata_octets; 8636733b39aSJayamohan Kallickal stats->rxdata_octets = conn->rxdata_octets; 8646733b39aSJayamohan Kallickal stats->dataout_pdus = conn->dataout_pdus_cnt; 8656733b39aSJayamohan Kallickal stats->scsirsp_pdus = conn->scsirsp_pdus_cnt; 8666733b39aSJayamohan Kallickal stats->scsicmd_pdus = conn->scsicmd_pdus_cnt; 8676733b39aSJayamohan Kallickal stats->datain_pdus = conn->datain_pdus_cnt; 8686733b39aSJayamohan Kallickal stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; 8696733b39aSJayamohan Kallickal stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt; 8706733b39aSJayamohan Kallickal stats->r2t_pdus = conn->r2t_pdus_cnt; 8716733b39aSJayamohan Kallickal stats->digest_err = 0; 8726733b39aSJayamohan Kallickal stats->timeout_err = 0; 873915aafd8SMike Christie stats->custom_length = 1; 8746733b39aSJayamohan Kallickal strcpy(stats->custom[0].desc, "eh_abort_cnt"); 8756733b39aSJayamohan Kallickal stats->custom[0].value = conn->eh_abort_cnt; 8766733b39aSJayamohan Kallickal } 8776733b39aSJayamohan Kallickal 8786733b39aSJayamohan Kallickal /** 8796733b39aSJayamohan Kallickal * beiscsi_set_params_for_offld - get the parameters for offload 8806733b39aSJayamohan Kallickal * @beiscsi_conn: pointer to beiscsi_conn 8816733b39aSJayamohan Kallickal * @params: pointer to offload_params structure 8826733b39aSJayamohan Kallickal */ 8836733b39aSJayamohan Kallickal static void beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn, 8846733b39aSJayamohan Kallickal struct beiscsi_offload_params *params) 8856733b39aSJayamohan Kallickal { 8866733b39aSJayamohan Kallickal struct iscsi_conn *conn = beiscsi_conn->conn; 8876733b39aSJayamohan Kallickal struct iscsi_session *session = conn->session; 8886733b39aSJayamohan Kallickal 8896733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length, 8906733b39aSJayamohan Kallickal params, session->max_burst); 8916733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_beiscsi_offload_params, 8926733b39aSJayamohan Kallickal max_send_data_segment_length, params, 8936733b39aSJayamohan Kallickal conn->max_xmit_dlength); 8946733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length, 8956733b39aSJayamohan Kallickal params, session->first_burst); 8966733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_beiscsi_offload_params, erl, params, 8976733b39aSJayamohan Kallickal session->erl); 8986733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params, 8996733b39aSJayamohan Kallickal conn->datadgst_en); 9006733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params, 9016733b39aSJayamohan Kallickal conn->hdrdgst_en); 9026733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params, 9036733b39aSJayamohan Kallickal session->initial_r2t_en); 9046733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params, 9056733b39aSJayamohan Kallickal session->imm_data_en); 906acb9693cSJohn Soni Jose AMAP_SET_BITS(struct amap_beiscsi_offload_params, 907acb9693cSJohn Soni Jose data_seq_inorder, params, 908acb9693cSJohn Soni Jose session->dataseq_inorder_en); 909acb9693cSJohn Soni Jose AMAP_SET_BITS(struct amap_beiscsi_offload_params, 910acb9693cSJohn Soni Jose pdu_seq_inorder, params, 911acb9693cSJohn Soni Jose session->pdu_inorder_en); 912acb9693cSJohn Soni Jose AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_r2t, params, 913acb9693cSJohn Soni Jose session->max_r2t); 9146733b39aSJayamohan Kallickal AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params, 9156733b39aSJayamohan Kallickal (conn->exp_statsn - 1)); 9167331613eSJayamohan Kallickal AMAP_SET_BITS(struct amap_beiscsi_offload_params, 9177331613eSJayamohan Kallickal max_recv_data_segment_length, params, 9187331613eSJayamohan Kallickal conn->max_recv_dlength); 9197331613eSJayamohan Kallickal 9206733b39aSJayamohan Kallickal } 9216733b39aSJayamohan Kallickal 9226733b39aSJayamohan Kallickal /** 9236733b39aSJayamohan Kallickal * beiscsi_conn_start - offload of session to chip 9246733b39aSJayamohan Kallickal * @cls_conn: pointer to beiscsi_conn 9256733b39aSJayamohan Kallickal */ 9266733b39aSJayamohan Kallickal int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) 9276733b39aSJayamohan Kallickal { 9286733b39aSJayamohan Kallickal struct iscsi_conn *conn = cls_conn->dd_data; 9296733b39aSJayamohan Kallickal struct beiscsi_conn *beiscsi_conn = conn->dd_data; 9306733b39aSJayamohan Kallickal struct beiscsi_endpoint *beiscsi_ep; 9316733b39aSJayamohan Kallickal struct beiscsi_offload_params params; 9323567f36aSJayamohan Kallickal struct beiscsi_hba *phba; 9336733b39aSJayamohan Kallickal 9343567f36aSJayamohan Kallickal phba = ((struct beiscsi_conn *)conn->dd_data)->phba; 9353567f36aSJayamohan Kallickal 936d1d5ca88SJitendra Bhivare if (!beiscsi_hba_is_online(phba)) { 9379122e991SJitendra Bhivare beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 9389122e991SJitendra Bhivare "BS_%d : HBA in error 0x%lx\n", phba->state); 9393567f36aSJayamohan Kallickal return -EBUSY; 9403567f36aSJayamohan Kallickal } 9419122e991SJitendra Bhivare beiscsi_log(beiscsi_conn->phba, KERN_INFO, BEISCSI_LOG_CONFIG, 9429122e991SJitendra Bhivare "BS_%d : In beiscsi_conn_start\n"); 94399bc5d55SJohn Soni Jose 9446733b39aSJayamohan Kallickal memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); 9456733b39aSJayamohan Kallickal beiscsi_ep = beiscsi_conn->ep; 9466733b39aSJayamohan Kallickal if (!beiscsi_ep) 94799bc5d55SJohn Soni Jose beiscsi_log(beiscsi_conn->phba, KERN_ERR, 94899bc5d55SJohn Soni Jose BEISCSI_LOG_CONFIG, 94999bc5d55SJohn Soni Jose "BS_%d : In beiscsi_conn_start , no beiscsi_ep\n"); 9506733b39aSJayamohan Kallickal 9516733b39aSJayamohan Kallickal beiscsi_conn->login_in_progress = 0; 9526733b39aSJayamohan Kallickal beiscsi_set_params_for_offld(beiscsi_conn, ¶ms); 9536733b39aSJayamohan Kallickal beiscsi_offload_connection(beiscsi_conn, ¶ms); 9546733b39aSJayamohan Kallickal iscsi_conn_start(cls_conn); 9556733b39aSJayamohan Kallickal return 0; 9566733b39aSJayamohan Kallickal } 9576733b39aSJayamohan Kallickal 9586733b39aSJayamohan Kallickal /** 9596733b39aSJayamohan Kallickal * beiscsi_get_cid - Allocate a cid 9606733b39aSJayamohan Kallickal * @phba: The phba instance 9616733b39aSJayamohan Kallickal */ 9626733b39aSJayamohan Kallickal static int beiscsi_get_cid(struct beiscsi_hba *phba) 9636733b39aSJayamohan Kallickal { 9640a3db7c0SJayamohan Kallickal uint16_t cid_avlbl_ulp0, cid_avlbl_ulp1; 965*413f3656SJitendra Bhivare unsigned short cid, cid_from_ulp; 966*413f3656SJitendra Bhivare struct ulp_cid_info *cid_info; 9676733b39aSJayamohan Kallickal 9680a3db7c0SJayamohan Kallickal /* Find the ULP which has more CID available */ 9690a3db7c0SJayamohan Kallickal cid_avlbl_ulp0 = (phba->cid_array_info[BEISCSI_ULP0]) ? 9700a3db7c0SJayamohan Kallickal BEISCSI_ULP0_AVLBL_CID(phba) : 0; 9710a3db7c0SJayamohan Kallickal cid_avlbl_ulp1 = (phba->cid_array_info[BEISCSI_ULP1]) ? 9720a3db7c0SJayamohan Kallickal BEISCSI_ULP1_AVLBL_CID(phba) : 0; 9730a3db7c0SJayamohan Kallickal cid_from_ulp = (cid_avlbl_ulp0 > cid_avlbl_ulp1) ? 9740a3db7c0SJayamohan Kallickal BEISCSI_ULP0 : BEISCSI_ULP1; 975*413f3656SJitendra Bhivare /** 976*413f3656SJitendra Bhivare * If iSCSI protocol is loaded only on ULP 0, and when cid_avlbl_ulp 977*413f3656SJitendra Bhivare * is ZERO for both, ULP 1 is returned. 978*413f3656SJitendra Bhivare * Check if ULP is loaded before getting new CID. 979*413f3656SJitendra Bhivare */ 980*413f3656SJitendra Bhivare if (!test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported)) 981*413f3656SJitendra Bhivare return BE_INVALID_CID; 9820a3db7c0SJayamohan Kallickal 9830a3db7c0SJayamohan Kallickal cid_info = phba->cid_array_info[cid_from_ulp]; 984*413f3656SJitendra Bhivare cid = cid_info->cid_array[cid_info->cid_alloc]; 985*413f3656SJitendra Bhivare if (!cid_info->avlbl_cids || cid == BE_INVALID_CID) { 986*413f3656SJitendra Bhivare __beiscsi_log(phba, KERN_ERR, 987*413f3656SJitendra Bhivare "BS_%d : failed to get cid: available %u:%u\n", 988*413f3656SJitendra Bhivare cid_info->avlbl_cids, cid_info->cid_free); 989*413f3656SJitendra Bhivare return BE_INVALID_CID; 9900a3db7c0SJayamohan Kallickal } 991*413f3656SJitendra Bhivare /* empty the slot */ 992*413f3656SJitendra Bhivare cid_info->cid_array[cid_info->cid_alloc++] = BE_INVALID_CID; 993*413f3656SJitendra Bhivare if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT(phba, cid_from_ulp)) 994*413f3656SJitendra Bhivare cid_info->cid_alloc = 0; 995*413f3656SJitendra Bhivare cid_info->avlbl_cids--; 9966733b39aSJayamohan Kallickal return cid; 9976733b39aSJayamohan Kallickal } 9986733b39aSJayamohan Kallickal 9996733b39aSJayamohan Kallickal /** 1000fa95d206SMike Christie * beiscsi_put_cid - Free the cid 1001fa95d206SMike Christie * @phba: The phba for which the cid is being freed 1002fa95d206SMike Christie * @cid: The cid to free 1003fa95d206SMike Christie */ 1004fa95d206SMike Christie static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) 1005fa95d206SMike Christie { 10060a3db7c0SJayamohan Kallickal uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); 1007*413f3656SJitendra Bhivare struct hwi_wrb_context *pwrb_context; 1008*413f3656SJitendra Bhivare struct hwi_controller *phwi_ctrlr; 1009*413f3656SJitendra Bhivare struct ulp_cid_info *cid_info; 1010*413f3656SJitendra Bhivare uint16_t cid_post_ulp; 10110a3db7c0SJayamohan Kallickal 10120a3db7c0SJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 10130a3db7c0SJayamohan Kallickal pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; 10140a3db7c0SJayamohan Kallickal cid_post_ulp = pwrb_context->ulp_num; 10150a3db7c0SJayamohan Kallickal 10160a3db7c0SJayamohan Kallickal cid_info = phba->cid_array_info[cid_post_ulp]; 1017*413f3656SJitendra Bhivare /* fill only in empty slot */ 1018*413f3656SJitendra Bhivare if (cid_info->cid_array[cid_info->cid_free] != BE_INVALID_CID) { 1019*413f3656SJitendra Bhivare __beiscsi_log(phba, KERN_ERR, 1020*413f3656SJitendra Bhivare "BS_%d : failed to put cid %u: available %u:%u\n", 1021*413f3656SJitendra Bhivare cid, cid_info->avlbl_cids, cid_info->cid_free); 1022*413f3656SJitendra Bhivare return; 1023*413f3656SJitendra Bhivare } 10240a3db7c0SJayamohan Kallickal cid_info->cid_array[cid_info->cid_free++] = cid; 10250a3db7c0SJayamohan Kallickal if (cid_info->cid_free == BEISCSI_GET_CID_COUNT(phba, cid_post_ulp)) 10260a3db7c0SJayamohan Kallickal cid_info->cid_free = 0; 1027*413f3656SJitendra Bhivare cid_info->avlbl_cids++; 1028fa95d206SMike Christie } 1029fa95d206SMike Christie 1030fa95d206SMike Christie /** 1031fa95d206SMike Christie * beiscsi_free_ep - free endpoint 1032fa95d206SMike Christie * @ep: pointer to iscsi endpoint structure 1033fa95d206SMike Christie */ 1034fa95d206SMike Christie static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) 1035fa95d206SMike Christie { 1036fa95d206SMike Christie struct beiscsi_hba *phba = beiscsi_ep->phba; 103743f388b0SJayamohan Kallickal struct beiscsi_conn *beiscsi_conn; 1038fa95d206SMike Christie 1039fa95d206SMike Christie beiscsi_put_cid(phba, beiscsi_ep->ep_cid); 1040fa95d206SMike Christie beiscsi_ep->phba = NULL; 1041*413f3656SJitendra Bhivare /* clear this to track freeing in beiscsi_ep_disconnect */ 1042*413f3656SJitendra Bhivare phba->ep_array[BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid)] = NULL; 104343f388b0SJayamohan Kallickal 104443f388b0SJayamohan Kallickal /** 104543f388b0SJayamohan Kallickal * Check if any connection resource allocated by driver 104643f388b0SJayamohan Kallickal * is to be freed.This case occurs when target redirection 104743f388b0SJayamohan Kallickal * or connection retry is done. 104843f388b0SJayamohan Kallickal **/ 104943f388b0SJayamohan Kallickal if (!beiscsi_ep->conn) 105043f388b0SJayamohan Kallickal return; 105143f388b0SJayamohan Kallickal 105243f388b0SJayamohan Kallickal beiscsi_conn = beiscsi_ep->conn; 1053*413f3656SJitendra Bhivare /** 1054*413f3656SJitendra Bhivare * Break ep->conn link here so that completions after 1055*413f3656SJitendra Bhivare * this are ignored. 1056*413f3656SJitendra Bhivare */ 1057*413f3656SJitendra Bhivare beiscsi_ep->conn = NULL; 105843f388b0SJayamohan Kallickal if (beiscsi_conn->login_in_progress) { 10594a4a11b9SJayamohan Kallickal beiscsi_free_mgmt_task_handles(beiscsi_conn, 10604a4a11b9SJayamohan Kallickal beiscsi_conn->task); 106143f388b0SJayamohan Kallickal beiscsi_conn->login_in_progress = 0; 106243f388b0SJayamohan Kallickal } 1063fa95d206SMike Christie } 1064fa95d206SMike Christie 1065fa95d206SMike Christie /** 10666733b39aSJayamohan Kallickal * beiscsi_open_conn - Ask FW to open a TCP connection 10676733b39aSJayamohan Kallickal * @ep: endpoint to be used 10686733b39aSJayamohan Kallickal * @src_addr: The source IP address 10696733b39aSJayamohan Kallickal * @dst_addr: The Destination IP address 10706733b39aSJayamohan Kallickal * 10716733b39aSJayamohan Kallickal * Asks the FW to open a TCP connection 10726733b39aSJayamohan Kallickal */ 10736733b39aSJayamohan Kallickal static int beiscsi_open_conn(struct iscsi_endpoint *ep, 10746733b39aSJayamohan Kallickal struct sockaddr *src_addr, 10756733b39aSJayamohan Kallickal struct sockaddr *dst_addr, int non_blocking) 10766733b39aSJayamohan Kallickal { 10776733b39aSJayamohan Kallickal struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; 10786733b39aSJayamohan Kallickal struct beiscsi_hba *phba = beiscsi_ep->phba; 1079756d29c8SJayamohan Kallickal struct tcp_connect_and_offload_out *ptcpcnct_out; 10803cbb7a74SJayamohan Kallickal struct be_dma_mem nonemb_cmd; 1081b3c202dcSJayamohan Kallickal unsigned int tag, req_memsize; 1082d3ad2bb3SJayamohan Kallickal int ret = -ENOMEM; 10836733b39aSJayamohan Kallickal 108499bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 108599bc5d55SJohn Soni Jose "BS_%d : In beiscsi_open_conn\n"); 108699bc5d55SJohn Soni Jose 10876733b39aSJayamohan Kallickal beiscsi_ep->ep_cid = beiscsi_get_cid(phba); 1088*413f3656SJitendra Bhivare if (beiscsi_ep->ep_cid == BE_INVALID_CID) { 108999bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 109099bc5d55SJohn Soni Jose "BS_%d : No free cid available\n"); 10916733b39aSJayamohan Kallickal return ret; 10926733b39aSJayamohan Kallickal } 109399bc5d55SJohn Soni Jose 109499bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 109599bc5d55SJohn Soni Jose "BS_%d : In beiscsi_open_conn, ep_cid=%d\n", 10966733b39aSJayamohan Kallickal beiscsi_ep->ep_cid); 109799bc5d55SJohn Soni Jose 1098a7909b39SJayamohan Kallickal phba->ep_array[BE_GET_CRI_FROM_CID 1099a7909b39SJayamohan Kallickal (beiscsi_ep->ep_cid)] = ep; 11006733b39aSJayamohan Kallickal 11016733b39aSJayamohan Kallickal beiscsi_ep->cid_vld = 0; 1102b3c202dcSJayamohan Kallickal 1103b3c202dcSJayamohan Kallickal if (is_chip_be2_be3r(phba)) 1104b3c202dcSJayamohan Kallickal req_memsize = sizeof(struct tcp_connect_and_offload_in); 1105b3c202dcSJayamohan Kallickal else 1106b3c202dcSJayamohan Kallickal req_memsize = sizeof(struct tcp_connect_and_offload_in_v1); 1107b3c202dcSJayamohan Kallickal 11083cbb7a74SJayamohan Kallickal nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, 1109b3c202dcSJayamohan Kallickal req_memsize, 11103cbb7a74SJayamohan Kallickal &nonemb_cmd.dma); 11113cbb7a74SJayamohan Kallickal if (nonemb_cmd.va == NULL) { 111299bc5d55SJohn Soni Jose 111399bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 111499bc5d55SJohn Soni Jose "BS_%d : Failed to allocate memory for" 111599bc5d55SJohn Soni Jose " mgmt_open_connection\n"); 111699bc5d55SJohn Soni Jose 1117a7909b39SJayamohan Kallickal beiscsi_free_ep(beiscsi_ep); 11183cbb7a74SJayamohan Kallickal return -ENOMEM; 11193cbb7a74SJayamohan Kallickal } 1120b3c202dcSJayamohan Kallickal nonemb_cmd.size = req_memsize; 11213cbb7a74SJayamohan Kallickal memset(nonemb_cmd.va, 0, nonemb_cmd.size); 11223cbb7a74SJayamohan Kallickal tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd); 1123fa1261c4SJitendra Bhivare if (!tag) { 112499bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 112599bc5d55SJohn Soni Jose "BS_%d : mgmt_open_connection Failed for cid=%d\n", 1126756d29c8SJayamohan Kallickal beiscsi_ep->ep_cid); 112799bc5d55SJohn Soni Jose 11283cbb7a74SJayamohan Kallickal pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, 11293cbb7a74SJayamohan Kallickal nonemb_cmd.va, nonemb_cmd.dma); 1130a7909b39SJayamohan Kallickal beiscsi_free_ep(beiscsi_ep); 11311f92638fSJayamohan Kallickal return -EAGAIN; 1132756d29c8SJayamohan Kallickal } 1133e175defeSJohn Soni Jose 113488840332SJitendra Bhivare ret = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd); 1135e175defeSJohn Soni Jose if (ret) { 113699bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, 113799bc5d55SJohn Soni Jose BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, 1138e175defeSJohn Soni Jose "BS_%d : mgmt_open_connection Failed"); 113999bc5d55SJohn Soni Jose 11401957aa7fSJayamohan Kallickal if (ret != -EBUSY) 11413cbb7a74SJayamohan Kallickal pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, 11423cbb7a74SJayamohan Kallickal nonemb_cmd.va, nonemb_cmd.dma); 11431957aa7fSJayamohan Kallickal 1144a7909b39SJayamohan Kallickal beiscsi_free_ep(beiscsi_ep); 11451957aa7fSJayamohan Kallickal return ret; 1146e175defeSJohn Soni Jose } 1147756d29c8SJayamohan Kallickal 11481e234bbbSJayamohan Kallickal ptcpcnct_out = (struct tcp_connect_and_offload_out *)nonemb_cmd.va; 1149756d29c8SJayamohan Kallickal beiscsi_ep = ep->dd_data; 1150756d29c8SJayamohan Kallickal beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle; 1151756d29c8SJayamohan Kallickal beiscsi_ep->cid_vld = 1; 115299bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 115399bc5d55SJohn Soni Jose "BS_%d : mgmt_open_connection Success\n"); 1154e175defeSJohn Soni Jose 11553cbb7a74SJayamohan Kallickal pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, 11563cbb7a74SJayamohan Kallickal nonemb_cmd.va, nonemb_cmd.dma); 1157756d29c8SJayamohan Kallickal return 0; 11586733b39aSJayamohan Kallickal } 11596733b39aSJayamohan Kallickal 11606733b39aSJayamohan Kallickal /** 11616733b39aSJayamohan Kallickal * beiscsi_ep_connect - Ask chip to create TCP Conn 11626733b39aSJayamohan Kallickal * @scsi_host: Pointer to scsi_host structure 11636733b39aSJayamohan Kallickal * @dst_addr: The IP address of Target 11646733b39aSJayamohan Kallickal * @non_blocking: blocking or non-blocking call 11656733b39aSJayamohan Kallickal * 11666733b39aSJayamohan Kallickal * This routines first asks chip to create a connection and then allocates an EP 11676733b39aSJayamohan Kallickal */ 11686733b39aSJayamohan Kallickal struct iscsi_endpoint * 11696733b39aSJayamohan Kallickal beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, 11706733b39aSJayamohan Kallickal int non_blocking) 11716733b39aSJayamohan Kallickal { 11726733b39aSJayamohan Kallickal struct beiscsi_hba *phba; 11736733b39aSJayamohan Kallickal struct beiscsi_endpoint *beiscsi_ep; 11746733b39aSJayamohan Kallickal struct iscsi_endpoint *ep; 11756733b39aSJayamohan Kallickal int ret; 11766733b39aSJayamohan Kallickal 11779122e991SJitendra Bhivare if (!shost) { 11786733b39aSJayamohan Kallickal ret = -ENXIO; 11799122e991SJitendra Bhivare pr_err("beiscsi_ep_connect shost is NULL\n"); 11806733b39aSJayamohan Kallickal return ERR_PTR(ret); 11816733b39aSJayamohan Kallickal } 1182bfead3b2SJayamohan Kallickal 11839122e991SJitendra Bhivare phba = iscsi_host_priv(shost); 1184d1d5ca88SJitendra Bhivare if (!beiscsi_hba_is_online(phba)) { 1185cf6e3c64SJayamohan Kallickal ret = -EIO; 11869122e991SJitendra Bhivare beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 11879122e991SJitendra Bhivare "BS_%d : HBA in error 0x%lx\n", phba->state); 1188cf6e3c64SJayamohan Kallickal return ERR_PTR(ret); 1189cf6e3c64SJayamohan Kallickal } 11909122e991SJitendra Bhivare if (!test_bit(BEISCSI_HBA_LINK_UP, &phba->state)) { 1191bfead3b2SJayamohan Kallickal ret = -EBUSY; 11928359c79bSJohn Soni Jose beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, 11938359c79bSJohn Soni Jose "BS_%d : The Adapter Port state is Down!!!\n"); 1194bfead3b2SJayamohan Kallickal return ERR_PTR(ret); 1195bfead3b2SJayamohan Kallickal } 1196bfead3b2SJayamohan Kallickal 11976733b39aSJayamohan Kallickal ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint)); 11986733b39aSJayamohan Kallickal if (!ep) { 11996733b39aSJayamohan Kallickal ret = -ENOMEM; 12006733b39aSJayamohan Kallickal return ERR_PTR(ret); 12016733b39aSJayamohan Kallickal } 12026733b39aSJayamohan Kallickal 12036733b39aSJayamohan Kallickal beiscsi_ep = ep->dd_data; 12046733b39aSJayamohan Kallickal beiscsi_ep->phba = phba; 1205c2462288SJayamohan Kallickal beiscsi_ep->openiscsi_ep = ep; 1206f5ed7bd4SJayamohan Kallickal ret = beiscsi_open_conn(ep, NULL, dst_addr, non_blocking); 1207f5ed7bd4SJayamohan Kallickal if (ret) { 120899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 120999bc5d55SJohn Soni Jose "BS_%d : Failed in beiscsi_open_conn\n"); 12106733b39aSJayamohan Kallickal goto free_ep; 12116733b39aSJayamohan Kallickal } 12126733b39aSJayamohan Kallickal 12136733b39aSJayamohan Kallickal return ep; 12146733b39aSJayamohan Kallickal 12156733b39aSJayamohan Kallickal free_ep: 1216fa95d206SMike Christie iscsi_destroy_endpoint(ep); 12176733b39aSJayamohan Kallickal return ERR_PTR(ret); 12186733b39aSJayamohan Kallickal } 12196733b39aSJayamohan Kallickal 12206733b39aSJayamohan Kallickal /** 12216733b39aSJayamohan Kallickal * beiscsi_ep_poll - Poll to see if connection is established 12226733b39aSJayamohan Kallickal * @ep: endpoint to be used 12236733b39aSJayamohan Kallickal * @timeout_ms: timeout specified in millisecs 12246733b39aSJayamohan Kallickal * 12256733b39aSJayamohan Kallickal * Poll to see if TCP connection established 12266733b39aSJayamohan Kallickal */ 12276733b39aSJayamohan Kallickal int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) 12286733b39aSJayamohan Kallickal { 12296733b39aSJayamohan Kallickal struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; 12306733b39aSJayamohan Kallickal 123199bc5d55SJohn Soni Jose beiscsi_log(beiscsi_ep->phba, KERN_INFO, BEISCSI_LOG_CONFIG, 123299bc5d55SJohn Soni Jose "BS_%d : In beiscsi_ep_poll\n"); 123399bc5d55SJohn Soni Jose 12346733b39aSJayamohan Kallickal if (beiscsi_ep->cid_vld == 1) 12356733b39aSJayamohan Kallickal return 1; 12366733b39aSJayamohan Kallickal else 12376733b39aSJayamohan Kallickal return 0; 12386733b39aSJayamohan Kallickal } 12396733b39aSJayamohan Kallickal 12406733b39aSJayamohan Kallickal /** 1241b7ab35b1SJayamohan Kallickal * beiscsi_flush_cq()- Flush the CQ created. 1242b7ab35b1SJayamohan Kallickal * @phba: ptr device priv structure. 1243b7ab35b1SJayamohan Kallickal * 1244b7ab35b1SJayamohan Kallickal * Before the connection resource are freed flush 1245b7ab35b1SJayamohan Kallickal * all the CQ enteries 1246b7ab35b1SJayamohan Kallickal **/ 1247b7ab35b1SJayamohan Kallickal static void beiscsi_flush_cq(struct beiscsi_hba *phba) 1248b7ab35b1SJayamohan Kallickal { 1249b7ab35b1SJayamohan Kallickal uint16_t i; 1250b7ab35b1SJayamohan Kallickal struct be_eq_obj *pbe_eq; 1251b7ab35b1SJayamohan Kallickal struct hwi_controller *phwi_ctrlr; 1252b7ab35b1SJayamohan Kallickal struct hwi_context_memory *phwi_context; 1253b7ab35b1SJayamohan Kallickal 1254b7ab35b1SJayamohan Kallickal phwi_ctrlr = phba->phwi_ctrlr; 1255b7ab35b1SJayamohan Kallickal phwi_context = phwi_ctrlr->phwi_ctxt; 1256b7ab35b1SJayamohan Kallickal 1257b7ab35b1SJayamohan Kallickal for (i = 0; i < phba->num_cpus; i++) { 1258b7ab35b1SJayamohan Kallickal pbe_eq = &phwi_context->be_eq[i]; 1259511cbce2SChristoph Hellwig irq_poll_disable(&pbe_eq->iopoll); 12601094cf68SJitendra Bhivare beiscsi_process_cq(pbe_eq, BE2_MAX_NUM_CQ_PROC); 1261511cbce2SChristoph Hellwig irq_poll_enable(&pbe_eq->iopoll); 1262b7ab35b1SJayamohan Kallickal } 1263b7ab35b1SJayamohan Kallickal } 1264b7ab35b1SJayamohan Kallickal 1265b7ab35b1SJayamohan Kallickal /** 12666733b39aSJayamohan Kallickal * beiscsi_close_conn - Upload the connection 12676733b39aSJayamohan Kallickal * @ep: The iscsi endpoint 12686733b39aSJayamohan Kallickal * @flag: The type of connection closure 12696733b39aSJayamohan Kallickal */ 1270c2462288SJayamohan Kallickal static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag) 12716733b39aSJayamohan Kallickal { 12726733b39aSJayamohan Kallickal int ret = 0; 1273756d29c8SJayamohan Kallickal unsigned int tag; 12746733b39aSJayamohan Kallickal struct beiscsi_hba *phba = beiscsi_ep->phba; 12756733b39aSJayamohan Kallickal 1276756d29c8SJayamohan Kallickal tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag); 1277756d29c8SJayamohan Kallickal if (!tag) { 127899bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 127999bc5d55SJohn Soni Jose "BS_%d : upload failed for cid 0x%x\n", 12806733b39aSJayamohan Kallickal beiscsi_ep->ep_cid); 128199bc5d55SJohn Soni Jose 1282d3ad2bb3SJayamohan Kallickal ret = -EAGAIN; 12836733b39aSJayamohan Kallickal } 1284e175defeSJohn Soni Jose 128588840332SJitendra Bhivare ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); 1286b7ab35b1SJayamohan Kallickal 1287b7ab35b1SJayamohan Kallickal /* Flush the CQ entries */ 1288b7ab35b1SJayamohan Kallickal beiscsi_flush_cq(phba); 1289b7ab35b1SJayamohan Kallickal 12906733b39aSJayamohan Kallickal return ret; 12916733b39aSJayamohan Kallickal } 12926733b39aSJayamohan Kallickal 12936733b39aSJayamohan Kallickal /** 1294fa95d206SMike Christie * beiscsi_ep_disconnect - Tears down the TCP connection 1295fa95d206SMike Christie * @ep: endpoint to be used 1296fa95d206SMike Christie * 1297fa95d206SMike Christie * Tears down the TCP connection 12986733b39aSJayamohan Kallickal */ 1299fa95d206SMike Christie void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) 13006733b39aSJayamohan Kallickal { 1301fa95d206SMike Christie struct beiscsi_conn *beiscsi_conn; 13026733b39aSJayamohan Kallickal struct beiscsi_endpoint *beiscsi_ep; 1303fa95d206SMike Christie struct beiscsi_hba *phba; 1304756d29c8SJayamohan Kallickal unsigned int tag; 13050a513dd8SJohn Soni Jose uint8_t mgmt_invalidate_flag, tcp_upload_flag; 13066733b39aSJayamohan Kallickal unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; 1307*413f3656SJitendra Bhivare uint16_t cri_index; 13086733b39aSJayamohan Kallickal 1309fa95d206SMike Christie beiscsi_ep = ep->dd_data; 1310fa95d206SMike Christie phba = beiscsi_ep->phba; 131199bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 1312*413f3656SJitendra Bhivare "BS_%d : In beiscsi_ep_disconnect for ep_cid = %u\n", 1313fa95d206SMike Christie beiscsi_ep->ep_cid); 1314fa95d206SMike Christie 1315*413f3656SJitendra Bhivare cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid); 1316*413f3656SJitendra Bhivare if (!phba->ep_array[cri_index]) { 1317*413f3656SJitendra Bhivare __beiscsi_log(phba, KERN_ERR, 1318*413f3656SJitendra Bhivare "BS_%d : ep_array at %u cid %u empty\n", 1319*413f3656SJitendra Bhivare cri_index, 1320*413f3656SJitendra Bhivare beiscsi_ep->ep_cid); 1321*413f3656SJitendra Bhivare return; 1322*413f3656SJitendra Bhivare } 1323*413f3656SJitendra Bhivare 13240a513dd8SJohn Soni Jose if (beiscsi_ep->conn) { 1325fa95d206SMike Christie beiscsi_conn = beiscsi_ep->conn; 1326fa95d206SMike Christie iscsi_suspend_queue(beiscsi_conn->conn); 13270a513dd8SJohn Soni Jose mgmt_invalidate_flag = ~BEISCSI_NO_RST_ISSUE; 13280a513dd8SJohn Soni Jose tcp_upload_flag = CONNECTION_UPLOAD_GRACEFUL; 13290a513dd8SJohn Soni Jose } else { 13300a513dd8SJohn Soni Jose mgmt_invalidate_flag = BEISCSI_NO_RST_ISSUE; 13310a513dd8SJohn Soni Jose tcp_upload_flag = CONNECTION_UPLOAD_ABORT; 13320a513dd8SJohn Soni Jose } 1333fa95d206SMike Christie 1334d1d5ca88SJitendra Bhivare if (!beiscsi_hba_is_online(phba)) { 13359122e991SJitendra Bhivare beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, 13369122e991SJitendra Bhivare "BS_%d : HBA in error 0x%lx\n", phba->state); 13373567f36aSJayamohan Kallickal goto free_ep; 13383567f36aSJayamohan Kallickal } 13393567f36aSJayamohan Kallickal 1340756d29c8SJayamohan Kallickal tag = mgmt_invalidate_connection(phba, beiscsi_ep, 13410a513dd8SJohn Soni Jose beiscsi_ep->ep_cid, 13420a513dd8SJohn Soni Jose mgmt_invalidate_flag, 13436733b39aSJayamohan Kallickal savecfg_flag); 1344756d29c8SJayamohan Kallickal if (!tag) { 134599bc5d55SJohn Soni Jose beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, 13460a513dd8SJohn Soni Jose "BS_%d : mgmt_invalidate_connection Failed for cid=%d\n", 13476733b39aSJayamohan Kallickal beiscsi_ep->ep_cid); 13486733b39aSJayamohan Kallickal } 1349fa95d206SMike Christie 135088840332SJitendra Bhivare beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); 13510a513dd8SJohn Soni Jose beiscsi_close_conn(beiscsi_ep, tcp_upload_flag); 13523567f36aSJayamohan Kallickal free_ep: 13539343be74SJayamohan Kallickal msleep(BEISCSI_LOGOUT_SYNC_DELAY); 1354c2462288SJayamohan Kallickal beiscsi_free_ep(beiscsi_ep); 1355*413f3656SJitendra Bhivare if (!phba->conn_table[cri_index]) 1356*413f3656SJitendra Bhivare __beiscsi_log(phba, KERN_ERR, 1357*413f3656SJitendra Bhivare "BS_%d : conn_table empty at %u: cid %u\n", 1358*413f3656SJitendra Bhivare cri_index, 1359*413f3656SJitendra Bhivare beiscsi_ep->ep_cid); 1360*413f3656SJitendra Bhivare phba->conn_table[cri_index] = NULL; 1361fa95d206SMike Christie iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); 13626733b39aSJayamohan Kallickal } 13633128c6c7SMike Christie 136496b48b92SJitendra Bhivare umode_t beiscsi_attr_is_visible(int param_type, int param) 13653128c6c7SMike Christie { 13663128c6c7SMike Christie switch (param_type) { 13670e43895eSMike Christie case ISCSI_NET_PARAM: 13680e43895eSMike Christie switch (param) { 13690e43895eSMike Christie case ISCSI_NET_PARAM_IFACE_ENABLE: 13700e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_ADDR: 13710e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_SUBNET: 13720e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_BOOTPROTO: 13730e43895eSMike Christie case ISCSI_NET_PARAM_IPV4_GW: 13740e43895eSMike Christie case ISCSI_NET_PARAM_IPV6_ADDR: 13756f72238eSJohn Soni Jose case ISCSI_NET_PARAM_VLAN_ID: 13766f72238eSJohn Soni Jose case ISCSI_NET_PARAM_VLAN_PRIORITY: 13776f72238eSJohn Soni Jose case ISCSI_NET_PARAM_VLAN_ENABLED: 13780e43895eSMike Christie return S_IRUGO; 13790e43895eSMike Christie default: 13800e43895eSMike Christie return 0; 13810e43895eSMike Christie } 1382f27fb2efSMike Christie case ISCSI_HOST_PARAM: 1383f27fb2efSMike Christie switch (param) { 1384f27fb2efSMike Christie case ISCSI_HOST_PARAM_HWADDRESS: 1385c62eef0dSJohn Soni Jose case ISCSI_HOST_PARAM_INITIATOR_NAME: 1386c62eef0dSJohn Soni Jose case ISCSI_HOST_PARAM_PORT_STATE: 1387c62eef0dSJohn Soni Jose case ISCSI_HOST_PARAM_PORT_SPEED: 1388f27fb2efSMike Christie return S_IRUGO; 1389f27fb2efSMike Christie default: 1390f27fb2efSMike Christie return 0; 1391f27fb2efSMike Christie } 13923128c6c7SMike Christie case ISCSI_PARAM: 13933128c6c7SMike Christie switch (param) { 13943128c6c7SMike Christie case ISCSI_PARAM_MAX_RECV_DLENGTH: 13953128c6c7SMike Christie case ISCSI_PARAM_MAX_XMIT_DLENGTH: 13963128c6c7SMike Christie case ISCSI_PARAM_HDRDGST_EN: 13973128c6c7SMike Christie case ISCSI_PARAM_DATADGST_EN: 13983128c6c7SMike Christie case ISCSI_PARAM_CONN_ADDRESS: 13993128c6c7SMike Christie case ISCSI_PARAM_CONN_PORT: 14003128c6c7SMike Christie case ISCSI_PARAM_EXP_STATSN: 14013128c6c7SMike Christie case ISCSI_PARAM_PERSISTENT_ADDRESS: 14023128c6c7SMike Christie case ISCSI_PARAM_PERSISTENT_PORT: 14033128c6c7SMike Christie case ISCSI_PARAM_PING_TMO: 14043128c6c7SMike Christie case ISCSI_PARAM_RECV_TMO: 14051d063c17SMike Christie case ISCSI_PARAM_INITIAL_R2T_EN: 14061d063c17SMike Christie case ISCSI_PARAM_MAX_R2T: 14071d063c17SMike Christie case ISCSI_PARAM_IMM_DATA_EN: 14081d063c17SMike Christie case ISCSI_PARAM_FIRST_BURST: 14091d063c17SMike Christie case ISCSI_PARAM_MAX_BURST: 14101d063c17SMike Christie case ISCSI_PARAM_PDU_INORDER_EN: 14111d063c17SMike Christie case ISCSI_PARAM_DATASEQ_INORDER_EN: 14121d063c17SMike Christie case ISCSI_PARAM_ERL: 14131d063c17SMike Christie case ISCSI_PARAM_TARGET_NAME: 14141d063c17SMike Christie case ISCSI_PARAM_TPGT: 14151d063c17SMike Christie case ISCSI_PARAM_USERNAME: 14161d063c17SMike Christie case ISCSI_PARAM_PASSWORD: 14171d063c17SMike Christie case ISCSI_PARAM_USERNAME_IN: 14181d063c17SMike Christie case ISCSI_PARAM_PASSWORD_IN: 14191d063c17SMike Christie case ISCSI_PARAM_FAST_ABORT: 14201d063c17SMike Christie case ISCSI_PARAM_ABORT_TMO: 14211d063c17SMike Christie case ISCSI_PARAM_LU_RESET_TMO: 14221d063c17SMike Christie case ISCSI_PARAM_IFACE_NAME: 14231d063c17SMike Christie case ISCSI_PARAM_INITIATOR_NAME: 14243128c6c7SMike Christie return S_IRUGO; 14253128c6c7SMike Christie default: 14263128c6c7SMike Christie return 0; 14273128c6c7SMike Christie } 14283128c6c7SMike Christie } 14293128c6c7SMike Christie 14303128c6c7SMike Christie return 0; 14313128c6c7SMike Christie } 1432