brintos

brintos / linux-shallow public Read only

0
0
Text · 12.4 KiB · 33dd27f Raw
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