1*c8806b6cSNarsimhulu Musini /* 2*c8806b6cSNarsimhulu Musini * Copyright 2014 Cisco Systems, Inc. All rights reserved. 3*c8806b6cSNarsimhulu Musini * 4*c8806b6cSNarsimhulu Musini * This program is free software; you may redistribute it and/or modify 5*c8806b6cSNarsimhulu Musini * it under the terms of the GNU General Public License as published by 6*c8806b6cSNarsimhulu Musini * the Free Software Foundation; version 2 of the License. 7*c8806b6cSNarsimhulu Musini * 8*c8806b6cSNarsimhulu Musini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 9*c8806b6cSNarsimhulu Musini * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 10*c8806b6cSNarsimhulu Musini * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 11*c8806b6cSNarsimhulu Musini * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 12*c8806b6cSNarsimhulu Musini * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 13*c8806b6cSNarsimhulu Musini * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14*c8806b6cSNarsimhulu Musini * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 15*c8806b6cSNarsimhulu Musini * SOFTWARE. 16*c8806b6cSNarsimhulu Musini */ 17*c8806b6cSNarsimhulu Musini 18*c8806b6cSNarsimhulu Musini #include <linux/errno.h> 19*c8806b6cSNarsimhulu Musini #include <linux/types.h> 20*c8806b6cSNarsimhulu Musini #include <linux/pci.h> 21*c8806b6cSNarsimhulu Musini 22*c8806b6cSNarsimhulu Musini #include "wq_enet_desc.h" 23*c8806b6cSNarsimhulu Musini #include "cq_enet_desc.h" 24*c8806b6cSNarsimhulu Musini #include "vnic_resource.h" 25*c8806b6cSNarsimhulu Musini #include "vnic_dev.h" 26*c8806b6cSNarsimhulu Musini #include "vnic_wq.h" 27*c8806b6cSNarsimhulu Musini #include "vnic_cq.h" 28*c8806b6cSNarsimhulu Musini #include "vnic_intr.h" 29*c8806b6cSNarsimhulu Musini #include "vnic_stats.h" 30*c8806b6cSNarsimhulu Musini #include "snic.h" 31*c8806b6cSNarsimhulu Musini 32*c8806b6cSNarsimhulu Musini int 33*c8806b6cSNarsimhulu Musini snic_get_vnic_config(struct snic *snic) 34*c8806b6cSNarsimhulu Musini { 35*c8806b6cSNarsimhulu Musini struct vnic_snic_config *c = &snic->config; 36*c8806b6cSNarsimhulu Musini int ret; 37*c8806b6cSNarsimhulu Musini 38*c8806b6cSNarsimhulu Musini #define GET_CONFIG(m) \ 39*c8806b6cSNarsimhulu Musini do { \ 40*c8806b6cSNarsimhulu Musini ret = svnic_dev_spec(snic->vdev, \ 41*c8806b6cSNarsimhulu Musini offsetof(struct vnic_snic_config, m), \ 42*c8806b6cSNarsimhulu Musini sizeof(c->m), \ 43*c8806b6cSNarsimhulu Musini &c->m); \ 44*c8806b6cSNarsimhulu Musini if (ret) { \ 45*c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost, \ 46*c8806b6cSNarsimhulu Musini "Error getting %s, %d\n", #m, ret); \ 47*c8806b6cSNarsimhulu Musini return ret; \ 48*c8806b6cSNarsimhulu Musini } \ 49*c8806b6cSNarsimhulu Musini } while (0) 50*c8806b6cSNarsimhulu Musini 51*c8806b6cSNarsimhulu Musini GET_CONFIG(wq_enet_desc_count); 52*c8806b6cSNarsimhulu Musini GET_CONFIG(maxdatafieldsize); 53*c8806b6cSNarsimhulu Musini GET_CONFIG(intr_timer); 54*c8806b6cSNarsimhulu Musini GET_CONFIG(intr_timer_type); 55*c8806b6cSNarsimhulu Musini GET_CONFIG(flags); 56*c8806b6cSNarsimhulu Musini GET_CONFIG(io_throttle_count); 57*c8806b6cSNarsimhulu Musini GET_CONFIG(port_down_timeout); 58*c8806b6cSNarsimhulu Musini GET_CONFIG(port_down_io_retries); 59*c8806b6cSNarsimhulu Musini GET_CONFIG(luns_per_tgt); 60*c8806b6cSNarsimhulu Musini GET_CONFIG(xpt_type); 61*c8806b6cSNarsimhulu Musini GET_CONFIG(hid); 62*c8806b6cSNarsimhulu Musini 63*c8806b6cSNarsimhulu Musini c->wq_enet_desc_count = min_t(u32, 64*c8806b6cSNarsimhulu Musini VNIC_SNIC_WQ_DESCS_MAX, 65*c8806b6cSNarsimhulu Musini max_t(u32, 66*c8806b6cSNarsimhulu Musini VNIC_SNIC_WQ_DESCS_MIN, 67*c8806b6cSNarsimhulu Musini c->wq_enet_desc_count)); 68*c8806b6cSNarsimhulu Musini 69*c8806b6cSNarsimhulu Musini c->wq_enet_desc_count = ALIGN(c->wq_enet_desc_count, 16); 70*c8806b6cSNarsimhulu Musini 71*c8806b6cSNarsimhulu Musini c->maxdatafieldsize = min_t(u32, 72*c8806b6cSNarsimhulu Musini VNIC_SNIC_MAXDATAFIELDSIZE_MAX, 73*c8806b6cSNarsimhulu Musini max_t(u32, 74*c8806b6cSNarsimhulu Musini VNIC_SNIC_MAXDATAFIELDSIZE_MIN, 75*c8806b6cSNarsimhulu Musini c->maxdatafieldsize)); 76*c8806b6cSNarsimhulu Musini 77*c8806b6cSNarsimhulu Musini c->io_throttle_count = min_t(u32, 78*c8806b6cSNarsimhulu Musini VNIC_SNIC_IO_THROTTLE_COUNT_MAX, 79*c8806b6cSNarsimhulu Musini max_t(u32, 80*c8806b6cSNarsimhulu Musini VNIC_SNIC_IO_THROTTLE_COUNT_MIN, 81*c8806b6cSNarsimhulu Musini c->io_throttle_count)); 82*c8806b6cSNarsimhulu Musini 83*c8806b6cSNarsimhulu Musini c->port_down_timeout = min_t(u32, 84*c8806b6cSNarsimhulu Musini VNIC_SNIC_PORT_DOWN_TIMEOUT_MAX, 85*c8806b6cSNarsimhulu Musini c->port_down_timeout); 86*c8806b6cSNarsimhulu Musini 87*c8806b6cSNarsimhulu Musini c->port_down_io_retries = min_t(u32, 88*c8806b6cSNarsimhulu Musini VNIC_SNIC_PORT_DOWN_IO_RETRIES_MAX, 89*c8806b6cSNarsimhulu Musini c->port_down_io_retries); 90*c8806b6cSNarsimhulu Musini 91*c8806b6cSNarsimhulu Musini c->luns_per_tgt = min_t(u32, 92*c8806b6cSNarsimhulu Musini VNIC_SNIC_LUNS_PER_TARGET_MAX, 93*c8806b6cSNarsimhulu Musini max_t(u32, 94*c8806b6cSNarsimhulu Musini VNIC_SNIC_LUNS_PER_TARGET_MIN, 95*c8806b6cSNarsimhulu Musini c->luns_per_tgt)); 96*c8806b6cSNarsimhulu Musini 97*c8806b6cSNarsimhulu Musini c->intr_timer = min_t(u32, VNIC_INTR_TIMER_MAX, c->intr_timer); 98*c8806b6cSNarsimhulu Musini 99*c8806b6cSNarsimhulu Musini SNIC_INFO("vNIC resources wq %d\n", c->wq_enet_desc_count); 100*c8806b6cSNarsimhulu Musini SNIC_INFO("vNIC mtu %d intr timer %d\n", 101*c8806b6cSNarsimhulu Musini c->maxdatafieldsize, 102*c8806b6cSNarsimhulu Musini c->intr_timer); 103*c8806b6cSNarsimhulu Musini 104*c8806b6cSNarsimhulu Musini SNIC_INFO("vNIC flags 0x%x luns per tgt %d\n", 105*c8806b6cSNarsimhulu Musini c->flags, 106*c8806b6cSNarsimhulu Musini c->luns_per_tgt); 107*c8806b6cSNarsimhulu Musini 108*c8806b6cSNarsimhulu Musini SNIC_INFO("vNIC io throttle count %d\n", c->io_throttle_count); 109*c8806b6cSNarsimhulu Musini SNIC_INFO("vNIC port down timeout %d port down io retries %d\n", 110*c8806b6cSNarsimhulu Musini c->port_down_timeout, 111*c8806b6cSNarsimhulu Musini c->port_down_io_retries); 112*c8806b6cSNarsimhulu Musini 113*c8806b6cSNarsimhulu Musini SNIC_INFO("vNIC back end type = %d\n", c->xpt_type); 114*c8806b6cSNarsimhulu Musini SNIC_INFO("vNIC hid = %d\n", c->hid); 115*c8806b6cSNarsimhulu Musini 116*c8806b6cSNarsimhulu Musini return 0; 117*c8806b6cSNarsimhulu Musini } 118*c8806b6cSNarsimhulu Musini 119*c8806b6cSNarsimhulu Musini void 120*c8806b6cSNarsimhulu Musini snic_get_res_counts(struct snic *snic) 121*c8806b6cSNarsimhulu Musini { 122*c8806b6cSNarsimhulu Musini snic->wq_count = svnic_dev_get_res_count(snic->vdev, RES_TYPE_WQ); 123*c8806b6cSNarsimhulu Musini SNIC_BUG_ON(snic->wq_count == 0); 124*c8806b6cSNarsimhulu Musini snic->cq_count = svnic_dev_get_res_count(snic->vdev, RES_TYPE_CQ); 125*c8806b6cSNarsimhulu Musini SNIC_BUG_ON(snic->cq_count == 0); 126*c8806b6cSNarsimhulu Musini snic->intr_count = svnic_dev_get_res_count(snic->vdev, 127*c8806b6cSNarsimhulu Musini RES_TYPE_INTR_CTRL); 128*c8806b6cSNarsimhulu Musini SNIC_BUG_ON(snic->intr_count == 0); 129*c8806b6cSNarsimhulu Musini } 130*c8806b6cSNarsimhulu Musini 131*c8806b6cSNarsimhulu Musini void 132*c8806b6cSNarsimhulu Musini snic_free_vnic_res(struct snic *snic) 133*c8806b6cSNarsimhulu Musini { 134*c8806b6cSNarsimhulu Musini unsigned int i; 135*c8806b6cSNarsimhulu Musini 136*c8806b6cSNarsimhulu Musini for (i = 0; i < snic->wq_count; i++) 137*c8806b6cSNarsimhulu Musini svnic_wq_free(&snic->wq[i]); 138*c8806b6cSNarsimhulu Musini 139*c8806b6cSNarsimhulu Musini for (i = 0; i < snic->cq_count; i++) 140*c8806b6cSNarsimhulu Musini svnic_cq_free(&snic->cq[i]); 141*c8806b6cSNarsimhulu Musini 142*c8806b6cSNarsimhulu Musini for (i = 0; i < snic->intr_count; i++) 143*c8806b6cSNarsimhulu Musini svnic_intr_free(&snic->intr[i]); 144*c8806b6cSNarsimhulu Musini } 145*c8806b6cSNarsimhulu Musini 146*c8806b6cSNarsimhulu Musini int 147*c8806b6cSNarsimhulu Musini snic_alloc_vnic_res(struct snic *snic) 148*c8806b6cSNarsimhulu Musini { 149*c8806b6cSNarsimhulu Musini enum vnic_dev_intr_mode intr_mode; 150*c8806b6cSNarsimhulu Musini unsigned int mask_on_assertion; 151*c8806b6cSNarsimhulu Musini unsigned int intr_offset; 152*c8806b6cSNarsimhulu Musini unsigned int err_intr_enable; 153*c8806b6cSNarsimhulu Musini unsigned int err_intr_offset; 154*c8806b6cSNarsimhulu Musini unsigned int i; 155*c8806b6cSNarsimhulu Musini int ret; 156*c8806b6cSNarsimhulu Musini 157*c8806b6cSNarsimhulu Musini intr_mode = svnic_dev_get_intr_mode(snic->vdev); 158*c8806b6cSNarsimhulu Musini 159*c8806b6cSNarsimhulu Musini SNIC_INFO("vNIC interrupt mode: %s\n", 160*c8806b6cSNarsimhulu Musini ((intr_mode == VNIC_DEV_INTR_MODE_INTX) ? 161*c8806b6cSNarsimhulu Musini "Legacy PCI INTx" : 162*c8806b6cSNarsimhulu Musini ((intr_mode == VNIC_DEV_INTR_MODE_MSI) ? 163*c8806b6cSNarsimhulu Musini "MSI" : 164*c8806b6cSNarsimhulu Musini ((intr_mode == VNIC_DEV_INTR_MODE_MSIX) ? 165*c8806b6cSNarsimhulu Musini "MSI-X" : "Unknown")))); 166*c8806b6cSNarsimhulu Musini 167*c8806b6cSNarsimhulu Musini /* only MSI-X is supported */ 168*c8806b6cSNarsimhulu Musini SNIC_BUG_ON(intr_mode != VNIC_DEV_INTR_MODE_MSIX); 169*c8806b6cSNarsimhulu Musini 170*c8806b6cSNarsimhulu Musini SNIC_INFO("wq %d cq %d intr %d\n", snic->wq_count, 171*c8806b6cSNarsimhulu Musini snic->cq_count, 172*c8806b6cSNarsimhulu Musini snic->intr_count); 173*c8806b6cSNarsimhulu Musini 174*c8806b6cSNarsimhulu Musini 175*c8806b6cSNarsimhulu Musini /* Allocate WQs used for SCSI IOs */ 176*c8806b6cSNarsimhulu Musini for (i = 0; i < snic->wq_count; i++) { 177*c8806b6cSNarsimhulu Musini ret = svnic_wq_alloc(snic->vdev, 178*c8806b6cSNarsimhulu Musini &snic->wq[i], 179*c8806b6cSNarsimhulu Musini i, 180*c8806b6cSNarsimhulu Musini snic->config.wq_enet_desc_count, 181*c8806b6cSNarsimhulu Musini sizeof(struct wq_enet_desc)); 182*c8806b6cSNarsimhulu Musini if (ret) 183*c8806b6cSNarsimhulu Musini goto error_cleanup; 184*c8806b6cSNarsimhulu Musini } 185*c8806b6cSNarsimhulu Musini 186*c8806b6cSNarsimhulu Musini /* CQ for each WQ */ 187*c8806b6cSNarsimhulu Musini for (i = 0; i < snic->wq_count; i++) { 188*c8806b6cSNarsimhulu Musini ret = svnic_cq_alloc(snic->vdev, 189*c8806b6cSNarsimhulu Musini &snic->cq[i], 190*c8806b6cSNarsimhulu Musini i, 191*c8806b6cSNarsimhulu Musini snic->config.wq_enet_desc_count, 192*c8806b6cSNarsimhulu Musini sizeof(struct cq_enet_wq_desc)); 193*c8806b6cSNarsimhulu Musini if (ret) 194*c8806b6cSNarsimhulu Musini goto error_cleanup; 195*c8806b6cSNarsimhulu Musini } 196*c8806b6cSNarsimhulu Musini 197*c8806b6cSNarsimhulu Musini SNIC_BUG_ON(snic->cq_count != 2 * snic->wq_count); 198*c8806b6cSNarsimhulu Musini /* CQ for FW TO host */ 199*c8806b6cSNarsimhulu Musini for (i = snic->wq_count; i < snic->cq_count; i++) { 200*c8806b6cSNarsimhulu Musini ret = svnic_cq_alloc(snic->vdev, 201*c8806b6cSNarsimhulu Musini &snic->cq[i], 202*c8806b6cSNarsimhulu Musini i, 203*c8806b6cSNarsimhulu Musini (snic->config.wq_enet_desc_count * 3), 204*c8806b6cSNarsimhulu Musini sizeof(struct snic_fw_req)); 205*c8806b6cSNarsimhulu Musini if (ret) 206*c8806b6cSNarsimhulu Musini goto error_cleanup; 207*c8806b6cSNarsimhulu Musini } 208*c8806b6cSNarsimhulu Musini 209*c8806b6cSNarsimhulu Musini for (i = 0; i < snic->intr_count; i++) { 210*c8806b6cSNarsimhulu Musini ret = svnic_intr_alloc(snic->vdev, &snic->intr[i], i); 211*c8806b6cSNarsimhulu Musini if (ret) 212*c8806b6cSNarsimhulu Musini goto error_cleanup; 213*c8806b6cSNarsimhulu Musini } 214*c8806b6cSNarsimhulu Musini 215*c8806b6cSNarsimhulu Musini /* 216*c8806b6cSNarsimhulu Musini * Init WQ Resources. 217*c8806b6cSNarsimhulu Musini * WQ[0 to n] points to CQ[0 to n-1] 218*c8806b6cSNarsimhulu Musini * firmware to host comm points to CQ[n to m+1] 219*c8806b6cSNarsimhulu Musini */ 220*c8806b6cSNarsimhulu Musini err_intr_enable = 1; 221*c8806b6cSNarsimhulu Musini err_intr_offset = snic->err_intr_offset; 222*c8806b6cSNarsimhulu Musini 223*c8806b6cSNarsimhulu Musini for (i = 0; i < snic->wq_count; i++) { 224*c8806b6cSNarsimhulu Musini svnic_wq_init(&snic->wq[i], 225*c8806b6cSNarsimhulu Musini i, 226*c8806b6cSNarsimhulu Musini err_intr_enable, 227*c8806b6cSNarsimhulu Musini err_intr_offset); 228*c8806b6cSNarsimhulu Musini } 229*c8806b6cSNarsimhulu Musini 230*c8806b6cSNarsimhulu Musini for (i = 0; i < snic->cq_count; i++) { 231*c8806b6cSNarsimhulu Musini intr_offset = i; 232*c8806b6cSNarsimhulu Musini 233*c8806b6cSNarsimhulu Musini svnic_cq_init(&snic->cq[i], 234*c8806b6cSNarsimhulu Musini 0 /* flow_control_enable */, 235*c8806b6cSNarsimhulu Musini 1 /* color_enable */, 236*c8806b6cSNarsimhulu Musini 0 /* cq_head */, 237*c8806b6cSNarsimhulu Musini 0 /* cq_tail */, 238*c8806b6cSNarsimhulu Musini 1 /* cq_tail_color */, 239*c8806b6cSNarsimhulu Musini 1 /* interrupt_enable */, 240*c8806b6cSNarsimhulu Musini 1 /* cq_entry_enable */, 241*c8806b6cSNarsimhulu Musini 0 /* cq_message_enable */, 242*c8806b6cSNarsimhulu Musini intr_offset, 243*c8806b6cSNarsimhulu Musini 0 /* cq_message_addr */); 244*c8806b6cSNarsimhulu Musini } 245*c8806b6cSNarsimhulu Musini 246*c8806b6cSNarsimhulu Musini /* 247*c8806b6cSNarsimhulu Musini * Init INTR resources 248*c8806b6cSNarsimhulu Musini * Assumption : snic is always in MSI-X mode 249*c8806b6cSNarsimhulu Musini */ 250*c8806b6cSNarsimhulu Musini SNIC_BUG_ON(intr_mode != VNIC_DEV_INTR_MODE_MSIX); 251*c8806b6cSNarsimhulu Musini mask_on_assertion = 1; 252*c8806b6cSNarsimhulu Musini 253*c8806b6cSNarsimhulu Musini for (i = 0; i < snic->intr_count; i++) { 254*c8806b6cSNarsimhulu Musini svnic_intr_init(&snic->intr[i], 255*c8806b6cSNarsimhulu Musini snic->config.intr_timer, 256*c8806b6cSNarsimhulu Musini snic->config.intr_timer_type, 257*c8806b6cSNarsimhulu Musini mask_on_assertion); 258*c8806b6cSNarsimhulu Musini } 259*c8806b6cSNarsimhulu Musini 260*c8806b6cSNarsimhulu Musini /* init the stats memory by making the first call here */ 261*c8806b6cSNarsimhulu Musini ret = svnic_dev_stats_dump(snic->vdev, &snic->stats); 262*c8806b6cSNarsimhulu Musini if (ret) { 263*c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost, 264*c8806b6cSNarsimhulu Musini "svnic_dev_stats_dump failed - x%x\n", 265*c8806b6cSNarsimhulu Musini ret); 266*c8806b6cSNarsimhulu Musini goto error_cleanup; 267*c8806b6cSNarsimhulu Musini } 268*c8806b6cSNarsimhulu Musini 269*c8806b6cSNarsimhulu Musini /* Clear LIF stats */ 270*c8806b6cSNarsimhulu Musini svnic_dev_stats_clear(snic->vdev); 271*c8806b6cSNarsimhulu Musini ret = 0; 272*c8806b6cSNarsimhulu Musini 273*c8806b6cSNarsimhulu Musini return ret; 274*c8806b6cSNarsimhulu Musini 275*c8806b6cSNarsimhulu Musini error_cleanup: 276*c8806b6cSNarsimhulu Musini snic_free_vnic_res(snic); 277*c8806b6cSNarsimhulu Musini 278*c8806b6cSNarsimhulu Musini return ret; 279*c8806b6cSNarsimhulu Musini } 280*c8806b6cSNarsimhulu Musini 281*c8806b6cSNarsimhulu Musini void 282*c8806b6cSNarsimhulu Musini snic_log_q_error(struct snic *snic) 283*c8806b6cSNarsimhulu Musini { 284*c8806b6cSNarsimhulu Musini unsigned int i; 285*c8806b6cSNarsimhulu Musini u32 err_status; 286*c8806b6cSNarsimhulu Musini 287*c8806b6cSNarsimhulu Musini for (i = 0; i < snic->wq_count; i++) { 288*c8806b6cSNarsimhulu Musini err_status = ioread32(&snic->wq[i].ctrl->error_status); 289*c8806b6cSNarsimhulu Musini if (err_status) 290*c8806b6cSNarsimhulu Musini SNIC_HOST_ERR(snic->shost, 291*c8806b6cSNarsimhulu Musini "WQ[%d] error status %d\n", 292*c8806b6cSNarsimhulu Musini i, 293*c8806b6cSNarsimhulu Musini err_status); 294*c8806b6cSNarsimhulu Musini } 295*c8806b6cSNarsimhulu Musini } /* end of snic_log_q_error */ 296