LCOV - code coverage report
Current view: top level - drivers/scsi/snic - snic_ctl.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 119 0.0 %
Date: 2022-04-01 14:17:54 Functions: 0 5 0.0 %
Branches: 0 54 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright 2014 Cisco Systems, Inc.  All rights reserved.
       3                 :            :  *
       4                 :            :  * This program is free software; you may redistribute it and/or modify
       5                 :            :  * it under the terms of the GNU General Public License as published by
       6                 :            :  * the Free Software Foundation; version 2 of the License.
       7                 :            :  *
       8                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       9                 :            :  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      10                 :            :  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      11                 :            :  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
      12                 :            :  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
      13                 :            :  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
      14                 :            :  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      15                 :            :  * SOFTWARE.
      16                 :            :  */
      17                 :            : 
      18                 :            : #include <linux/errno.h>
      19                 :            : #include <linux/pci.h>
      20                 :            : #include <linux/slab.h>
      21                 :            : 
      22                 :            : #include <linux/interrupt.h>
      23                 :            : #include <linux/workqueue.h>
      24                 :            : #include <linux/spinlock.h>
      25                 :            : #include <linux/mempool.h>
      26                 :            : #include <scsi/scsi_tcq.h>
      27                 :            : #include <linux/ctype.h>
      28                 :            : 
      29                 :            : #include "snic_io.h"
      30                 :            : #include "snic.h"
      31                 :            : #include "cq_enet_desc.h"
      32                 :            : #include "snic_fwint.h"
      33                 :            : 
      34                 :            : /*
      35                 :            :  * snic_handle_link : Handles link flaps.
      36                 :            :  */
      37                 :            : void
      38                 :          0 : snic_handle_link(struct work_struct *work)
      39                 :            : {
      40                 :          0 :         struct snic *snic = container_of(work, struct snic, link_work);
      41                 :            : 
      42         [ #  # ]:          0 :         if (snic->config.xpt_type == SNIC_DAS)
      43                 :            :                 return;
      44                 :            : 
      45                 :          0 :         snic->link_status = svnic_dev_link_status(snic->vdev);
      46                 :          0 :         snic->link_down_cnt = svnic_dev_link_down_cnt(snic->vdev);
      47         [ #  # ]:          0 :         SNIC_HOST_INFO(snic->shost, "Link Event: Link %s.\n",
      48                 :            :                        ((snic->link_status) ? "Up" : "Down"));
      49                 :            : 
      50                 :          0 :         SNIC_ASSERT_NOT_IMPL(1);
      51                 :            : }
      52                 :            : 
      53                 :            : 
      54                 :            : /*
      55                 :            :  * snic_ver_enc : Encodes version str to int
      56                 :            :  * version string is similar to netmask string
      57                 :            :  */
      58                 :            : static int
      59                 :          0 : snic_ver_enc(const char *s)
      60                 :            : {
      61                 :          0 :         int v[4] = {0};
      62                 :          0 :         int  i = 0, x = 0;
      63                 :          0 :         char c;
      64                 :          0 :         const char *p = s;
      65                 :            : 
      66                 :            :         /* validate version string */
      67   [ #  #  #  # ]:          0 :         if ((strlen(s) > 15) || (strlen(s) < 7))
      68                 :          0 :                 goto end;
      69                 :            : 
      70         [ #  # ]:          0 :         while ((c = *p++)) {
      71         [ #  # ]:          0 :                 if (c == '.') {
      72                 :          0 :                         i++;
      73                 :          0 :                         continue;
      74                 :            :                 }
      75                 :            : 
      76   [ #  #  #  # ]:          0 :                 if (i > 3 || !isdigit(c))
      77                 :          0 :                         goto end;
      78                 :            : 
      79                 :          0 :                 v[i] = v[i] * 10 + (c - '0');
      80                 :            :         }
      81                 :            : 
      82                 :            :         /* validate sub version numbers */
      83         [ #  # ]:          0 :         for (i = 3; i >= 0; i--)
      84         [ #  # ]:          0 :                 if (v[i] > 0xff)
      85                 :          0 :                         goto end;
      86                 :            : 
      87                 :          0 :         x |= (v[0] << 24) | v[1] << 16 | v[2] << 8 | v[3];
      88                 :            : 
      89                 :            : end:
      90         [ #  # ]:          0 :         if (x == 0) {
      91                 :          0 :                 SNIC_ERR("Invalid version string [%s].\n", s);
      92                 :            : 
      93                 :          0 :                 return -1;
      94                 :            :         }
      95                 :            : 
      96                 :            :         return x;
      97                 :            : } /* end of snic_ver_enc */
      98                 :            : 
      99                 :            : /*
     100                 :            :  * snic_qeueue_exch_ver_req :
     101                 :            :  *
     102                 :            :  * Queues Exchange Version Request, to communicate host information
     103                 :            :  * in return, it gets firmware version details
     104                 :            :  */
     105                 :            : int
     106                 :          0 : snic_queue_exch_ver_req(struct snic *snic)
     107                 :            : {
     108                 :          0 :         struct snic_req_info *rqi = NULL;
     109                 :          0 :         struct snic_host_req *req = NULL;
     110                 :          0 :         u32 ver = 0;
     111                 :          0 :         int ret = 0;
     112                 :            : 
     113                 :          0 :         SNIC_HOST_INFO(snic->shost, "Exch Ver Req Preparing...\n");
     114                 :            : 
     115                 :          0 :         rqi = snic_req_init(snic, 0);
     116         [ #  # ]:          0 :         if (!rqi) {
     117                 :          0 :                 SNIC_HOST_ERR(snic->shost,
     118                 :            :                               "Queuing Exch Ver Req failed, err = %d\n",
     119                 :            :                               ret);
     120                 :            : 
     121                 :          0 :                 ret = -ENOMEM;
     122                 :          0 :                 goto error;
     123                 :            :         }
     124                 :            : 
     125                 :          0 :         req = rqi_to_req(rqi);
     126                 :            : 
     127                 :            :         /* Initialize snic_host_req */
     128                 :          0 :         snic_io_hdr_enc(&req->hdr, SNIC_REQ_EXCH_VER, 0, SCSI_NO_TAG,
     129                 :          0 :                         snic->config.hid, 0, (ulong)rqi);
     130                 :          0 :         ver = snic_ver_enc(SNIC_DRV_VERSION);
     131                 :          0 :         req->u.exch_ver.drvr_ver = cpu_to_le32(ver);
     132                 :          0 :         req->u.exch_ver.os_type = cpu_to_le32(SNIC_OS_LINUX);
     133                 :            : 
     134                 :          0 :         snic_handle_untagged_req(snic, rqi);
     135                 :            : 
     136                 :          0 :         ret = snic_queue_wq_desc(snic, req, sizeof(*req));
     137         [ #  # ]:          0 :         if (ret) {
     138                 :          0 :                 snic_release_untagged_req(snic, rqi);
     139                 :          0 :                 SNIC_HOST_ERR(snic->shost,
     140                 :            :                               "Queuing Exch Ver Req failed, err = %d\n",
     141                 :            :                               ret);
     142                 :          0 :                 goto error;
     143                 :            :         }
     144                 :            : 
     145                 :          0 :         SNIC_HOST_INFO(snic->shost, "Exch Ver Req is issued. ret = %d\n", ret);
     146                 :            : 
     147                 :          0 : error:
     148                 :          0 :         return ret;
     149                 :            : } /* end of snic_queue_exch_ver_req */
     150                 :            : 
     151                 :            : /*
     152                 :            :  * snic_io_exch_ver_cmpl_handler
     153                 :            :  */
     154                 :            : int
     155                 :          0 : snic_io_exch_ver_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq)
     156                 :            : {
     157                 :          0 :         struct snic_req_info *rqi = NULL;
     158                 :          0 :         struct snic_exch_ver_rsp *exv_cmpl = &fwreq->u.exch_ver_cmpl;
     159                 :          0 :         u8 typ, hdr_stat;
     160                 :          0 :         u32 cmnd_id, hid, max_sgs;
     161                 :          0 :         ulong ctx = 0;
     162                 :          0 :         unsigned long flags;
     163                 :          0 :         int ret = 0;
     164                 :            : 
     165                 :          0 :         SNIC_HOST_INFO(snic->shost, "Exch Ver Compl Received.\n");
     166         [ #  # ]:          0 :         snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx);
     167   [ #  #  #  # ]:          0 :         SNIC_BUG_ON(snic->config.hid != hid);
     168                 :          0 :         rqi = (struct snic_req_info *) ctx;
     169                 :            : 
     170         [ #  # ]:          0 :         if (hdr_stat) {
     171                 :          0 :                 SNIC_HOST_ERR(snic->shost,
     172                 :            :                               "Exch Ver Completed w/ err status %d\n",
     173                 :            :                               hdr_stat);
     174                 :            : 
     175                 :          0 :                 goto exch_cmpl_end;
     176                 :            :         }
     177                 :            : 
     178                 :          0 :         spin_lock_irqsave(&snic->snic_lock, flags);
     179                 :          0 :         snic->fwinfo.fw_ver = le32_to_cpu(exv_cmpl->version);
     180                 :          0 :         snic->fwinfo.hid = le32_to_cpu(exv_cmpl->hid);
     181                 :          0 :         snic->fwinfo.max_concur_ios = le32_to_cpu(exv_cmpl->max_concur_ios);
     182                 :          0 :         snic->fwinfo.max_sgs_per_cmd = le32_to_cpu(exv_cmpl->max_sgs_per_cmd);
     183                 :          0 :         snic->fwinfo.max_io_sz = le32_to_cpu(exv_cmpl->max_io_sz);
     184                 :          0 :         snic->fwinfo.max_tgts = le32_to_cpu(exv_cmpl->max_tgts);
     185                 :          0 :         snic->fwinfo.io_tmo = le16_to_cpu(exv_cmpl->io_timeout);
     186                 :            : 
     187                 :          0 :         SNIC_HOST_INFO(snic->shost,
     188                 :            :                        "vers %u hid %u max_concur_ios %u max_sgs_per_cmd %u max_io_sz %u max_tgts %u fw tmo %u\n",
     189                 :            :                        snic->fwinfo.fw_ver,
     190                 :            :                        snic->fwinfo.hid,
     191                 :            :                        snic->fwinfo.max_concur_ios,
     192                 :            :                        snic->fwinfo.max_sgs_per_cmd,
     193                 :            :                        snic->fwinfo.max_io_sz,
     194                 :            :                        snic->fwinfo.max_tgts,
     195                 :            :                        snic->fwinfo.io_tmo);
     196                 :            : 
     197                 :          0 :         SNIC_HOST_INFO(snic->shost,
     198                 :            :                        "HBA Capabilities = 0x%x\n",
     199                 :            :                        le32_to_cpu(exv_cmpl->hba_cap));
     200                 :            : 
     201                 :            :         /* Updating SGList size */
     202                 :          0 :         max_sgs = snic->fwinfo.max_sgs_per_cmd;
     203         [ #  # ]:          0 :         if (max_sgs && max_sgs < SNIC_MAX_SG_DESC_CNT) {
     204                 :          0 :                 snic->shost->sg_tablesize = max_sgs;
     205                 :          0 :                 SNIC_HOST_INFO(snic->shost, "Max SGs set to %d\n",
     206                 :            :                                snic->shost->sg_tablesize);
     207         [ #  # ]:          0 :         } else if (max_sgs > snic->shost->sg_tablesize) {
     208                 :          0 :                 SNIC_HOST_INFO(snic->shost,
     209                 :            :                                "Target type %d Supports Larger Max SGList %d than driver's Max SG List %d.\n",
     210                 :            :                                snic->config.xpt_type, max_sgs,
     211                 :            :                                snic->shost->sg_tablesize);
     212                 :            :         }
     213                 :            : 
     214         [ #  # ]:          0 :         if (snic->shost->can_queue > snic->fwinfo.max_concur_ios)
     215                 :          0 :                 snic->shost->can_queue = snic->fwinfo.max_concur_ios;
     216                 :            : 
     217                 :          0 :         snic->shost->max_sectors = snic->fwinfo.max_io_sz >> 9;
     218         [ #  # ]:          0 :         if (snic->fwinfo.wait)
     219                 :          0 :                 complete(snic->fwinfo.wait);
     220                 :            : 
     221                 :          0 :         spin_unlock_irqrestore(&snic->snic_lock, flags);
     222                 :            : 
     223                 :          0 : exch_cmpl_end:
     224                 :          0 :         snic_release_untagged_req(snic, rqi);
     225                 :            : 
     226                 :          0 :         SNIC_HOST_INFO(snic->shost, "Exch_cmpl Done, hdr_stat %d.\n", hdr_stat);
     227                 :            : 
     228                 :          0 :         return ret;
     229                 :            : } /* end of snic_io_exch_ver_cmpl_handler */
     230                 :            : 
     231                 :            : /*
     232                 :            :  * snic_get_conf
     233                 :            :  *
     234                 :            :  * Synchronous call, and Retrieves snic params.
     235                 :            :  */
     236                 :            : int
     237                 :          0 : snic_get_conf(struct snic *snic)
     238                 :            : {
     239                 :          0 :         DECLARE_COMPLETION_ONSTACK(wait);
     240                 :          0 :         unsigned long flags;
     241                 :          0 :         int ret;
     242                 :          0 :         int nr_retries = 3;
     243                 :            : 
     244                 :          0 :         SNIC_HOST_INFO(snic->shost, "Retrieving snic params.\n");
     245                 :          0 :         spin_lock_irqsave(&snic->snic_lock, flags);
     246                 :          0 :         memset(&snic->fwinfo, 0, sizeof(snic->fwinfo));
     247                 :          0 :         snic->fwinfo.wait = &wait;
     248                 :          0 :         spin_unlock_irqrestore(&snic->snic_lock, flags);
     249                 :            : 
     250                 :            :         /* Additional delay to handle HW Resource initialization. */
     251                 :          0 :         msleep(50);
     252                 :            : 
     253                 :            :         /*
     254                 :            :          * Exch ver req can be ignored by FW, if HW Resource initialization
     255                 :            :          * is in progress, Hence retry.
     256                 :            :          */
     257                 :          0 :         do {
     258                 :          0 :                 ret = snic_queue_exch_ver_req(snic);
     259         [ #  # ]:          0 :                 if (ret)
     260                 :          0 :                         return ret;
     261                 :            : 
     262                 :          0 :                 wait_for_completion_timeout(&wait, msecs_to_jiffies(2000));
     263                 :          0 :                 spin_lock_irqsave(&snic->snic_lock, flags);
     264         [ #  # ]:          0 :                 ret = (snic->fwinfo.fw_ver != 0) ? 0 : -ETIMEDOUT;
     265                 :          0 :                 if (ret)
     266                 :          0 :                         SNIC_HOST_ERR(snic->shost,
     267                 :            :                                       "Failed to retrieve snic params,\n");
     268                 :            : 
     269                 :            :                 /* Unset fwinfo.wait, on success or on last retry */
     270   [ #  #  #  # ]:          0 :                 if (ret == 0 || nr_retries == 1)
     271                 :          0 :                         snic->fwinfo.wait = NULL;
     272                 :            : 
     273                 :          0 :                 spin_unlock_irqrestore(&snic->snic_lock, flags);
     274   [ #  #  #  # ]:          0 :         } while (ret && --nr_retries);
     275                 :            : 
     276                 :            :         return ret;
     277                 :            : } /* end of snic_get_info */

Generated by: LCOV version 1.14