462 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright 2008 Cisco Systems, Inc. All rights reserved.4 * Copyright 2007 Nuova Systems, Inc. All rights reserved.5 */6#include <linux/errno.h>7#include <linux/types.h>8#include <linux/pci.h>9#include "wq_enet_desc.h"10#include "rq_enet_desc.h"11#include "cq_enet_desc.h"12#include "vnic_resource.h"13#include "vnic_dev.h"14#include "vnic_wq.h"15#include "vnic_rq.h"16#include "vnic_cq.h"17#include "vnic_intr.h"18#include "vnic_stats.h"19#include "vnic_nic.h"20#include "fnic.h"21 22int fnic_get_vnic_config(struct fnic *fnic)23{24 struct vnic_fc_config *c = &fnic->config;25 int err;26 27#define GET_CONFIG(m) \28 do { \29 err = vnic_dev_spec(fnic->vdev, \30 offsetof(struct vnic_fc_config, m), \31 sizeof(c->m), &c->m); \32 if (err) { \33 shost_printk(KERN_ERR, fnic->lport->host, \34 "Error getting %s, %d\n", #m, \35 err); \36 return err; \37 } \38 } while (0);39 40 GET_CONFIG(node_wwn);41 GET_CONFIG(port_wwn);42 GET_CONFIG(wq_enet_desc_count);43 GET_CONFIG(wq_copy_desc_count);44 GET_CONFIG(rq_desc_count);45 GET_CONFIG(maxdatafieldsize);46 GET_CONFIG(ed_tov);47 GET_CONFIG(ra_tov);48 GET_CONFIG(intr_timer);49 GET_CONFIG(intr_timer_type);50 GET_CONFIG(flags);51 GET_CONFIG(flogi_retries);52 GET_CONFIG(flogi_timeout);53 GET_CONFIG(plogi_retries);54 GET_CONFIG(plogi_timeout);55 GET_CONFIG(io_throttle_count);56 GET_CONFIG(link_down_timeout);57 GET_CONFIG(port_down_timeout);58 GET_CONFIG(port_down_io_retries);59 GET_CONFIG(luns_per_tgt);60 GET_CONFIG(intr_mode);61 GET_CONFIG(wq_copy_count);62 63 c->wq_enet_desc_count =64 min_t(u32, VNIC_FNIC_WQ_DESCS_MAX,65 max_t(u32, VNIC_FNIC_WQ_DESCS_MIN,66 c->wq_enet_desc_count));67 c->wq_enet_desc_count = ALIGN(c->wq_enet_desc_count, 16);68 69 c->wq_copy_desc_count =70 min_t(u32, VNIC_FNIC_WQ_COPY_DESCS_MAX,71 max_t(u32, VNIC_FNIC_WQ_COPY_DESCS_MIN,72 c->wq_copy_desc_count));73 c->wq_copy_desc_count = ALIGN(c->wq_copy_desc_count, 16);74 75 c->rq_desc_count =76 min_t(u32, VNIC_FNIC_RQ_DESCS_MAX,77 max_t(u32, VNIC_FNIC_RQ_DESCS_MIN,78 c->rq_desc_count));79 c->rq_desc_count = ALIGN(c->rq_desc_count, 16);80 81 c->maxdatafieldsize =82 min_t(u16, VNIC_FNIC_MAXDATAFIELDSIZE_MAX,83 max_t(u16, VNIC_FNIC_MAXDATAFIELDSIZE_MIN,84 c->maxdatafieldsize));85 c->ed_tov =86 min_t(u32, VNIC_FNIC_EDTOV_MAX,87 max_t(u32, VNIC_FNIC_EDTOV_MIN,88 c->ed_tov));89 90 c->ra_tov =91 min_t(u32, VNIC_FNIC_RATOV_MAX,92 max_t(u32, VNIC_FNIC_RATOV_MIN,93 c->ra_tov));94 95 c->flogi_retries =96 min_t(u32, VNIC_FNIC_FLOGI_RETRIES_MAX, c->flogi_retries);97 98 c->flogi_timeout =99 min_t(u32, VNIC_FNIC_FLOGI_TIMEOUT_MAX,100 max_t(u32, VNIC_FNIC_FLOGI_TIMEOUT_MIN,101 c->flogi_timeout));102 103 c->plogi_retries =104 min_t(u32, VNIC_FNIC_PLOGI_RETRIES_MAX, c->plogi_retries);105 106 c->plogi_timeout =107 min_t(u32, VNIC_FNIC_PLOGI_TIMEOUT_MAX,108 max_t(u32, VNIC_FNIC_PLOGI_TIMEOUT_MIN,109 c->plogi_timeout));110 111 c->io_throttle_count =112 min_t(u32, VNIC_FNIC_IO_THROTTLE_COUNT_MAX,113 max_t(u32, VNIC_FNIC_IO_THROTTLE_COUNT_MIN,114 c->io_throttle_count));115 116 c->link_down_timeout =117 min_t(u32, VNIC_FNIC_LINK_DOWN_TIMEOUT_MAX,118 c->link_down_timeout);119 120 c->port_down_timeout =121 min_t(u32, VNIC_FNIC_PORT_DOWN_TIMEOUT_MAX,122 c->port_down_timeout);123 124 c->port_down_io_retries =125 min_t(u32, VNIC_FNIC_PORT_DOWN_IO_RETRIES_MAX,126 c->port_down_io_retries);127 128 c->luns_per_tgt =129 min_t(u32, VNIC_FNIC_LUNS_PER_TARGET_MAX,130 max_t(u32, VNIC_FNIC_LUNS_PER_TARGET_MIN,131 c->luns_per_tgt));132 133 c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer);134 c->intr_timer_type = c->intr_timer_type;135 136 /* for older firmware, GET_CONFIG will not return anything */137 if (c->wq_copy_count == 0)138 c->wq_copy_count = 1;139 140 c->wq_copy_count = min_t(u16, FNIC_WQ_COPY_MAX, c->wq_copy_count);141 142 shost_printk(KERN_INFO, fnic->lport->host,143 "vNIC MAC addr %pM "144 "wq/wq_copy/rq %d/%d/%d\n",145 fnic->ctlr.ctl_src_addr,146 c->wq_enet_desc_count, c->wq_copy_desc_count,147 c->rq_desc_count);148 shost_printk(KERN_INFO, fnic->lport->host,149 "vNIC node wwn %llx port wwn %llx\n",150 c->node_wwn, c->port_wwn);151 shost_printk(KERN_INFO, fnic->lport->host,152 "vNIC ed_tov %d ra_tov %d\n",153 c->ed_tov, c->ra_tov);154 shost_printk(KERN_INFO, fnic->lport->host,155 "vNIC mtu %d intr timer %d\n",156 c->maxdatafieldsize, c->intr_timer);157 shost_printk(KERN_INFO, fnic->lport->host,158 "vNIC flags 0x%x luns per tgt %d\n",159 c->flags, c->luns_per_tgt);160 shost_printk(KERN_INFO, fnic->lport->host,161 "vNIC flogi_retries %d flogi timeout %d\n",162 c->flogi_retries, c->flogi_timeout);163 shost_printk(KERN_INFO, fnic->lport->host,164 "vNIC plogi retries %d plogi timeout %d\n",165 c->plogi_retries, c->plogi_timeout);166 shost_printk(KERN_INFO, fnic->lport->host,167 "vNIC io throttle count %d link dn timeout %d\n",168 c->io_throttle_count, c->link_down_timeout);169 shost_printk(KERN_INFO, fnic->lport->host,170 "vNIC port dn io retries %d port dn timeout %d\n",171 c->port_down_io_retries, c->port_down_timeout);172 shost_printk(KERN_INFO, fnic->lport->host,173 "vNIC wq_copy_count: %d\n", c->wq_copy_count);174 shost_printk(KERN_INFO, fnic->lport->host,175 "vNIC intr mode: %d\n", c->intr_mode);176 177 return 0;178}179 180int fnic_set_nic_config(struct fnic *fnic, u8 rss_default_cpu,181 u8 rss_hash_type,182 u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable,183 u8 tso_ipid_split_en, u8 ig_vlan_strip_en)184{185 u64 a0, a1;186 u32 nic_cfg;187 int wait = 1000;188 189 vnic_set_nic_cfg(&nic_cfg, rss_default_cpu,190 rss_hash_type, rss_hash_bits, rss_base_cpu,191 rss_enable, tso_ipid_split_en, ig_vlan_strip_en);192 193 a0 = nic_cfg;194 a1 = 0;195 196 return vnic_dev_cmd(fnic->vdev, CMD_NIC_CFG, &a0, &a1, wait);197}198 199void fnic_get_res_counts(struct fnic *fnic)200{201 fnic->wq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_WQ);202 fnic->raw_wq_count = 1;203 fnic->wq_copy_count = fnic->config.wq_copy_count;204 fnic->rq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_RQ);205 fnic->cq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_CQ);206 fnic->intr_count = vnic_dev_get_res_count(fnic->vdev,207 RES_TYPE_INTR_CTRL);208 209 shost_printk(KERN_INFO, fnic->lport->host,210 "vNIC fw resources wq_count: %d\n", fnic->wq_count);211 shost_printk(KERN_INFO, fnic->lport->host,212 "vNIC fw resources raw_wq_count: %d\n", fnic->raw_wq_count);213 shost_printk(KERN_INFO, fnic->lport->host,214 "vNIC fw resources wq_copy_count: %d\n", fnic->wq_copy_count);215 shost_printk(KERN_INFO, fnic->lport->host,216 "vNIC fw resources rq_count: %d\n", fnic->rq_count);217 shost_printk(KERN_INFO, fnic->lport->host,218 "vNIC fw resources cq_count: %d\n", fnic->cq_count);219 shost_printk(KERN_INFO, fnic->lport->host,220 "vNIC fw resources intr_count: %d\n", fnic->intr_count);221}222 223void fnic_free_vnic_resources(struct fnic *fnic)224{225 unsigned int i;226 227 for (i = 0; i < fnic->raw_wq_count; i++)228 vnic_wq_free(&fnic->wq[i]);229 230 for (i = 0; i < fnic->wq_copy_count; i++)231 vnic_wq_copy_free(&fnic->hw_copy_wq[i]);232 233 for (i = 0; i < fnic->rq_count; i++)234 vnic_rq_free(&fnic->rq[i]);235 236 for (i = 0; i < fnic->cq_count; i++)237 vnic_cq_free(&fnic->cq[i]);238 239 for (i = 0; i < fnic->intr_count; i++)240 vnic_intr_free(&fnic->intr[i]);241}242 243int fnic_alloc_vnic_resources(struct fnic *fnic)244{245 enum vnic_dev_intr_mode intr_mode;246 unsigned int mask_on_assertion;247 unsigned int interrupt_offset;248 unsigned int error_interrupt_enable;249 unsigned int error_interrupt_offset;250 unsigned int i, cq_index;251 unsigned int wq_copy_cq_desc_count;252 int err;253 254 intr_mode = vnic_dev_get_intr_mode(fnic->vdev);255 256 shost_printk(KERN_INFO, fnic->lport->host, "vNIC interrupt mode: %s\n",257 intr_mode == VNIC_DEV_INTR_MODE_INTX ? "legacy PCI INTx" :258 intr_mode == VNIC_DEV_INTR_MODE_MSI ? "MSI" :259 intr_mode == VNIC_DEV_INTR_MODE_MSIX ?260 "MSI-X" : "unknown");261 262 shost_printk(KERN_INFO, fnic->lport->host,263 "vNIC resources avail: wq %d cp_wq %d raw_wq %d rq %d",264 fnic->wq_count, fnic->wq_copy_count,265 fnic->raw_wq_count, fnic->rq_count);266 267 shost_printk(KERN_INFO, fnic->lport->host,268 "vNIC resources avail: cq %d intr %d cpy-wq desc count %d\n",269 fnic->cq_count, fnic->intr_count,270 fnic->config.wq_copy_desc_count);271 272 /* Allocate Raw WQ used for FCS frames */273 for (i = 0; i < fnic->raw_wq_count; i++) {274 err = vnic_wq_alloc(fnic->vdev, &fnic->wq[i], i,275 fnic->config.wq_enet_desc_count,276 sizeof(struct wq_enet_desc));277 if (err)278 goto err_out_cleanup;279 }280 281 /* Allocate Copy WQs used for SCSI IOs */282 for (i = 0; i < fnic->wq_copy_count; i++) {283 err = vnic_wq_copy_alloc(fnic->vdev, &fnic->hw_copy_wq[i],284 (fnic->raw_wq_count + i),285 fnic->config.wq_copy_desc_count,286 sizeof(struct fcpio_host_req));287 if (err)288 goto err_out_cleanup;289 }290 291 /* RQ for receiving FCS frames */292 for (i = 0; i < fnic->rq_count; i++) {293 err = vnic_rq_alloc(fnic->vdev, &fnic->rq[i], i,294 fnic->config.rq_desc_count,295 sizeof(struct rq_enet_desc));296 if (err)297 goto err_out_cleanup;298 }299 300 /* CQ for each RQ */301 for (i = 0; i < fnic->rq_count; i++) {302 cq_index = i;303 err = vnic_cq_alloc(fnic->vdev,304 &fnic->cq[cq_index], cq_index,305 fnic->config.rq_desc_count,306 sizeof(struct cq_enet_rq_desc));307 if (err)308 goto err_out_cleanup;309 }310 311 /* CQ for each WQ */312 for (i = 0; i < fnic->raw_wq_count; i++) {313 cq_index = fnic->rq_count + i;314 err = vnic_cq_alloc(fnic->vdev, &fnic->cq[cq_index], cq_index,315 fnic->config.wq_enet_desc_count,316 sizeof(struct cq_enet_wq_desc));317 if (err)318 goto err_out_cleanup;319 }320 321 /* CQ for each COPY WQ */322 wq_copy_cq_desc_count = (fnic->config.wq_copy_desc_count * 3);323 for (i = 0; i < fnic->wq_copy_count; i++) {324 cq_index = fnic->raw_wq_count + fnic->rq_count + i;325 err = vnic_cq_alloc(fnic->vdev, &fnic->cq[cq_index],326 cq_index,327 wq_copy_cq_desc_count,328 sizeof(struct fcpio_fw_req));329 if (err)330 goto err_out_cleanup;331 }332 333 for (i = 0; i < fnic->intr_count; i++) {334 err = vnic_intr_alloc(fnic->vdev, &fnic->intr[i], i);335 if (err)336 goto err_out_cleanup;337 }338 339 fnic->legacy_pba = vnic_dev_get_res(fnic->vdev,340 RES_TYPE_INTR_PBA_LEGACY, 0);341 342 if (!fnic->legacy_pba && intr_mode == VNIC_DEV_INTR_MODE_INTX) {343 shost_printk(KERN_ERR, fnic->lport->host,344 "Failed to hook legacy pba resource\n");345 err = -ENODEV;346 goto err_out_cleanup;347 }348 349 /*350 * Init RQ/WQ resources.351 *352 * RQ[0 to n-1] point to CQ[0 to n-1]353 * WQ[0 to m-1] point to CQ[n to n+m-1]354 * WQ_COPY[0 to k-1] points to CQ[n+m to n+m+k-1]355 *356 * Note for copy wq we always initialize with cq_index = 0357 *358 * Error interrupt is not enabled for MSI.359 */360 361 switch (intr_mode) {362 case VNIC_DEV_INTR_MODE_INTX:363 case VNIC_DEV_INTR_MODE_MSIX:364 error_interrupt_enable = 1;365 error_interrupt_offset = fnic->err_intr_offset;366 break;367 default:368 error_interrupt_enable = 0;369 error_interrupt_offset = 0;370 break;371 }372 373 for (i = 0; i < fnic->rq_count; i++) {374 cq_index = i;375 vnic_rq_init(&fnic->rq[i],376 cq_index,377 error_interrupt_enable,378 error_interrupt_offset);379 }380 381 for (i = 0; i < fnic->raw_wq_count; i++) {382 cq_index = i + fnic->rq_count;383 vnic_wq_init(&fnic->wq[i],384 cq_index,385 error_interrupt_enable,386 error_interrupt_offset);387 }388 389 for (i = 0; i < fnic->wq_copy_count; i++) {390 vnic_wq_copy_init(&fnic->hw_copy_wq[i],391 0 /* cq_index 0 - always */,392 error_interrupt_enable,393 error_interrupt_offset);394 }395 396 for (i = 0; i < fnic->cq_count; i++) {397 398 switch (intr_mode) {399 case VNIC_DEV_INTR_MODE_MSIX:400 interrupt_offset = i;401 break;402 default:403 interrupt_offset = 0;404 break;405 }406 407 vnic_cq_init(&fnic->cq[i],408 0 /* flow_control_enable */,409 1 /* color_enable */,410 0 /* cq_head */,411 0 /* cq_tail */,412 1 /* cq_tail_color */,413 1 /* interrupt_enable */,414 1 /* cq_entry_enable */,415 0 /* cq_message_enable */,416 interrupt_offset,417 0 /* cq_message_addr */);418 }419 420 /*421 * Init INTR resources422 *423 * mask_on_assertion is not used for INTx due to the level-424 * triggered nature of INTx425 */426 427 switch (intr_mode) {428 case VNIC_DEV_INTR_MODE_MSI:429 case VNIC_DEV_INTR_MODE_MSIX:430 mask_on_assertion = 1;431 break;432 default:433 mask_on_assertion = 0;434 break;435 }436 437 for (i = 0; i < fnic->intr_count; i++) {438 vnic_intr_init(&fnic->intr[i],439 fnic->config.intr_timer,440 fnic->config.intr_timer_type,441 mask_on_assertion);442 }443 444 /* init the stats memory by making the first call here */445 err = vnic_dev_stats_dump(fnic->vdev, &fnic->stats);446 if (err) {447 shost_printk(KERN_ERR, fnic->lport->host,448 "vnic_dev_stats_dump failed - x%x\n", err);449 goto err_out_cleanup;450 }451 452 /* Clear LIF stats */453 vnic_dev_stats_clear(fnic->vdev);454 455 return 0;456 457err_out_cleanup:458 fnic_free_vnic_resources(fnic);459 460 return err;461}462