cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fnic_res.c (12229B)


      1/*
      2 * Copyright 2008 Cisco Systems, Inc.  All rights reserved.
      3 * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
      4 *
      5 * This program is free software; you may redistribute it and/or modify
      6 * it under the terms of the GNU General Public License as published by
      7 * the Free Software Foundation; version 2 of the License.
      8 *
      9 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     10 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     11 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     12 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     13 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     14 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     15 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     16 * SOFTWARE.
     17 */
     18#include <linux/errno.h>
     19#include <linux/types.h>
     20#include <linux/pci.h>
     21#include "wq_enet_desc.h"
     22#include "rq_enet_desc.h"
     23#include "cq_enet_desc.h"
     24#include "vnic_resource.h"
     25#include "vnic_dev.h"
     26#include "vnic_wq.h"
     27#include "vnic_rq.h"
     28#include "vnic_cq.h"
     29#include "vnic_intr.h"
     30#include "vnic_stats.h"
     31#include "vnic_nic.h"
     32#include "fnic.h"
     33
     34int fnic_get_vnic_config(struct fnic *fnic)
     35{
     36	struct vnic_fc_config *c = &fnic->config;
     37	int err;
     38
     39#define GET_CONFIG(m) \
     40	do { \
     41		err = vnic_dev_spec(fnic->vdev, \
     42				    offsetof(struct vnic_fc_config, m), \
     43				    sizeof(c->m), &c->m); \
     44		if (err) { \
     45			shost_printk(KERN_ERR, fnic->lport->host, \
     46				     "Error getting %s, %d\n", #m, \
     47				     err); \
     48			return err; \
     49		} \
     50	} while (0);
     51
     52	GET_CONFIG(node_wwn);
     53	GET_CONFIG(port_wwn);
     54	GET_CONFIG(wq_enet_desc_count);
     55	GET_CONFIG(wq_copy_desc_count);
     56	GET_CONFIG(rq_desc_count);
     57	GET_CONFIG(maxdatafieldsize);
     58	GET_CONFIG(ed_tov);
     59	GET_CONFIG(ra_tov);
     60	GET_CONFIG(intr_timer);
     61	GET_CONFIG(intr_timer_type);
     62	GET_CONFIG(flags);
     63	GET_CONFIG(flogi_retries);
     64	GET_CONFIG(flogi_timeout);
     65	GET_CONFIG(plogi_retries);
     66	GET_CONFIG(plogi_timeout);
     67	GET_CONFIG(io_throttle_count);
     68	GET_CONFIG(link_down_timeout);
     69	GET_CONFIG(port_down_timeout);
     70	GET_CONFIG(port_down_io_retries);
     71	GET_CONFIG(luns_per_tgt);
     72
     73	c->wq_enet_desc_count =
     74		min_t(u32, VNIC_FNIC_WQ_DESCS_MAX,
     75		      max_t(u32, VNIC_FNIC_WQ_DESCS_MIN,
     76			    c->wq_enet_desc_count));
     77	c->wq_enet_desc_count = ALIGN(c->wq_enet_desc_count, 16);
     78
     79	c->wq_copy_desc_count =
     80		min_t(u32, VNIC_FNIC_WQ_COPY_DESCS_MAX,
     81		      max_t(u32, VNIC_FNIC_WQ_COPY_DESCS_MIN,
     82			    c->wq_copy_desc_count));
     83	c->wq_copy_desc_count = ALIGN(c->wq_copy_desc_count, 16);
     84
     85	c->rq_desc_count =
     86		min_t(u32, VNIC_FNIC_RQ_DESCS_MAX,
     87		      max_t(u32, VNIC_FNIC_RQ_DESCS_MIN,
     88			    c->rq_desc_count));
     89	c->rq_desc_count = ALIGN(c->rq_desc_count, 16);
     90
     91	c->maxdatafieldsize =
     92		min_t(u16, VNIC_FNIC_MAXDATAFIELDSIZE_MAX,
     93		      max_t(u16, VNIC_FNIC_MAXDATAFIELDSIZE_MIN,
     94			    c->maxdatafieldsize));
     95	c->ed_tov =
     96		min_t(u32, VNIC_FNIC_EDTOV_MAX,
     97		      max_t(u32, VNIC_FNIC_EDTOV_MIN,
     98			    c->ed_tov));
     99
    100	c->ra_tov =
    101		min_t(u32, VNIC_FNIC_RATOV_MAX,
    102		      max_t(u32, VNIC_FNIC_RATOV_MIN,
    103			    c->ra_tov));
    104
    105	c->flogi_retries =
    106		min_t(u32, VNIC_FNIC_FLOGI_RETRIES_MAX, c->flogi_retries);
    107
    108	c->flogi_timeout =
    109		min_t(u32, VNIC_FNIC_FLOGI_TIMEOUT_MAX,
    110		      max_t(u32, VNIC_FNIC_FLOGI_TIMEOUT_MIN,
    111			    c->flogi_timeout));
    112
    113	c->plogi_retries =
    114		min_t(u32, VNIC_FNIC_PLOGI_RETRIES_MAX, c->plogi_retries);
    115
    116	c->plogi_timeout =
    117		min_t(u32, VNIC_FNIC_PLOGI_TIMEOUT_MAX,
    118		      max_t(u32, VNIC_FNIC_PLOGI_TIMEOUT_MIN,
    119			    c->plogi_timeout));
    120
    121	c->io_throttle_count =
    122		min_t(u32, VNIC_FNIC_IO_THROTTLE_COUNT_MAX,
    123		      max_t(u32, VNIC_FNIC_IO_THROTTLE_COUNT_MIN,
    124			    c->io_throttle_count));
    125
    126	c->link_down_timeout =
    127		min_t(u32, VNIC_FNIC_LINK_DOWN_TIMEOUT_MAX,
    128		      c->link_down_timeout);
    129
    130	c->port_down_timeout =
    131		min_t(u32, VNIC_FNIC_PORT_DOWN_TIMEOUT_MAX,
    132		      c->port_down_timeout);
    133
    134	c->port_down_io_retries =
    135		min_t(u32, VNIC_FNIC_PORT_DOWN_IO_RETRIES_MAX,
    136		      c->port_down_io_retries);
    137
    138	c->luns_per_tgt =
    139		min_t(u32, VNIC_FNIC_LUNS_PER_TARGET_MAX,
    140		      max_t(u32, VNIC_FNIC_LUNS_PER_TARGET_MIN,
    141			    c->luns_per_tgt));
    142
    143	c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer);
    144	c->intr_timer_type = c->intr_timer_type;
    145
    146	shost_printk(KERN_INFO, fnic->lport->host,
    147		     "vNIC MAC addr %pM "
    148		     "wq/wq_copy/rq %d/%d/%d\n",
    149		     fnic->ctlr.ctl_src_addr,
    150		     c->wq_enet_desc_count, c->wq_copy_desc_count,
    151		     c->rq_desc_count);
    152	shost_printk(KERN_INFO, fnic->lport->host,
    153		     "vNIC node wwn %llx port wwn %llx\n",
    154		     c->node_wwn, c->port_wwn);
    155	shost_printk(KERN_INFO, fnic->lport->host,
    156		     "vNIC ed_tov %d ra_tov %d\n",
    157		     c->ed_tov, c->ra_tov);
    158	shost_printk(KERN_INFO, fnic->lport->host,
    159		     "vNIC mtu %d intr timer %d\n",
    160		     c->maxdatafieldsize, c->intr_timer);
    161	shost_printk(KERN_INFO, fnic->lport->host,
    162		     "vNIC flags 0x%x luns per tgt %d\n",
    163		     c->flags, c->luns_per_tgt);
    164	shost_printk(KERN_INFO, fnic->lport->host,
    165		     "vNIC flogi_retries %d flogi timeout %d\n",
    166		     c->flogi_retries, c->flogi_timeout);
    167	shost_printk(KERN_INFO, fnic->lport->host,
    168		     "vNIC plogi retries %d plogi timeout %d\n",
    169		     c->plogi_retries, c->plogi_timeout);
    170	shost_printk(KERN_INFO, fnic->lport->host,
    171		     "vNIC io throttle count %d link dn timeout %d\n",
    172		     c->io_throttle_count, c->link_down_timeout);
    173	shost_printk(KERN_INFO, fnic->lport->host,
    174		     "vNIC port dn io retries %d port dn timeout %d\n",
    175		     c->port_down_io_retries, c->port_down_timeout);
    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 = fnic->wq_count - 1;
    203	fnic->wq_copy_count = fnic->wq_count - fnic->raw_wq_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
    210void fnic_free_vnic_resources(struct fnic *fnic)
    211{
    212	unsigned int i;
    213
    214	for (i = 0; i < fnic->raw_wq_count; i++)
    215		vnic_wq_free(&fnic->wq[i]);
    216
    217	for (i = 0; i < fnic->wq_copy_count; i++)
    218		vnic_wq_copy_free(&fnic->wq_copy[i]);
    219
    220	for (i = 0; i < fnic->rq_count; i++)
    221		vnic_rq_free(&fnic->rq[i]);
    222
    223	for (i = 0; i < fnic->cq_count; i++)
    224		vnic_cq_free(&fnic->cq[i]);
    225
    226	for (i = 0; i < fnic->intr_count; i++)
    227		vnic_intr_free(&fnic->intr[i]);
    228}
    229
    230int fnic_alloc_vnic_resources(struct fnic *fnic)
    231{
    232	enum vnic_dev_intr_mode intr_mode;
    233	unsigned int mask_on_assertion;
    234	unsigned int interrupt_offset;
    235	unsigned int error_interrupt_enable;
    236	unsigned int error_interrupt_offset;
    237	unsigned int i, cq_index;
    238	unsigned int wq_copy_cq_desc_count;
    239	int err;
    240
    241	intr_mode = vnic_dev_get_intr_mode(fnic->vdev);
    242
    243	shost_printk(KERN_INFO, fnic->lport->host, "vNIC interrupt mode: %s\n",
    244		     intr_mode == VNIC_DEV_INTR_MODE_INTX ? "legacy PCI INTx" :
    245		     intr_mode == VNIC_DEV_INTR_MODE_MSI ? "MSI" :
    246		     intr_mode == VNIC_DEV_INTR_MODE_MSIX ?
    247		     "MSI-X" : "unknown");
    248
    249	shost_printk(KERN_INFO, fnic->lport->host, "vNIC resources avail: "
    250		     "wq %d cp_wq %d raw_wq %d rq %d cq %d intr %d\n",
    251		     fnic->wq_count, fnic->wq_copy_count, fnic->raw_wq_count,
    252		     fnic->rq_count, fnic->cq_count, fnic->intr_count);
    253
    254	/* Allocate Raw WQ used for FCS frames */
    255	for (i = 0; i < fnic->raw_wq_count; i++) {
    256		err = vnic_wq_alloc(fnic->vdev, &fnic->wq[i], i,
    257			fnic->config.wq_enet_desc_count,
    258			sizeof(struct wq_enet_desc));
    259		if (err)
    260			goto err_out_cleanup;
    261	}
    262
    263	/* Allocate Copy WQs used for SCSI IOs */
    264	for (i = 0; i < fnic->wq_copy_count; i++) {
    265		err = vnic_wq_copy_alloc(fnic->vdev, &fnic->wq_copy[i],
    266			(fnic->raw_wq_count + i),
    267			fnic->config.wq_copy_desc_count,
    268			sizeof(struct fcpio_host_req));
    269		if (err)
    270			goto err_out_cleanup;
    271	}
    272
    273	/* RQ for receiving FCS frames */
    274	for (i = 0; i < fnic->rq_count; i++) {
    275		err = vnic_rq_alloc(fnic->vdev, &fnic->rq[i], i,
    276			fnic->config.rq_desc_count,
    277			sizeof(struct rq_enet_desc));
    278		if (err)
    279			goto err_out_cleanup;
    280	}
    281
    282	/* CQ for each RQ */
    283	for (i = 0; i < fnic->rq_count; i++) {
    284		cq_index = i;
    285		err = vnic_cq_alloc(fnic->vdev,
    286			&fnic->cq[cq_index], cq_index,
    287			fnic->config.rq_desc_count,
    288			sizeof(struct cq_enet_rq_desc));
    289		if (err)
    290			goto err_out_cleanup;
    291	}
    292
    293	/* CQ for each WQ */
    294	for (i = 0; i < fnic->raw_wq_count; i++) {
    295		cq_index = fnic->rq_count + i;
    296		err = vnic_cq_alloc(fnic->vdev, &fnic->cq[cq_index], cq_index,
    297			fnic->config.wq_enet_desc_count,
    298			sizeof(struct cq_enet_wq_desc));
    299		if (err)
    300			goto err_out_cleanup;
    301	}
    302
    303	/* CQ for each COPY WQ */
    304	wq_copy_cq_desc_count = (fnic->config.wq_copy_desc_count * 3);
    305	for (i = 0; i < fnic->wq_copy_count; i++) {
    306		cq_index = fnic->raw_wq_count + fnic->rq_count + i;
    307		err = vnic_cq_alloc(fnic->vdev, &fnic->cq[cq_index],
    308			cq_index,
    309			wq_copy_cq_desc_count,
    310			sizeof(struct fcpio_fw_req));
    311		if (err)
    312			goto err_out_cleanup;
    313	}
    314
    315	for (i = 0; i < fnic->intr_count; i++) {
    316		err = vnic_intr_alloc(fnic->vdev, &fnic->intr[i], i);
    317		if (err)
    318			goto err_out_cleanup;
    319	}
    320
    321	fnic->legacy_pba = vnic_dev_get_res(fnic->vdev,
    322				RES_TYPE_INTR_PBA_LEGACY, 0);
    323
    324	if (!fnic->legacy_pba && intr_mode == VNIC_DEV_INTR_MODE_INTX) {
    325		shost_printk(KERN_ERR, fnic->lport->host,
    326			     "Failed to hook legacy pba resource\n");
    327		err = -ENODEV;
    328		goto err_out_cleanup;
    329	}
    330
    331	/*
    332	 * Init RQ/WQ resources.
    333	 *
    334	 * RQ[0 to n-1] point to CQ[0 to n-1]
    335	 * WQ[0 to m-1] point to CQ[n to n+m-1]
    336	 * WQ_COPY[0 to k-1] points to CQ[n+m to n+m+k-1]
    337	 *
    338	 * Note for copy wq we always initialize with cq_index = 0
    339	 *
    340	 * Error interrupt is not enabled for MSI.
    341	 */
    342
    343	switch (intr_mode) {
    344	case VNIC_DEV_INTR_MODE_INTX:
    345	case VNIC_DEV_INTR_MODE_MSIX:
    346		error_interrupt_enable = 1;
    347		error_interrupt_offset = fnic->err_intr_offset;
    348		break;
    349	default:
    350		error_interrupt_enable = 0;
    351		error_interrupt_offset = 0;
    352		break;
    353	}
    354
    355	for (i = 0; i < fnic->rq_count; i++) {
    356		cq_index = i;
    357		vnic_rq_init(&fnic->rq[i],
    358			     cq_index,
    359			     error_interrupt_enable,
    360			     error_interrupt_offset);
    361	}
    362
    363	for (i = 0; i < fnic->raw_wq_count; i++) {
    364		cq_index = i + fnic->rq_count;
    365		vnic_wq_init(&fnic->wq[i],
    366			     cq_index,
    367			     error_interrupt_enable,
    368			     error_interrupt_offset);
    369	}
    370
    371	for (i = 0; i < fnic->wq_copy_count; i++) {
    372		vnic_wq_copy_init(&fnic->wq_copy[i],
    373				  0 /* cq_index 0 - always */,
    374				  error_interrupt_enable,
    375				  error_interrupt_offset);
    376	}
    377
    378	for (i = 0; i < fnic->cq_count; i++) {
    379
    380		switch (intr_mode) {
    381		case VNIC_DEV_INTR_MODE_MSIX:
    382			interrupt_offset = i;
    383			break;
    384		default:
    385			interrupt_offset = 0;
    386			break;
    387		}
    388
    389		vnic_cq_init(&fnic->cq[i],
    390			0 /* flow_control_enable */,
    391			1 /* color_enable */,
    392			0 /* cq_head */,
    393			0 /* cq_tail */,
    394			1 /* cq_tail_color */,
    395			1 /* interrupt_enable */,
    396			1 /* cq_entry_enable */,
    397			0 /* cq_message_enable */,
    398			interrupt_offset,
    399			0 /* cq_message_addr */);
    400	}
    401
    402	/*
    403	 * Init INTR resources
    404	 *
    405	 * mask_on_assertion is not used for INTx due to the level-
    406	 * triggered nature of INTx
    407	 */
    408
    409	switch (intr_mode) {
    410	case VNIC_DEV_INTR_MODE_MSI:
    411	case VNIC_DEV_INTR_MODE_MSIX:
    412		mask_on_assertion = 1;
    413		break;
    414	default:
    415		mask_on_assertion = 0;
    416		break;
    417	}
    418
    419	for (i = 0; i < fnic->intr_count; i++) {
    420		vnic_intr_init(&fnic->intr[i],
    421			fnic->config.intr_timer,
    422			fnic->config.intr_timer_type,
    423			mask_on_assertion);
    424	}
    425
    426	/* init the stats memory by making the first call here */
    427	err = vnic_dev_stats_dump(fnic->vdev, &fnic->stats);
    428	if (err) {
    429		shost_printk(KERN_ERR, fnic->lport->host,
    430			     "vnic_dev_stats_dump failed - x%x\n", err);
    431		goto err_out_cleanup;
    432	}
    433
    434	/* Clear LIF stats */
    435	vnic_dev_stats_clear(fnic->vdev);
    436
    437	return 0;
    438
    439err_out_cleanup:
    440	fnic_free_vnic_resources(fnic);
    441
    442	return err;
    443}