/drivers/infiniband/hw/ipath/ipath_driver.c
C | 2816 lines | 1898 code | 306 blank | 612 comment | 328 complexity | ca44f78cee3afdf9b7593b762b99e426 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
- * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
- #include <linux/sched.h>
- #include <linux/spinlock.h>
- #include <linux/idr.h>
- #include <linux/pci.h>
- #include <linux/io.h>
- #include <linux/delay.h>
- #include <linux/netdevice.h>
- #include <linux/vmalloc.h>
- #include <linux/bitmap.h>
- #include <linux/slab.h>
- #include "ipath_kernel.h"
- #include "ipath_verbs.h"
- static void ipath_update_pio_bufs(struct ipath_devdata *);
- const char *ipath_get_unit_name(int unit)
- {
- static char iname[16];
- snprintf(iname, sizeof iname, "infinipath%u", unit);
- return iname;
- }
- #define DRIVER_LOAD_MSG "QLogic " IPATH_DRV_NAME " loaded: "
- #define PFX IPATH_DRV_NAME ": "
- /*
- * The size has to be longer than this string, so we can append
- * board/chip information to it in the init code.
- */
- const char ib_ipath_version[] = IPATH_IDSTR "\n";
- static struct idr unit_table;
- DEFINE_SPINLOCK(ipath_devs_lock);
- LIST_HEAD(ipath_dev_list);
- wait_queue_head_t ipath_state_wait;
- unsigned ipath_debug = __IPATH_INFO;
- module_param_named(debug, ipath_debug, uint, S_IWUSR | S_IRUGO);
- MODULE_PARM_DESC(debug, "mask for debug prints");
- EXPORT_SYMBOL_GPL(ipath_debug);
- unsigned ipath_mtu4096 = 1; /* max 4KB IB mtu by default, if supported */
- module_param_named(mtu4096, ipath_mtu4096, uint, S_IRUGO);
- MODULE_PARM_DESC(mtu4096, "enable MTU of 4096 bytes, if supported");
- static unsigned ipath_hol_timeout_ms = 13000;
- module_param_named(hol_timeout_ms, ipath_hol_timeout_ms, uint, S_IRUGO);
- MODULE_PARM_DESC(hol_timeout_ms,
- "duration of user app suspension after link failure");
- unsigned ipath_linkrecovery = 1;
- module_param_named(linkrecovery, ipath_linkrecovery, uint, S_IWUSR | S_IRUGO);
- MODULE_PARM_DESC(linkrecovery, "enable workaround for link recovery issue");
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("QLogic <support@qlogic.com>");
- MODULE_DESCRIPTION("QLogic InfiniPath driver");
- /*
- * Table to translate the LINKTRAININGSTATE portion of
- * IBCStatus to a human-readable form.
- */
- const char *ipath_ibcstatus_str[] = {
- "Disabled",
- "LinkUp",
- "PollActive",
- "PollQuiet",
- "SleepDelay",
- "SleepQuiet",
- "LState6", /* unused */
- "LState7", /* unused */
- "CfgDebounce",
- "CfgRcvfCfg",
- "CfgWaitRmt",
- "CfgIdle",
- "RecovRetrain",
- "CfgTxRevLane", /* unused before IBA7220 */
- "RecovWaitRmt",
- "RecovIdle",
- /* below were added for IBA7220 */
- "CfgEnhanced",
- "CfgTest",
- "CfgWaitRmtTest",
- "CfgWaitCfgEnhanced",
- "SendTS_T",
- "SendTstIdles",
- "RcvTS_T",
- "SendTst_TS1s",
- "LTState18", "LTState19", "LTState1A", "LTState1B",
- "LTState1C", "LTState1D", "LTState1E", "LTState1F"
- };
- static void __devexit ipath_remove_one(struct pci_dev *);
- static int __devinit ipath_init_one(struct pci_dev *,
- const struct pci_device_id *);
- /* Only needed for registration, nothing else needs this info */
- #define PCI_VENDOR_ID_PATHSCALE 0x1fc1
- #define PCI_VENDOR_ID_QLOGIC 0x1077
- #define PCI_DEVICE_ID_INFINIPATH_HT 0xd
- #define PCI_DEVICE_ID_INFINIPATH_PE800 0x10
- #define PCI_DEVICE_ID_INFINIPATH_7220 0x7220
- /* Number of seconds before our card status check... */
- #define STATUS_TIMEOUT 60
- static const struct pci_device_id ipath_pci_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) },
- { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_PE800) },
- { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_INFINIPATH_7220) },
- { 0, }
- };
- MODULE_DEVICE_TABLE(pci, ipath_pci_tbl);
- static struct pci_driver ipath_driver = {
- .name = IPATH_DRV_NAME,
- .probe = ipath_init_one,
- .remove = __devexit_p(ipath_remove_one),
- .id_table = ipath_pci_tbl,
- .driver = {
- .groups = ipath_driver_attr_groups,
- },
- };
- static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev,
- u32 *bar0, u32 *bar1)
- {
- int ret;
- ret = pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
- if (ret)
- ipath_dev_err(dd, "failed to read bar0 before enable: "
- "error %d\n", -ret);
- ret = pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, bar1);
- if (ret)
- ipath_dev_err(dd, "failed to read bar1 before enable: "
- "error %d\n", -ret);
- ipath_dbg("Read bar0 %x bar1 %x\n", *bar0, *bar1);
- }
- static void ipath_free_devdata(struct pci_dev *pdev,
- struct ipath_devdata *dd)
- {
- unsigned long flags;
- pci_set_drvdata(pdev, NULL);
- if (dd->ipath_unit != -1) {
- spin_lock_irqsave(&ipath_devs_lock, flags);
- idr_remove(&unit_table, dd->ipath_unit);
- list_del(&dd->ipath_list);
- spin_unlock_irqrestore(&ipath_devs_lock, flags);
- }
- vfree(dd);
- }
- static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
- {
- unsigned long flags;
- struct ipath_devdata *dd;
- int ret;
- if (!idr_pre_get(&unit_table, GFP_KERNEL)) {
- dd = ERR_PTR(-ENOMEM);
- goto bail;
- }
- dd = vmalloc(sizeof(*dd));
- if (!dd) {
- dd = ERR_PTR(-ENOMEM);
- goto bail;
- }
- memset(dd, 0, sizeof(*dd));
- dd->ipath_unit = -1;
- spin_lock_irqsave(&ipath_devs_lock, flags);
- ret = idr_get_new(&unit_table, dd, &dd->ipath_unit);
- if (ret < 0) {
- printk(KERN_ERR IPATH_DRV_NAME
- ": Could not allocate unit ID: error %d\n", -ret);
- ipath_free_devdata(pdev, dd);
- dd = ERR_PTR(ret);
- goto bail_unlock;
- }
- dd->pcidev = pdev;
- pci_set_drvdata(pdev, dd);
- list_add(&dd->ipath_list, &ipath_dev_list);
- bail_unlock:
- spin_unlock_irqrestore(&ipath_devs_lock, flags);
- bail:
- return dd;
- }
- static inline struct ipath_devdata *__ipath_lookup(int unit)
- {
- return idr_find(&unit_table, unit);
- }
- struct ipath_devdata *ipath_lookup(int unit)
- {
- struct ipath_devdata *dd;
- unsigned long flags;
-