brintos

brintos / linux-shallow public Read only

0
0
Text · 28.7 KiB · 9a3f2ed Raw
1255 lines · c
1/*2 * This file is part of the Chelsio FCoE driver for Linux.3 *4 * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.5 *6 * This software is available to you under a choice of one of two7 * licenses.  You may choose to be licensed under the terms of the GNU8 * General Public License (GPL) Version 2, available from the file9 * COPYING in the main directory of this source tree, or the10 * OpenIB.org BSD license below:11 *12 *     Redistribution and use in source and binary forms, with or13 *     without modification, are permitted provided that the following14 *     conditions are met:15 *16 *      - Redistributions of source code must retain the above17 *        copyright notice, this list of conditions and the following18 *        disclaimer.19 *20 *      - Redistributions in binary form must reproduce the above21 *        copyright notice, this list of conditions and the following22 *        disclaimer in the documentation and/or other materials23 *        provided with the distribution.24 *25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE32 * SOFTWARE.33 */34 35#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt36 37#include <linux/kernel.h>38#include <linux/module.h>39#include <linux/init.h>40#include <linux/pci.h>41#include <linux/mm.h>42#include <linux/notifier.h>43#include <linux/kdebug.h>44#include <linux/seq_file.h>45#include <linux/debugfs.h>46#include <linux/string.h>47#include <linux/export.h>48 49#include "csio_init.h"50#include "csio_defs.h"51 52#define CSIO_MIN_MEMPOOL_SZ	6453 54static struct dentry *csio_debugfs_root;55 56static struct scsi_transport_template *csio_fcoe_transport;57static struct scsi_transport_template *csio_fcoe_transport_vport;58 59/*60 * debugfs support61 */62static ssize_t63csio_mem_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)64{65	loff_t pos = *ppos;66	loff_t avail = file_inode(file)->i_size;67	unsigned int mem = (uintptr_t)file->private_data & 3;68	struct csio_hw *hw = file->private_data - mem;69 70	if (pos < 0)71		return -EINVAL;72	if (pos >= avail)73		return 0;74	if (count > avail - pos)75		count = avail - pos;76 77	while (count) {78		size_t len;79		int ret, ofst;80		__be32 data[16];81 82		if (mem == MEM_MC)83			ret = hw->chip_ops->chip_mc_read(hw, 0, pos,84							 data, NULL);85		else86			ret = hw->chip_ops->chip_edc_read(hw, mem, pos,87							  data, NULL);88		if (ret)89			return ret;90 91		ofst = pos % sizeof(data);92		len = min(count, sizeof(data) - ofst);93		if (copy_to_user(buf, (u8 *)data + ofst, len))94			return -EFAULT;95 96		buf += len;97		pos += len;98		count -= len;99	}100	count = pos - *ppos;101	*ppos = pos;102	return count;103}104 105static const struct file_operations csio_mem_debugfs_fops = {106	.owner   = THIS_MODULE,107	.open    = simple_open,108	.read    = csio_mem_read,109	.llseek  = default_llseek,110};111 112void csio_add_debugfs_mem(struct csio_hw *hw, const char *name,113				 unsigned int idx, unsigned int size_mb)114{115	debugfs_create_file_size(name, S_IRUSR, hw->debugfs_root,116				 (void *)hw + idx, &csio_mem_debugfs_fops,117				 size_mb << 20);118}119 120static int csio_setup_debugfs(struct csio_hw *hw)121{122	int i;123 124	if (IS_ERR_OR_NULL(hw->debugfs_root))125		return -1;126 127	i = csio_rd_reg32(hw, MA_TARGET_MEM_ENABLE_A);128	if (i & EDRAM0_ENABLE_F)129		csio_add_debugfs_mem(hw, "edc0", MEM_EDC0, 5);130	if (i & EDRAM1_ENABLE_F)131		csio_add_debugfs_mem(hw, "edc1", MEM_EDC1, 5);132 133	hw->chip_ops->chip_dfs_create_ext_mem(hw);134	return 0;135}136 137/*138 * csio_dfs_create - Creates and sets up per-hw debugfs.139 *140 */141static int142csio_dfs_create(struct csio_hw *hw)143{144	if (csio_debugfs_root) {145		hw->debugfs_root = debugfs_create_dir(pci_name(hw->pdev),146							csio_debugfs_root);147		csio_setup_debugfs(hw);148	}149 150	return 0;151}152 153/*154 * csio_dfs_destroy - Destroys per-hw debugfs.155 */156static void157csio_dfs_destroy(struct csio_hw *hw)158{159	debugfs_remove_recursive(hw->debugfs_root);160}161 162/*163 * csio_dfs_init - Debug filesystem initialization for the module.164 *165 */166static void167csio_dfs_init(void)168{169	csio_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);170}171 172/*173 * csio_dfs_exit - debugfs cleanup for the module.174 */175static void176csio_dfs_exit(void)177{178	debugfs_remove(csio_debugfs_root);179}180 181/*182 * csio_pci_init - PCI initialization.183 * @pdev: PCI device.184 * @bars: Bitmask of bars to be requested.185 *186 * Initializes the PCI function by enabling MMIO, setting bus187 * mastership and setting DMA mask.188 */189static int190csio_pci_init(struct pci_dev *pdev, int *bars)191{192	int rv = -ENODEV;193 194	*bars = pci_select_bars(pdev, IORESOURCE_MEM);195 196	if (pci_enable_device_mem(pdev))197		goto err;198 199	if (pci_request_selected_regions(pdev, *bars, KBUILD_MODNAME))200		goto err_disable_device;201 202	pci_set_master(pdev);203	pci_try_set_mwi(pdev);204 205	rv = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));206	if (rv)207		rv = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));208	if (rv) {209		rv = -ENODEV;210		dev_err(&pdev->dev, "No suitable DMA available.\n");211		goto err_release_regions;212	}213 214	return 0;215 216err_release_regions:217	pci_release_selected_regions(pdev, *bars);218err_disable_device:219	pci_disable_device(pdev);220err:221	return rv;222 223}224 225/*226 * csio_pci_exit - PCI unitialization.227 * @pdev: PCI device.228 * @bars: Bars to be released.229 *230 */231static void232csio_pci_exit(struct pci_dev *pdev, int *bars)233{234	pci_release_selected_regions(pdev, *bars);235	pci_disable_device(pdev);236}237 238/*239 * csio_hw_init_workers - Initialize the HW module's worker threads.240 * @hw: HW module.241 *242 */243static void244csio_hw_init_workers(struct csio_hw *hw)245{246	INIT_WORK(&hw->evtq_work, csio_evtq_worker);247}248 249static void250csio_hw_exit_workers(struct csio_hw *hw)251{252	cancel_work_sync(&hw->evtq_work);253}254 255static int256csio_create_queues(struct csio_hw *hw)257{258	int i, j;259	struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);260	int rv;261	struct csio_scsi_cpu_info *info;262 263	if (hw->flags & CSIO_HWF_Q_FW_ALLOCED)264		return 0;265 266	if (hw->intr_mode != CSIO_IM_MSIX) {267		rv = csio_wr_iq_create(hw, NULL, hw->intr_iq_idx,268					0, hw->pport[0].portid, false, NULL);269		if (rv != 0) {270			csio_err(hw, " Forward Interrupt IQ failed!: %d\n", rv);271			return rv;272		}273	}274 275	/* FW event queue */276	rv = csio_wr_iq_create(hw, NULL, hw->fwevt_iq_idx,277			       csio_get_fwevt_intr_idx(hw),278			       hw->pport[0].portid, true, NULL);279	if (rv != 0) {280		csio_err(hw, "FW event IQ config failed!: %d\n", rv);281		return rv;282	}283 284	/* Create mgmt queue */285	rv = csio_wr_eq_create(hw, NULL, mgmtm->eq_idx,286			mgmtm->iq_idx, hw->pport[0].portid, NULL);287 288	if (rv != 0) {289		csio_err(hw, "Mgmt EQ create failed!: %d\n", rv);290		goto err;291	}292 293	/* Create SCSI queues */294	for (i = 0; i < hw->num_pports; i++) {295		info = &hw->scsi_cpu_info[i];296 297		for (j = 0; j < info->max_cpus; j++) {298			struct csio_scsi_qset *sqset = &hw->sqset[i][j];299 300			rv = csio_wr_iq_create(hw, NULL, sqset->iq_idx,301					       sqset->intr_idx, i, false, NULL);302			if (rv != 0) {303				csio_err(hw,304				   "SCSI module IQ config failed [%d][%d]:%d\n",305				   i, j, rv);306				goto err;307			}308			rv = csio_wr_eq_create(hw, NULL, sqset->eq_idx,309					       sqset->iq_idx, i, NULL);310			if (rv != 0) {311				csio_err(hw,312				   "SCSI module EQ config failed [%d][%d]:%d\n",313				   i, j, rv);314				goto err;315			}316		} /* for all CPUs */317	} /* For all ports */318 319	hw->flags |= CSIO_HWF_Q_FW_ALLOCED;320	return 0;321err:322	csio_wr_destroy_queues(hw, true);323	return -EINVAL;324}325 326/*327 * csio_config_queues - Configure the DMA queues.328 * @hw: HW module.329 *330 * Allocates memory for queues are registers them with FW.331 */332int333csio_config_queues(struct csio_hw *hw)334{335	int i, j, idx, k = 0;336	int rv;337	struct csio_scsi_qset *sqset;338	struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw);339	struct csio_scsi_qset *orig;340	struct csio_scsi_cpu_info *info;341 342	if (hw->flags & CSIO_HWF_Q_MEM_ALLOCED)343		return csio_create_queues(hw);344 345	/* Calculate number of SCSI queues for MSIX we would like */346	hw->num_scsi_msix_cpus = num_online_cpus();347	hw->num_sqsets = num_online_cpus() * hw->num_pports;348 349	if (hw->num_sqsets > CSIO_MAX_SCSI_QSETS) {350		hw->num_sqsets = CSIO_MAX_SCSI_QSETS;351		hw->num_scsi_msix_cpus = CSIO_MAX_SCSI_CPU;352	}353 354	/* Initialize max_cpus, may get reduced during msix allocations */355	for (i = 0; i < hw->num_pports; i++)356		hw->scsi_cpu_info[i].max_cpus = hw->num_scsi_msix_cpus;357 358	csio_dbg(hw, "nsqsets:%d scpus:%d\n",359		    hw->num_sqsets, hw->num_scsi_msix_cpus);360 361	csio_intr_enable(hw);362 363	if (hw->intr_mode != CSIO_IM_MSIX) {364 365		/* Allocate Forward interrupt iq. */366		hw->intr_iq_idx = csio_wr_alloc_q(hw, CSIO_INTR_IQSIZE,367						CSIO_INTR_WRSIZE, CSIO_INGRESS,368						(void *)hw, 0, 0, NULL);369		if (hw->intr_iq_idx == -1) {370			csio_err(hw,371				 "Forward interrupt queue creation failed\n");372			goto intr_disable;373		}374	}375 376	/* Allocate the FW evt queue */377	hw->fwevt_iq_idx = csio_wr_alloc_q(hw, CSIO_FWEVT_IQSIZE,378					   CSIO_FWEVT_WRSIZE,379					   CSIO_INGRESS, (void *)hw,380					   CSIO_FWEVT_FLBUFS, 0,381					   csio_fwevt_intx_handler);382	if (hw->fwevt_iq_idx == -1) {383		csio_err(hw, "FW evt queue creation failed\n");384		goto intr_disable;385	}386 387	/* Allocate the mgmt queue */388	mgmtm->eq_idx = csio_wr_alloc_q(hw, CSIO_MGMT_EQSIZE,389				      CSIO_MGMT_EQ_WRSIZE,390				      CSIO_EGRESS, (void *)hw, 0, 0, NULL);391	if (mgmtm->eq_idx == -1) {392		csio_err(hw, "Failed to alloc egress queue for mgmt module\n");393		goto intr_disable;394	}395 396	/* Use FW IQ for MGMT req completion */397	mgmtm->iq_idx = hw->fwevt_iq_idx;398 399	/* Allocate SCSI queues */400	for (i = 0; i < hw->num_pports; i++) {401		info = &hw->scsi_cpu_info[i];402 403		for (j = 0; j < hw->num_scsi_msix_cpus; j++) {404			sqset = &hw->sqset[i][j];405 406			if (j >= info->max_cpus) {407				k = j % info->max_cpus;408				orig = &hw->sqset[i][k];409				sqset->eq_idx = orig->eq_idx;410				sqset->iq_idx = orig->iq_idx;411				continue;412			}413 414			idx = csio_wr_alloc_q(hw, csio_scsi_eqsize, 0,415					      CSIO_EGRESS, (void *)hw, 0, 0,416					      NULL);417			if (idx == -1) {418				csio_err(hw, "EQ creation failed for idx:%d\n",419					    idx);420				goto intr_disable;421			}422 423			sqset->eq_idx = idx;424 425			idx = csio_wr_alloc_q(hw, CSIO_SCSI_IQSIZE,426					     CSIO_SCSI_IQ_WRSZ, CSIO_INGRESS,427					     (void *)hw, 0, 0,428					     csio_scsi_intx_handler);429			if (idx == -1) {430				csio_err(hw, "IQ creation failed for idx:%d\n",431					    idx);432				goto intr_disable;433			}434			sqset->iq_idx = idx;435		} /* for all CPUs */436	} /* For all ports */437 438	hw->flags |= CSIO_HWF_Q_MEM_ALLOCED;439 440	rv = csio_create_queues(hw);441	if (rv != 0)442		goto intr_disable;443 444	/*445	 * Now request IRQs for the vectors. In the event of a failure,446	 * cleanup is handled internally by this function.447	 */448	rv = csio_request_irqs(hw);449	if (rv != 0)450		return -EINVAL;451 452	return 0;453 454intr_disable:455	csio_intr_disable(hw, false);456 457	return -EINVAL;458}459 460static int461csio_resource_alloc(struct csio_hw *hw)462{463	struct csio_wrm *wrm = csio_hw_to_wrm(hw);464	int rv = -ENOMEM;465 466	wrm->num_q = ((CSIO_MAX_SCSI_QSETS * 2) + CSIO_HW_NIQ +467		       CSIO_HW_NEQ + CSIO_HW_NFLQ + CSIO_HW_NINTXQ);468 469	hw->mb_mempool = mempool_create_kmalloc_pool(CSIO_MIN_MEMPOOL_SZ,470						  sizeof(struct csio_mb));471	if (!hw->mb_mempool)472		goto err;473 474	hw->rnode_mempool = mempool_create_kmalloc_pool(CSIO_MIN_MEMPOOL_SZ,475						     sizeof(struct csio_rnode));476	if (!hw->rnode_mempool)477		goto err_free_mb_mempool;478 479	hw->scsi_dma_pool = dma_pool_create("csio_scsi_dma_pool",480					    &hw->pdev->dev, CSIO_SCSI_RSP_LEN,481					    8, 0);482	if (!hw->scsi_dma_pool)483		goto err_free_rn_pool;484 485	return 0;486 487err_free_rn_pool:488	mempool_destroy(hw->rnode_mempool);489	hw->rnode_mempool = NULL;490err_free_mb_mempool:491	mempool_destroy(hw->mb_mempool);492	hw->mb_mempool = NULL;493err:494	return rv;495}496 497static void498csio_resource_free(struct csio_hw *hw)499{500	dma_pool_destroy(hw->scsi_dma_pool);501	hw->scsi_dma_pool = NULL;502	mempool_destroy(hw->rnode_mempool);503	hw->rnode_mempool = NULL;504	mempool_destroy(hw->mb_mempool);505	hw->mb_mempool = NULL;506}507 508/*509 * csio_hw_alloc - Allocate and initialize the HW module.510 * @pdev: PCI device.511 *512 * Allocates HW structure, DMA, memory resources, maps BARS to513 * host memory and initializes HW module.514 */515static struct csio_hw *csio_hw_alloc(struct pci_dev *pdev)516{517	struct csio_hw *hw;518 519	hw = kzalloc(sizeof(struct csio_hw), GFP_KERNEL);520	if (!hw)521		goto err;522 523	hw->pdev = pdev;524	strscpy(hw->drv_version, CSIO_DRV_VERSION,525		sizeof(hw->drv_version));526 527	/* memory pool/DMA pool allocation */528	if (csio_resource_alloc(hw))529		goto err_free_hw;530 531	/* Get the start address of registers from BAR 0 */532	hw->regstart = ioremap(pci_resource_start(pdev, 0),533				       pci_resource_len(pdev, 0));534	if (!hw->regstart) {535		csio_err(hw, "Could not map BAR 0, regstart = %p\n",536			 hw->regstart);537		goto err_resource_free;538	}539 540	csio_hw_init_workers(hw);541 542	if (csio_hw_init(hw))543		goto err_unmap_bar;544 545	csio_dfs_create(hw);546 547	csio_dbg(hw, "hw:%p\n", hw);548 549	return hw;550 551err_unmap_bar:552	csio_hw_exit_workers(hw);553	iounmap(hw->regstart);554err_resource_free:555	csio_resource_free(hw);556err_free_hw:557	kfree(hw);558err:559	return NULL;560}561 562/*563 * csio_hw_free - Uninitialize and free the HW module.564 * @hw: The HW module565 *566 * Disable interrupts, uninit the HW module, free resources, free hw.567 */568static void569csio_hw_free(struct csio_hw *hw)570{571	csio_intr_disable(hw, true);572	csio_hw_exit_workers(hw);573	csio_hw_exit(hw);574	iounmap(hw->regstart);575	csio_dfs_destroy(hw);576	csio_resource_free(hw);577	kfree(hw);578}579 580/**581 * csio_shost_init - Create and initialize the lnode module.582 * @hw:		The HW module.583 * @dev:	The device associated with this invocation.584 * @probe:	Called from probe context or not?585 * @pln:	Parent lnode if any.586 *587 * Allocates lnode structure via scsi_host_alloc, initializes588 * shost, initializes lnode module and registers with SCSI ML589 * via scsi_host_add. This function is shared between physical and590 * virtual node ports.591 */592struct csio_lnode *593csio_shost_init(struct csio_hw *hw, struct device *dev,594		  bool probe, struct csio_lnode *pln)595{596	struct Scsi_Host  *shost = NULL;597	struct csio_lnode *ln;598 599	csio_fcoe_shost_template.cmd_per_lun = csio_lun_qdepth;600	csio_fcoe_shost_vport_template.cmd_per_lun = csio_lun_qdepth;601 602	/*603	 * hw->pdev is the physical port's PCI dev structure,604	 * which will be different from the NPIV dev structure.605	 */606	if (dev == &hw->pdev->dev)607		shost = scsi_host_alloc(608				&csio_fcoe_shost_template,609				sizeof(struct csio_lnode));610	else611		shost = scsi_host_alloc(612				&csio_fcoe_shost_vport_template,613				sizeof(struct csio_lnode));614 615	if (!shost)616		goto err;617 618	ln = shost_priv(shost);619	memset(ln, 0, sizeof(struct csio_lnode));620 621	/* Link common lnode to this lnode */622	ln->dev_num = (shost->host_no << 16);623 624	shost->can_queue = CSIO_MAX_QUEUE;625	shost->this_id = -1;626	shost->unique_id = shost->host_no;627	shost->max_cmd_len = 16; /* Max CDB length supported */628	shost->max_id = min_t(uint32_t, csio_fcoe_rnodes,629			      hw->fres_info.max_ssns);630	shost->max_lun = CSIO_MAX_LUN;631	if (dev == &hw->pdev->dev)632		shost->transportt = csio_fcoe_transport;633	else634		shost->transportt = csio_fcoe_transport_vport;635 636	/* root lnode */637	if (!hw->rln)638		hw->rln = ln;639 640	/* Other initialization here: Common, Transport specific */641	if (csio_lnode_init(ln, hw, pln))642		goto err_shost_put;643 644	if (scsi_add_host_with_dma(shost, dev, &hw->pdev->dev))645		goto err_lnode_exit;646 647	return ln;648 649err_lnode_exit:650	csio_lnode_exit(ln);651err_shost_put:652	scsi_host_put(shost);653err:654	return NULL;655}656 657/**658 * csio_shost_exit - De-instantiate the shost.659 * @ln:		The lnode module corresponding to the shost.660 *661 */662void663csio_shost_exit(struct csio_lnode *ln)664{665	struct Scsi_Host *shost = csio_ln_to_shost(ln);666	struct csio_hw *hw = csio_lnode_to_hw(ln);667 668	/* Inform transport */669	fc_remove_host(shost);670 671	/* Inform SCSI ML */672	scsi_remove_host(shost);673 674	/* Flush all the events, so that any rnode removal events675	 * already queued are all handled, before we remove the lnode.676	 */677	spin_lock_irq(&hw->lock);678	csio_evtq_flush(hw);679	spin_unlock_irq(&hw->lock);680 681	csio_lnode_exit(ln);682	scsi_host_put(shost);683}684 685struct csio_lnode *686csio_lnode_alloc(struct csio_hw *hw)687{688	return csio_shost_init(hw, &hw->pdev->dev, false, NULL);689}690 691void692csio_lnodes_block_request(struct csio_hw *hw)693{694	struct Scsi_Host  *shost;695	struct csio_lnode *sln;696	struct csio_lnode *ln;697	struct list_head *cur_ln, *cur_cln;698	struct csio_lnode **lnode_list;699	int cur_cnt = 0, ii;700 701	lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),702			GFP_KERNEL);703	if (!lnode_list) {704		csio_err(hw, "Failed to allocate lnodes_list");705		return;706	}707 708	spin_lock_irq(&hw->lock);709	/* Traverse sibling lnodes */710	list_for_each(cur_ln, &hw->sln_head) {711		sln = (struct csio_lnode *) cur_ln;712		lnode_list[cur_cnt++] = sln;713 714		/* Traverse children lnodes */715		list_for_each(cur_cln, &sln->cln_head)716			lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;717	}718	spin_unlock_irq(&hw->lock);719 720	for (ii = 0; ii < cur_cnt; ii++) {721		csio_dbg(hw, "Blocking IOs on lnode: %p\n", lnode_list[ii]);722		ln = lnode_list[ii];723		shost = csio_ln_to_shost(ln);724		scsi_block_requests(shost);725 726	}727	kfree(lnode_list);728}729 730void731csio_lnodes_unblock_request(struct csio_hw *hw)732{733	struct csio_lnode *ln;734	struct Scsi_Host  *shost;735	struct csio_lnode *sln;736	struct list_head *cur_ln, *cur_cln;737	struct csio_lnode **lnode_list;738	int cur_cnt = 0, ii;739 740	lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),741			GFP_KERNEL);742	if (!lnode_list) {743		csio_err(hw, "Failed to allocate lnodes_list");744		return;745	}746 747	spin_lock_irq(&hw->lock);748	/* Traverse sibling lnodes */749	list_for_each(cur_ln, &hw->sln_head) {750		sln = (struct csio_lnode *) cur_ln;751		lnode_list[cur_cnt++] = sln;752 753		/* Traverse children lnodes */754		list_for_each(cur_cln, &sln->cln_head)755			lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;756	}757	spin_unlock_irq(&hw->lock);758 759	for (ii = 0; ii < cur_cnt; ii++) {760		csio_dbg(hw, "unblocking IOs on lnode: %p\n", lnode_list[ii]);761		ln = lnode_list[ii];762		shost = csio_ln_to_shost(ln);763		scsi_unblock_requests(shost);764	}765	kfree(lnode_list);766}767 768void769csio_lnodes_block_by_port(struct csio_hw *hw, uint8_t portid)770{771	struct csio_lnode *ln;772	struct Scsi_Host  *shost;773	struct csio_lnode *sln;774	struct list_head *cur_ln, *cur_cln;775	struct csio_lnode **lnode_list;776	int cur_cnt = 0, ii;777 778	lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),779			GFP_KERNEL);780	if (!lnode_list) {781		csio_err(hw, "Failed to allocate lnodes_list");782		return;783	}784 785	spin_lock_irq(&hw->lock);786	/* Traverse sibling lnodes */787	list_for_each(cur_ln, &hw->sln_head) {788		sln = (struct csio_lnode *) cur_ln;789		if (sln->portid != portid)790			continue;791 792		lnode_list[cur_cnt++] = sln;793 794		/* Traverse children lnodes */795		list_for_each(cur_cln, &sln->cln_head)796			lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;797	}798	spin_unlock_irq(&hw->lock);799 800	for (ii = 0; ii < cur_cnt; ii++) {801		csio_dbg(hw, "Blocking IOs on lnode: %p\n", lnode_list[ii]);802		ln = lnode_list[ii];803		shost = csio_ln_to_shost(ln);804		scsi_block_requests(shost);805	}806	kfree(lnode_list);807}808 809void810csio_lnodes_unblock_by_port(struct csio_hw *hw, uint8_t portid)811{812	struct csio_lnode *ln;813	struct Scsi_Host  *shost;814	struct csio_lnode *sln;815	struct list_head *cur_ln, *cur_cln;816	struct csio_lnode **lnode_list;817	int cur_cnt = 0, ii;818 819	lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),820			GFP_KERNEL);821	if (!lnode_list) {822		csio_err(hw, "Failed to allocate lnodes_list");823		return;824	}825 826	spin_lock_irq(&hw->lock);827	/* Traverse sibling lnodes */828	list_for_each(cur_ln, &hw->sln_head) {829		sln = (struct csio_lnode *) cur_ln;830		if (sln->portid != portid)831			continue;832		lnode_list[cur_cnt++] = sln;833 834		/* Traverse children lnodes */835		list_for_each(cur_cln, &sln->cln_head)836			lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;837	}838	spin_unlock_irq(&hw->lock);839 840	for (ii = 0; ii < cur_cnt; ii++) {841		csio_dbg(hw, "unblocking IOs on lnode: %p\n", lnode_list[ii]);842		ln = lnode_list[ii];843		shost = csio_ln_to_shost(ln);844		scsi_unblock_requests(shost);845	}846	kfree(lnode_list);847}848 849void850csio_lnodes_exit(struct csio_hw *hw, bool npiv)851{852	struct csio_lnode *sln;853	struct csio_lnode *ln;854	struct list_head *cur_ln, *cur_cln;855	struct csio_lnode **lnode_list;856	int cur_cnt = 0, ii;857 858	lnode_list = kzalloc((sizeof(struct csio_lnode *) * hw->num_lns),859			GFP_KERNEL);860	if (!lnode_list) {861		csio_err(hw, "lnodes_exit: Failed to allocate lnodes_list.\n");862		return;863	}864 865	/* Get all child lnodes(NPIV ports) */866	spin_lock_irq(&hw->lock);867	list_for_each(cur_ln, &hw->sln_head) {868		sln = (struct csio_lnode *) cur_ln;869 870		/* Traverse children lnodes */871		list_for_each(cur_cln, &sln->cln_head)872			lnode_list[cur_cnt++] = (struct csio_lnode *) cur_cln;873	}874	spin_unlock_irq(&hw->lock);875 876	/* Delete NPIV lnodes */877	for (ii = 0; ii < cur_cnt; ii++) {878		csio_dbg(hw, "Deleting child lnode: %p\n", lnode_list[ii]);879		ln = lnode_list[ii];880		fc_vport_terminate(ln->fc_vport);881	}882 883	/* Delete only npiv lnodes */884	if (npiv)885		goto free_lnodes;886 887	cur_cnt = 0;888	/* Get all physical lnodes */889	spin_lock_irq(&hw->lock);890	/* Traverse sibling lnodes */891	list_for_each(cur_ln, &hw->sln_head) {892		sln = (struct csio_lnode *) cur_ln;893		lnode_list[cur_cnt++] = sln;894	}895	spin_unlock_irq(&hw->lock);896 897	/* Delete physical lnodes */898	for (ii = 0; ii < cur_cnt; ii++) {899		csio_dbg(hw, "Deleting parent lnode: %p\n", lnode_list[ii]);900		csio_shost_exit(lnode_list[ii]);901	}902 903free_lnodes:904	kfree(lnode_list);905}906 907/*908 * csio_lnode_init_post: Set lnode attributes after starting HW.909 * @ln: lnode.910 *911 */912static void913csio_lnode_init_post(struct csio_lnode *ln)914{915	struct Scsi_Host  *shost = csio_ln_to_shost(ln);916 917	csio_fchost_attr_init(ln);918 919	scsi_scan_host(shost);920}921 922/*923 * csio_probe_one - Instantiate this function.924 * @pdev: PCI device925 * @id: Device ID926 *927 * This is the .probe() callback of the driver. This function:928 * - Initializes the PCI function by enabling MMIO, setting bus929 *   mastership and setting DMA mask.930 * - Allocates HW structure, DMA, memory resources, maps BARS to931 *   host memory and initializes HW module.932 * - Allocates lnode structure via scsi_host_alloc, initializes933 *   shost, initialized lnode module and registers with SCSI ML934 *   via scsi_host_add.935 * - Enables interrupts, and starts the chip by kicking off the936 *   HW state machine.937 * - Once hardware is ready, initiated scan of the host via938 *   scsi_scan_host.939 */940static int csio_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)941{942	int rv;943	int bars;944	int i;945	struct csio_hw *hw;946	struct csio_lnode *ln;947 948	/* probe only T5 and T6 cards */949	if (!csio_is_t5((pdev->device & CSIO_HW_CHIP_MASK)) &&950	    !csio_is_t6((pdev->device & CSIO_HW_CHIP_MASK)))951		return -ENODEV;952 953	rv = csio_pci_init(pdev, &bars);954	if (rv)955		goto err;956 957	hw = csio_hw_alloc(pdev);958	if (!hw) {959		rv = -ENODEV;960		goto err_pci_exit;961	}962 963	if (!pcie_relaxed_ordering_enabled(pdev))964		hw->flags |= CSIO_HWF_ROOT_NO_RELAXED_ORDERING;965 966	pci_set_drvdata(pdev, hw);967 968	rv = csio_hw_start(hw);969	if (rv) {970		if (rv == -EINVAL) {971			dev_err(&pdev->dev,972				"Failed to start FW, continuing in debug mode.\n");973			return 0;974		}975		goto err_lnode_exit;976	}977 978	sprintf(hw->fwrev_str, "%u.%u.%u.%u\n",979		    FW_HDR_FW_VER_MAJOR_G(hw->fwrev),980		    FW_HDR_FW_VER_MINOR_G(hw->fwrev),981		    FW_HDR_FW_VER_MICRO_G(hw->fwrev),982		    FW_HDR_FW_VER_BUILD_G(hw->fwrev));983 984	for (i = 0; i < hw->num_pports; i++) {985		ln = csio_shost_init(hw, &pdev->dev, true, NULL);986		if (!ln) {987			rv = -ENODEV;988			break;989		}990		/* Initialize portid */991		ln->portid = hw->pport[i].portid;992 993		spin_lock_irq(&hw->lock);994		if (csio_lnode_start(ln) != 0)995			rv = -ENODEV;996		spin_unlock_irq(&hw->lock);997 998		if (rv)999			break;1000 1001		csio_lnode_init_post(ln);1002	}1003 1004	if (rv)1005		goto err_lnode_exit;1006 1007	return 0;1008 1009err_lnode_exit:1010	csio_lnodes_block_request(hw);1011	spin_lock_irq(&hw->lock);1012	csio_hw_stop(hw);1013	spin_unlock_irq(&hw->lock);1014	csio_lnodes_unblock_request(hw);1015	csio_lnodes_exit(hw, 0);1016	csio_hw_free(hw);1017err_pci_exit:1018	csio_pci_exit(pdev, &bars);1019err:1020	dev_err(&pdev->dev, "probe of device failed: %d\n", rv);1021	return rv;1022}1023 1024/*1025 * csio_remove_one - Remove one instance of the driver at this PCI function.1026 * @pdev: PCI device1027 *1028 * Used during hotplug operation.1029 */1030static void csio_remove_one(struct pci_dev *pdev)1031{1032	struct csio_hw *hw = pci_get_drvdata(pdev);1033	int bars = pci_select_bars(pdev, IORESOURCE_MEM);1034 1035	csio_lnodes_block_request(hw);1036	spin_lock_irq(&hw->lock);1037 1038	/* Stops lnode, Rnode s/m1039	 * Quiesce IOs.1040	 * All sessions with remote ports are unregistered.1041	 */1042	csio_hw_stop(hw);1043	spin_unlock_irq(&hw->lock);1044	csio_lnodes_unblock_request(hw);1045 1046	csio_lnodes_exit(hw, 0);1047	csio_hw_free(hw);1048	csio_pci_exit(pdev, &bars);1049}1050 1051/*1052 * csio_pci_error_detected - PCI error was detected1053 * @pdev: PCI device1054 *1055 */1056static pci_ers_result_t1057csio_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)1058{1059	struct csio_hw *hw = pci_get_drvdata(pdev);1060 1061	csio_lnodes_block_request(hw);1062	spin_lock_irq(&hw->lock);1063 1064	/* Post PCI error detected evt to HW s/m1065	 * HW s/m handles this evt by quiescing IOs, unregisters rports1066	 * and finally takes the device to offline.1067	 */1068	csio_post_event(&hw->sm, CSIO_HWE_PCIERR_DETECTED);1069	spin_unlock_irq(&hw->lock);1070	csio_lnodes_unblock_request(hw);1071	csio_lnodes_exit(hw, 0);1072	csio_intr_disable(hw, true);1073	pci_disable_device(pdev);1074	return state == pci_channel_io_perm_failure ?1075		PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;1076}1077 1078/*1079 * csio_pci_slot_reset - PCI slot has been reset.1080 * @pdev: PCI device1081 *1082 */1083static pci_ers_result_t1084csio_pci_slot_reset(struct pci_dev *pdev)1085{1086	struct csio_hw *hw = pci_get_drvdata(pdev);1087	int ready;1088 1089	if (pci_enable_device(pdev)) {1090		dev_err(&pdev->dev, "cannot re-enable device in slot reset\n");1091		return PCI_ERS_RESULT_DISCONNECT;1092	}1093 1094	pci_set_master(pdev);1095	pci_restore_state(pdev);1096	pci_save_state(pdev);1097 1098	/* Bring HW s/m to ready state.1099	 * but don't resume IOs.1100	 */1101	spin_lock_irq(&hw->lock);1102	csio_post_event(&hw->sm, CSIO_HWE_PCIERR_SLOT_RESET);1103	ready = csio_is_hw_ready(hw);1104	spin_unlock_irq(&hw->lock);1105 1106	if (ready) {1107		return PCI_ERS_RESULT_RECOVERED;1108	} else {1109		dev_err(&pdev->dev, "Can't initialize HW when in slot reset\n");1110		return PCI_ERS_RESULT_DISCONNECT;1111	}1112}1113 1114/*1115 * csio_pci_resume - Resume normal operations1116 * @pdev: PCI device1117 *1118 */1119static void1120csio_pci_resume(struct pci_dev *pdev)1121{1122	struct csio_hw *hw = pci_get_drvdata(pdev);1123	struct csio_lnode *ln;1124	int rv = 0;1125	int i;1126 1127	/* Bring the LINK UP and Resume IO */1128 1129	for (i = 0; i < hw->num_pports; i++) {1130		ln = csio_shost_init(hw, &pdev->dev, true, NULL);1131		if (!ln) {1132			rv = -ENODEV;1133			break;1134		}1135		/* Initialize portid */1136		ln->portid = hw->pport[i].portid;1137 1138		spin_lock_irq(&hw->lock);1139		if (csio_lnode_start(ln) != 0)1140			rv = -ENODEV;1141		spin_unlock_irq(&hw->lock);1142 1143		if (rv)1144			break;1145 1146		csio_lnode_init_post(ln);1147	}1148 1149	if (rv)1150		goto err_resume_exit;1151 1152	return;1153 1154err_resume_exit:1155	csio_lnodes_block_request(hw);1156	spin_lock_irq(&hw->lock);1157	csio_hw_stop(hw);1158	spin_unlock_irq(&hw->lock);1159	csio_lnodes_unblock_request(hw);1160	csio_lnodes_exit(hw, 0);1161	csio_hw_free(hw);1162	dev_err(&pdev->dev, "resume of device failed: %d\n", rv);1163}1164 1165static struct pci_error_handlers csio_err_handler = {1166	.error_detected = csio_pci_error_detected,1167	.slot_reset	= csio_pci_slot_reset,1168	.resume		= csio_pci_resume,1169};1170 1171/*1172 *  Macros needed to support the PCI Device ID Table ...1173 */1174#define CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN \1175	static const struct pci_device_id csio_pci_tbl[] = {1176/* Define for FCoE uses PF6 */1177#define CH_PCI_DEVICE_ID_FUNCTION	0x61178 1179#define CH_PCI_ID_TABLE_ENTRY(devid) \1180		{ PCI_VDEVICE(CHELSIO, (devid)), 0 }1181 1182#define CH_PCI_DEVICE_ID_TABLE_DEFINE_END { 0, } }1183 1184#include "t4_pci_id_tbl.h"1185 1186static struct pci_driver csio_pci_driver = {1187	.name		= KBUILD_MODNAME,1188	.id_table	= csio_pci_tbl,1189	.probe		= csio_probe_one,1190	.remove		= csio_remove_one,1191	.err_handler	= &csio_err_handler,1192};1193 1194/*1195 * csio_init - Chelsio storage driver initialization function.1196 *1197 */1198static int __init1199csio_init(void)1200{1201	int rv = -ENOMEM;1202 1203	pr_info("%s %s\n", CSIO_DRV_DESC, CSIO_DRV_VERSION);1204 1205	csio_dfs_init();1206 1207	csio_fcoe_transport = fc_attach_transport(&csio_fc_transport_funcs);1208	if (!csio_fcoe_transport)1209		goto err;1210 1211	csio_fcoe_transport_vport =1212			fc_attach_transport(&csio_fc_transport_vport_funcs);1213	if (!csio_fcoe_transport_vport)1214		goto err_vport;1215 1216	rv = pci_register_driver(&csio_pci_driver);1217	if (rv)1218		goto err_pci;1219 1220	return 0;1221 1222err_pci:1223	fc_release_transport(csio_fcoe_transport_vport);1224err_vport:1225	fc_release_transport(csio_fcoe_transport);1226err:1227	csio_dfs_exit();1228	return rv;1229}1230 1231/*1232 * csio_exit - Chelsio storage driver uninitialization .1233 *1234 * Function that gets called in the unload path.1235 */1236static void __exit1237csio_exit(void)1238{1239	pci_unregister_driver(&csio_pci_driver);1240	csio_dfs_exit();1241	fc_release_transport(csio_fcoe_transport_vport);1242	fc_release_transport(csio_fcoe_transport);1243}1244 1245module_init(csio_init);1246module_exit(csio_exit);1247MODULE_AUTHOR(CSIO_DRV_AUTHOR);1248MODULE_DESCRIPTION(CSIO_DRV_DESC);1249MODULE_LICENSE("Dual BSD/GPL");1250MODULE_DEVICE_TABLE(pci, csio_pci_tbl);1251MODULE_VERSION(CSIO_DRV_VERSION);1252MODULE_FIRMWARE(FW_FNAME_T5);1253MODULE_FIRMWARE(FW_FNAME_T6);1254MODULE_SOFTDEP("pre: cxgb4");1255