diff options
| author | Bryan O'Sullivan <bos@pathscale.com> | 2006-03-29 18:23:28 -0500 |
|---|---|---|
| committer | Roland Dreier <rolandd@cisco.com> | 2006-03-31 16:14:19 -0500 |
| commit | 097709fea03140b567bde8369f3ffafe33dfc1c6 (patch) | |
| tree | 98ef94e0abcf13798c6f416ba7a5318ab4b47d7d | |
| parent | dc741bbd4f47080c623d243546dd4cb5ff6c9564 (diff) | |
IB/ipath: chip initialisation code, and diag support
ipath_init_chip.c sets up an InfiniPath device for use.
ipath_diag.c permits userspace diagnostic tools to read and write a
chip's registers. It is different in purpose from the mmap interfaces
to the /sys/bus/pci resource files.
Signed-off-by: Bryan O'Sullivan <bos@pathscale.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_diag.c | 379 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ipath/ipath_init_chip.c | 951 |
2 files changed, 1330 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c new file mode 100644 index 000000000000..cd533cf951c2 --- /dev/null +++ b/drivers/infiniband/hw/ipath/ipath_diag.c | |||
| @@ -0,0 +1,379 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | ||
| 3 | * | ||
| 4 | * This software is available to you under a choice of one of two | ||
| 5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
| 6 | * General Public License (GPL) Version 2, available from the file | ||
| 7 | * COPYING in the main directory of this source tree, or the | ||
| 8 | * OpenIB.org BSD license below: | ||
| 9 | * | ||
| 10 | * Redistribution and use in source and binary forms, with or | ||
| 11 | * without modification, are permitted provided that the following | ||
| 12 | * conditions are met: | ||
| 13 | * | ||
| 14 | * - Redistributions of source code must retain the above | ||
| 15 | * copyright notice, this list of conditions and the following | ||
| 16 | * disclaimer. | ||
| 17 | * | ||
| 18 | * - Redistributions in binary form must reproduce the above | ||
| 19 | * copyright notice, this list of conditions and the following | ||
| 20 | * disclaimer in the documentation and/or other materials | ||
| 21 | * provided with the distribution. | ||
| 22 | * | ||
| 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
| 27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 30 | * SOFTWARE. | ||
| 31 | */ | ||
| 32 | |||
| 33 | /* | ||
| 34 | * This file contains support for diagnostic functions. It is accessed by | ||
| 35 | * opening the ipath_diag device, normally minor number 129. Diagnostic use | ||
| 36 | * of the InfiniPath chip may render the chip or board unusable until the | ||
| 37 | * driver is unloaded, or in some cases, until the system is rebooted. | ||
| 38 | * | ||
| 39 | * Accesses to the chip through this interface are not similar to going | ||
| 40 | * through the /sys/bus/pci resource mmap interface. | ||
| 41 | */ | ||
| 42 | |||
| 43 | #include <linux/pci.h> | ||
| 44 | #include <asm/uaccess.h> | ||
| 45 | |||
| 46 | #include "ipath_common.h" | ||
| 47 | #include "ipath_kernel.h" | ||
| 48 | #include "ips_common.h" | ||
| 49 | #include "ipath_layer.h" | ||
| 50 | |||
| 51 | int ipath_diag_inuse; | ||
| 52 | static int diag_set_link; | ||
| 53 | |||
| 54 | static int ipath_diag_open(struct inode *in, struct file *fp); | ||
| 55 | static int ipath_diag_release(struct inode *in, struct file *fp); | ||
| 56 | static ssize_t ipath_diag_read(struct file *fp, char __user *data, | ||
| 57 | size_t count, loff_t *off); | ||
| 58 | static ssize_t ipath_diag_write(struct file *fp, const char __user *data, | ||
| 59 | size_t count, loff_t *off); | ||
| 60 | |||
| 61 | static struct file_operations diag_file_ops = { | ||
| 62 | .owner = THIS_MODULE, | ||
| 63 | .write = ipath_diag_write, | ||
| 64 | .read = ipath_diag_read, | ||
| 65 | .open = ipath_diag_open, | ||
| 66 | .release = ipath_diag_release | ||
| 67 | }; | ||
| 68 | |||
| 69 | static struct cdev *diag_cdev; | ||
| 70 | static struct class_device *diag_class_dev; | ||
| 71 | |||
| 72 | int ipath_diag_init(void) | ||
| 73 | { | ||
| 74 | return ipath_cdev_init(IPATH_DIAG_MINOR, "ipath_diag", | ||
| 75 | &diag_file_ops, &diag_cdev, &diag_class_dev); | ||
| 76 | } | ||
| 77 | |||
| 78 | void ipath_diag_cleanup(void) | ||
| 79 | { | ||
| 80 | ipath_cdev_cleanup(&diag_cdev, &diag_class_dev); | ||
| 81 | } | ||
| 82 | |||
| 83 | /** | ||
| 84 | * ipath_read_umem64 - read a 64-bit quantity from the chip into user space | ||
| 85 | * @dd: the infinipath device | ||
| 86 | * @uaddr: the location to store the data in user memory | ||
| 87 | * @caddr: the source chip address (full pointer, not offset) | ||
| 88 | * @count: number of bytes to copy (multiple of 32 bits) | ||
| 89 | * | ||
| 90 | * This function also localizes all chip memory accesses. | ||
| 91 | * The copy should be written such that we read full cacheline packets | ||
| 92 | * from the chip. This is usually used for a single qword | ||
| 93 | * | ||
| 94 | * NOTE: This assumes the chip address is 64-bit aligned. | ||
| 95 | */ | ||
| 96 | static int ipath_read_umem64(struct ipath_devdata *dd, void __user *uaddr, | ||
| 97 | const void __iomem *caddr, size_t count) | ||
| 98 | { | ||
| 99 | const u64 __iomem *reg_addr = caddr; | ||
| 100 | const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64)); | ||
| 101 | int ret; | ||
| 102 | |||
| 103 | /* not very efficient, but it works for now */ | ||
| 104 | if (reg_addr < dd->ipath_kregbase || | ||
| 105 | reg_end > dd->ipath_kregend) { | ||
| 106 | ret = -EINVAL; | ||
| 107 | goto bail; | ||
| 108 | } | ||
| 109 | while (reg_addr < reg_end) { | ||
| 110 | u64 data = readq(reg_addr); | ||
| 111 | if (copy_to_user(uaddr, &data, sizeof(u64))) { | ||
| 112 | ret = -EFAULT; | ||
| 113 | goto bail; | ||
| 114 | } | ||
| 115 | reg_addr++; | ||
| 116 | uaddr++; | ||
| 117 | } | ||
| 118 | ret = 0; | ||
| 119 | bail: | ||
| 120 | return ret; | ||
| 121 | } | ||
| 122 | |||
| 123 | /** | ||
| 124 | * ipath_write_umem64 - write a 64-bit quantity to the chip from user space | ||
| 125 | * @dd: the infinipath device | ||
| 126 | * @caddr: the destination chip address (full pointer, not offset) | ||
| 127 | * @uaddr: the source of the data in user memory | ||
| 128 | * @count: the number of bytes to copy (multiple of 32 bits) | ||
| 129 | * | ||
| 130 | * This is usually used for a single qword | ||
| 131 | * NOTE: This assumes the chip address is 64-bit aligned. | ||
| 132 | */ | ||
| 133 | |||
| 134 | static int ipath_write_umem64(struct ipath_devdata *dd, void __iomem *caddr, | ||
| 135 | const void __user *uaddr, size_t count) | ||
| 136 | { | ||
| 137 | u64 __iomem *reg_addr = caddr; | ||
| 138 | const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64)); | ||
| 139 | int ret; | ||
| 140 | |||
| 141 | /* not very efficient, but it works for now */ | ||
| 142 | if (reg_addr < dd->ipath_kregbase || | ||
| 143 | reg_end > dd->ipath_kregend) { | ||
| 144 | ret = -EINVAL; | ||
| 145 | goto bail; | ||
| 146 | } | ||
| 147 | while (reg_addr < reg_end) { | ||
| 148 | u64 data; | ||
| 149 | if (copy_from_user(&data, uaddr, sizeof(data))) { | ||
| 150 | ret = -EFAULT; | ||
| 151 | goto bail; | ||
| 152 | } | ||
| 153 | writeq(data, reg_addr); | ||
| 154 | |||
| 155 | reg_addr++; | ||
| 156 | uaddr++; | ||
| 157 | } | ||
| 158 | ret = 0; | ||
| 159 | bail: | ||
| 160 | return ret; | ||
| 161 | } | ||
| 162 | |||
| 163 | /** | ||
| 164 | * ipath_read_umem32 - read a 32-bit quantity from the chip into user space | ||
| 165 | * @dd: the infinipath device | ||
| 166 | * @uaddr: the location to store the data in user memory | ||
| 167 | * @caddr: the source chip address (full pointer, not offset) | ||
| 168 | * @count: number of bytes to copy | ||
| 169 | * | ||
| 170 | * read 32 bit values, not 64 bit; for memories that only | ||
| 171 | * support 32 bit reads; usually a single dword. | ||
| 172 | */ | ||
| 173 | static int ipath_read_umem32(struct ipath_devdata *dd, void __user *uaddr, | ||
| 174 | const void __iomem *caddr, size_t count) | ||
| 175 | { | ||
| 176 | const u32 __iomem *reg_addr = caddr; | ||
| 177 | const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32)); | ||
| 178 | int ret; | ||
| 179 | |||
| 180 | if (reg_addr < (u32 __iomem *) dd->ipath_kregbase || | ||
| 181 | reg_end > (u32 __iomem *) dd->ipath_kregend) { | ||
| 182 | ret = -EINVAL; | ||
| 183 | goto bail; | ||
| 184 | } | ||
| 185 | /* not very efficient, but it works for now */ | ||
| 186 | while (reg_addr < reg_end) { | ||
| 187 | u32 data = readl(reg_addr); | ||
| 188 | if (copy_to_user(uaddr, &data, sizeof(data))) { | ||
| 189 | ret = -EFAULT; | ||
| 190 | goto bail; | ||
| 191 | } | ||
| 192 | |||
| 193 | reg_addr++; | ||
| 194 | uaddr++; | ||
| 195 | } | ||
| 196 | ret = 0; | ||
| 197 | bail: | ||
| 198 | return ret; | ||
| 199 | } | ||
| 200 | |||
| 201 | /** | ||
| 202 | * ipath_write_umem32 - write a 32-bit quantity to the chip from user space | ||
| 203 | * @dd: the infinipath device | ||
| 204 | * @caddr: the destination chip address (full pointer, not offset) | ||
| 205 | * @uaddr: the source of the data in user memory | ||
| 206 | * @count: number of bytes to copy | ||
| 207 | * | ||
| 208 | * write 32 bit values, not 64 bit; for memories that only | ||
| 209 | * support 32 bit write; usually a single dword. | ||
| 210 | */ | ||
| 211 | |||
| 212 | static int ipath_write_umem32(struct ipath_devdata *dd, void __iomem *caddr, | ||
| 213 | const void __user *uaddr, size_t count) | ||
| 214 | { | ||
| 215 | u32 __iomem *reg_addr = caddr; | ||
| 216 | const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32)); | ||
| 217 | int ret; | ||
| 218 | |||
| 219 | if (reg_addr < (u32 __iomem *) dd->ipath_kregbase || | ||
| 220 | reg_end > (u32 __iomem *) dd->ipath_kregend) { | ||
| 221 | ret = -EINVAL; | ||
| 222 | goto bail; | ||
| 223 | } | ||
| 224 | while (reg_addr < reg_end) { | ||
| 225 | u32 data; | ||
| 226 | if (copy_from_user(&data, uaddr, sizeof(data))) { | ||
| 227 | ret = -EFAULT; | ||
| 228 | goto bail; | ||
| 229 | } | ||
| 230 | writel(data, reg_addr); | ||
| 231 | |||
| 232 | reg_addr++; | ||
| 233 | uaddr++; | ||
| 234 | } | ||
| 235 | ret = 0; | ||
| 236 | bail: | ||
| 237 | return ret; | ||
| 238 | } | ||
| 239 | |||
| 240 | static int ipath_diag_open(struct inode *in, struct file *fp) | ||
| 241 | { | ||
| 242 | struct ipath_devdata *dd; | ||
| 243 | int unit = 0; /* XXX this is bogus */ | ||
| 244 | unsigned long flags; | ||
| 245 | int ret; | ||
| 246 | |||
| 247 | dd = ipath_lookup(unit); | ||
| 248 | |||
| 249 | mutex_lock(&ipath_mutex); | ||
| 250 | spin_lock_irqsave(&ipath_devs_lock, flags); | ||
| 251 | |||
| 252 | if (ipath_diag_inuse) { | ||
| 253 | ret = -EBUSY; | ||
| 254 | goto bail; | ||
| 255 | } | ||
| 256 | |||
| 257 | list_for_each_entry(dd, &ipath_dev_list, ipath_list) { | ||
| 258 | /* | ||
| 259 | * we need at least one infinipath device to be present | ||
| 260 | * (don't use INITTED, because we want to be able to open | ||
| 261 | * even if device is in freeze mode, which cleared INITTED). | ||
| 262 | * There is a small amount of risk to this, which is why we | ||
| 263 | * also verify kregbase is set. | ||
| 264 | */ | ||
| 265 | |||
| 266 | if (!(dd->ipath_flags & IPATH_PRESENT) || | ||
| 267 | !dd->ipath_kregbase) | ||
| 268 | continue; | ||
| 269 | |||
| 270 | ipath_diag_inuse = 1; | ||
| 271 | diag_set_link = 0; | ||
| 272 | ret = 0; | ||
| 273 | goto bail; | ||
| 274 | } | ||
| 275 | |||
| 276 | ret = -ENODEV; | ||
| 277 | |||
| 278 | bail: | ||
| 279 | spin_unlock_irqrestore(&ipath_devs_lock, flags); | ||
| 280 | mutex_unlock(&ipath_mutex); | ||
| 281 | |||
| 282 | /* Only expose a way to reset the device if we | ||
| 283 | make it into diag mode. */ | ||
| 284 | if (ret == 0) | ||
| 285 | ipath_expose_reset(&dd->pcidev->dev); | ||
| 286 | |||
| 287 | return ret; | ||
| 288 | } | ||
| 289 | |||
| 290 | static int ipath_diag_release(struct inode *i, struct file *f) | ||
| 291 | { | ||
| 292 | mutex_lock(&ipath_mutex); | ||
| 293 | ipath_diag_inuse = 0; | ||
| 294 | mutex_unlock(&ipath_mutex); | ||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | |||
| 298 | static ssize_t ipath_diag_read(struct file *fp, char __user *data, | ||
| 299 | size_t count, loff_t *off) | ||
| 300 | { | ||
| 301 | int unit = 0; /* XXX provide for reads on other units some day */ | ||
| 302 | struct ipath_devdata *dd; | ||
| 303 | void __iomem *kreg_base; | ||
| 304 | ssize_t ret; | ||
| 305 | |||
| 306 | dd = ipath_lookup(unit); | ||
| 307 | if (!dd) { | ||
| 308 | ret = -ENODEV; | ||
| 309 | goto bail; | ||
| 310 | } | ||
| 311 | |||
| 312 | kreg_base = dd->ipath_kregbase; | ||
| 313 | |||
| 314 | if (count == 0) | ||
| 315 | ret = 0; | ||
| 316 | else if ((count % 4) || (*off % 4)) | ||
| 317 | /* address or length is not 32-bit aligned, hence invalid */ | ||
| 318 | ret = -EINVAL; | ||
| 319 | else if ((count % 8) || (*off % 8)) | ||
| 320 | /* address or length not 64-bit aligned; do 32-bit reads */ | ||
| 321 | ret = ipath_read_umem32(dd, data, kreg_base + *off, count); | ||
| 322 | else | ||
| 323 | ret = ipath_read_umem64(dd, data, kreg_base + *off, count); | ||
| 324 | |||
| 325 | if (ret >= 0) { | ||
| 326 | *off += count; | ||
| 327 | ret = count; | ||
| 328 | } | ||
| 329 | |||
| 330 | bail: | ||
| 331 | return ret; | ||
| 332 | } | ||
| 333 | |||
| 334 | static ssize_t ipath_diag_write(struct file *fp, const char __user *data, | ||
| 335 | size_t count, loff_t *off) | ||
| 336 | { | ||
| 337 | int unit = 0; /* XXX this is bogus */ | ||
| 338 | struct ipath_devdata *dd; | ||
| 339 | void __iomem *kreg_base; | ||
| 340 | ssize_t ret; | ||
| 341 | |||
| 342 | dd = ipath_lookup(unit); | ||
| 343 | if (!dd) { | ||
| 344 | ret = -ENODEV; | ||
| 345 | goto bail; | ||
| 346 | } | ||
| 347 | kreg_base = dd->ipath_kregbase; | ||
| 348 | |||
| 349 | if (count == 0) | ||
| 350 | ret = 0; | ||
| 351 | else if ((count % 4) || (*off % 4)) | ||
| 352 | /* address or length is not 32-bit aligned, hence invalid */ | ||
| 353 | ret = -EINVAL; | ||
| 354 | else if ((count % 8) || (*off % 8)) | ||
| 355 | /* address or length not 64-bit aligned; do 32-bit writes */ | ||
| 356 | ret = ipath_write_umem32(dd, kreg_base + *off, data, count); | ||
| 357 | else | ||
| 358 | ret = ipath_write_umem64(dd, kreg_base + *off, data, count); | ||
| 359 | |||
| 360 | if (ret >= 0) { | ||
| 361 | *off += count; | ||
| 362 | ret = count; | ||
| 363 | } | ||
| 364 | |||
| 365 | bail: | ||
| 366 | return ret; | ||
| 367 | } | ||
| 368 | |||
| 369 | void ipath_diag_bringup_link(struct ipath_devdata *dd) | ||
| 370 | { | ||
| 371 | if (diag_set_link || (dd->ipath_flags & IPATH_LINKACTIVE)) | ||
| 372 | return; | ||
| 373 | |||
| 374 | diag_set_link = 1; | ||
| 375 | ipath_cdbg(VERBOSE, "Trying to set to set link active for " | ||
| 376 | "diag pkt\n"); | ||
| 377 | ipath_layer_set_linkstate(dd, IPATH_IB_LINKARM); | ||
| 378 | ipath_layer_set_linkstate(dd, IPATH_IB_LINKACTIVE); | ||
| 379 | } | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c new file mode 100644 index 000000000000..2823ff9c0c62 --- /dev/null +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c | |||
| @@ -0,0 +1,951 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | ||
| 3 | * | ||
| 4 | * This software is available to you under a choice of one of two | ||
| 5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
| 6 | * General Public License (GPL) Version 2, available from the file | ||
| 7 | * COPYING in the main directory of this source tree, or the | ||
| 8 | * OpenIB.org BSD license below: | ||
| 9 | * | ||
| 10 | * Redistribution and use in source and binary forms, with or | ||
| 11 | * without modification, are permitted provided that the following | ||
| 12 | * conditions are met: | ||
| 13 | * | ||
| 14 | * - Redistributions of source code must retain the above | ||
| 15 | * copyright notice, this list of conditions and the following | ||
| 16 | * disclaimer. | ||
| 17 | * | ||
| 18 | * - Redistributions in binary form must reproduce the above | ||
| 19 | * copyright notice, this list of conditions and the following | ||
| 20 | * disclaimer in the documentation and/or other materials | ||
| 21 | * provided with the distribution. | ||
| 22 | * | ||
| 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
| 27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 30 | * SOFTWARE. | ||
| 31 | */ | ||
| 32 | |||
| 33 | #include <linux/pci.h> | ||
| 34 | #include <linux/netdevice.h> | ||
| 35 | #include <linux/vmalloc.h> | ||
| 36 | |||
| 37 | #include "ipath_kernel.h" | ||
| 38 | #include "ips_common.h" | ||
| 39 | |||
| 40 | /* | ||
| 41 | * min buffers we want to have per port, after driver | ||
| 42 | */ | ||
| 43 | #define IPATH_MIN_USER_PORT_BUFCNT 8 | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Number of ports we are configured to use (to allow for more pio | ||
| 47 | * buffers per port, etc.) Zero means use chip value. | ||
| 48 | */ | ||
| 49 | static ushort ipath_cfgports; | ||
| 50 | |||
| 51 | module_param_named(cfgports, ipath_cfgports, ushort, S_IRUGO); | ||
| 52 | MODULE_PARM_DESC(cfgports, "Set max number of ports to use"); | ||
| 53 | |||
| 54 | /* | ||
| 55 | * Number of buffers reserved for driver (layered drivers and SMA | ||
| 56 | * send). Reserved at end of buffer list. | ||
| 57 | */ | ||
| 58 | static ushort ipath_kpiobufs = 32; | ||
| 59 | |||
| 60 | static int ipath_set_kpiobufs(const char *val, struct kernel_param *kp); | ||
| 61 | |||
| 62 | module_param_call(kpiobufs, ipath_set_kpiobufs, param_get_uint, | ||
| 63 | &ipath_kpiobufs, S_IWUSR | S_IRUGO); | ||
| 64 | MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver"); | ||
| 65 | |||
| 66 | /** | ||
| 67 | * create_port0_egr - allocate the eager TID buffers | ||
| 68 | * @dd: the infinipath device | ||
| 69 | * | ||
| 70 | * This code is now quite different for user and kernel, because | ||
| 71 | * the kernel uses skb's, for the accelerated network performance. | ||
| 72 | * This is the kernel (port0) version. | ||
| 73 | * | ||
| 74 | * Allocate the eager TID buffers and program them into infinipath. | ||
| 75 | * We use the network layer alloc_skb() allocator to allocate the | ||
| 76 | * memory, and either use the buffers as is for things like SMA | ||
| 77 | * packets, or pass the buffers up to the ipath layered driver and | ||
| 78 | * thence the network layer, replacing them as we do so (see | ||
| 79 | * ipath_rcv_layer()). | ||
| 80 | */ | ||
| 81 | static int create_port0_egr(struct ipath_devdata *dd) | ||
| 82 | { | ||
| 83 | unsigned e, egrcnt; | ||
| 84 | struct sk_buff **skbs; | ||
| 85 | int ret; | ||
| 86 | |||
| 87 | egrcnt = dd->ipath_rcvegrcnt; | ||
| 88 | |||
| 89 | skbs = vmalloc(sizeof(*dd->ipath_port0_skbs) * egrcnt); | ||
| 90 | if (skbs == NULL) { | ||
| 91 | ipath_dev_err(dd, "allocation error for eager TID " | ||
| 92 | "skb array\n"); | ||
| 93 | ret = -ENOMEM; | ||
| 94 | goto bail; | ||
| 95 | } | ||
| 96 | for (e = 0; e < egrcnt; e++) { | ||
| 97 | /* | ||
| 98 | * This is a bit tricky in that we allocate extra | ||
| 99 | * space for 2 bytes of the 14 byte ethernet header. | ||
| 100 | * These two bytes are passed in the ipath header so | ||
| 101 | * the rest of the data is word aligned. We allocate | ||
| 102 | * 4 bytes so that the data buffer stays word aligned. | ||
| 103 | * See ipath_kreceive() for more details. | ||
| 104 | */ | ||
| 105 | skbs[e] = ipath_alloc_skb(dd, GFP_KERNEL); | ||
| 106 | if (!skbs[e]) { | ||
| 107 | ipath_dev_err(dd, "SKB allocation error for " | ||
| 108 | "eager TID %u\n", e); | ||
| 109 | while (e != 0) | ||
| 110 | dev_kfree_skb(skbs[--e]); | ||
| 111 | ret = -ENOMEM; | ||
| 112 | goto bail; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | /* | ||
| 116 | * After loop above, so we can test non-NULL to see if ready | ||
| 117 | * to use at receive, etc. | ||
| 118 | */ | ||
| 119 | dd->ipath_port0_skbs = skbs; | ||
| 120 | |||
| 121 | for (e = 0; e < egrcnt; e++) { | ||
| 122 | unsigned long phys = | ||
| 123 | virt_to_phys(dd->ipath_port0_skbs[e]->data); | ||
| 124 | dd->ipath_f_put_tid(dd, e + (u64 __iomem *) | ||
| 125 | ((char __iomem *) dd->ipath_kregbase + | ||
| 126 | dd->ipath_rcvegrbase), 0, phys); | ||
| 127 | } | ||
| 128 | |||
| 129 | ret = 0; | ||
| 130 | |||
| 131 | bail: | ||
| 132 | return ret; | ||
| 133 | } | ||
| 134 | |||
| 135 | static int bringup_link(struct ipath_devdata *dd) | ||
| 136 | { | ||
| 137 | u64 val, ibc; | ||
| 138 | int ret = 0; | ||
| 139 | |||
| 140 | /* hold IBC in reset */ | ||
| 141 | dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; | ||
| 142 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, | ||
| 143 | dd->ipath_control); | ||
| 144 | |||
| 145 | /* | ||
| 146 | * Note that prior to try 14 or 15 of IB, the credit scaling | ||
| 147 | * wasn't working, because it was swapped for writes with the | ||
| 148 | * 1 bit default linkstate field | ||
| 149 | */ | ||
| 150 | |||
| 151 | /* ignore pbc and align word */ | ||
| 152 | val = dd->ipath_piosize2k - 2 * sizeof(u32); | ||
| 153 | /* | ||
| 154 | * for ICRC, which we only send in diag test pkt mode, and we | ||
| 155 | * don't need to worry about that for mtu | ||
| 156 | */ | ||
| 157 | val += 1; | ||
| 158 | /* | ||
| 159 | * Set the IBC maxpktlength to the size of our pio buffers the | ||
| 160 | * maxpktlength is in words. This is *not* the IB data MTU. | ||
| 161 | */ | ||
| 162 | ibc = (val / sizeof(u32)) << INFINIPATH_IBCC_MAXPKTLEN_SHIFT; | ||
| 163 | /* in KB */ | ||
| 164 | ibc |= 0x5ULL << INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT; | ||
| 165 | /* | ||
| 166 | * How often flowctrl sent. More or less in usecs; balance against | ||
| 167 | * watermark value, so that in theory senders always get a flow | ||
| 168 | * control update in time to not let the IB link go idle. | ||
| 169 | */ | ||
| 170 | ibc |= 0x3ULL << INFINIPATH_IBCC_FLOWCTRLPERIOD_SHIFT; | ||
| 171 | /* max error tolerance */ | ||
| 172 | ibc |= 0xfULL << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT; | ||
| 173 | /* use "real" buffer space for */ | ||
| 174 | ibc |= 4ULL << INFINIPATH_IBCC_CREDITSCALE_SHIFT; | ||
| 175 | /* IB credit flow control. */ | ||
| 176 | ibc |= 0xfULL << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT; | ||
| 177 | /* initially come up waiting for TS1, without sending anything. */ | ||
| 178 | dd->ipath_ibcctrl = ibc; | ||
| 179 | /* | ||
| 180 | * Want to start out with both LINKCMD and LINKINITCMD in NOP | ||
| 181 | * (0 and 0). Don't put linkinitcmd in ipath_ibcctrl, want that | ||
| 182 | * to stay a NOP | ||
| 183 | */ | ||
| 184 | ibc |= INFINIPATH_IBCC_LINKINITCMD_DISABLE << | ||
| 185 | INFINIPATH_IBCC_LINKINITCMD_SHIFT; | ||
| 186 | ipath_cdbg(VERBOSE, "Writing 0x%llx to ibcctrl\n", | ||
| 187 | (unsigned long long) ibc); | ||
| 188 | ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, ibc); | ||
| 189 | |||
| 190 | // be sure chip saw it | ||
| 191 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch); | ||
| 192 | |||
| 193 | ret = dd->ipath_f_bringup_serdes(dd); | ||
| 194 | |||
| 195 | if (ret) | ||
| 196 | dev_info(&dd->pcidev->dev, "Could not initialize SerDes, " | ||
| 197 | "not usable\n"); | ||
| 198 | else { | ||
| 199 | /* enable IBC */ | ||
| 200 | dd->ipath_control |= INFINIPATH_C_LINKENABLE; | ||
| 201 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, | ||
| 202 | dd->ipath_control); | ||
| 203 | } | ||
| 204 | |||
| 205 | return ret; | ||
| 206 | } | ||
| 207 | |||
| 208 | static int init_chip_first(struct ipath_devdata *dd, | ||
| 209 | struct ipath_portdata **pdp) | ||
| 210 | { | ||
| 211 | struct ipath_portdata *pd = NULL; | ||
| 212 | int ret = 0; | ||
| 213 | u64 val; | ||
| 214 | |||
| 215 | /* | ||
| 216 | * skip cfgports stuff because we are not allocating memory, | ||
| 217 | * and we don't want problems if the portcnt changed due to | ||
| 218 | * cfgports. We do still check and report a difference, if | ||
| 219 | * not same (should be impossible). | ||
| 220 | */ | ||
| 221 | dd->ipath_portcnt = | ||
| 222 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt); | ||
| 223 | if (!ipath_cfgports) | ||
| 224 | dd->ipath_cfgports = dd->ipath_portcnt; | ||
| 225 | else if (ipath_cfgports <= dd->ipath_portcnt) { | ||
| 226 | dd->ipath_cfgports = ipath_cfgports; | ||
| 227 | ipath_dbg("Configured to use %u ports out of %u in chip\n", | ||
| 228 | dd->ipath_cfgports, dd->ipath_portcnt); | ||
| 229 | } else { | ||
| 230 | dd->ipath_cfgports = dd->ipath_portcnt; | ||
| 231 | ipath_dbg("Tried to configured to use %u ports; chip " | ||
| 232 | "only supports %u\n", ipath_cfgports, | ||
| 233 | dd->ipath_portcnt); | ||
| 234 | } | ||
| 235 | dd->ipath_pd = kzalloc(sizeof(*dd->ipath_pd) * dd->ipath_cfgports, | ||
| 236 | GFP_KERNEL); | ||
| 237 | |||
| 238 | if (!dd->ipath_pd) { | ||
| 239 | ipath_dev_err(dd, "Unable to allocate portdata array, " | ||
| 240 | "failing\n"); | ||
| 241 | ret = -ENOMEM; | ||
| 242 | goto done; | ||
| 243 | } | ||
| 244 | |||
| 245 | dd->ipath_lastegrheads = kzalloc(sizeof(*dd->ipath_lastegrheads) | ||
| 246 | * dd->ipath_cfgports, | ||
| 247 | GFP_KERNEL); | ||
| 248 | dd->ipath_lastrcvhdrqtails = | ||
| 249 | kzalloc(sizeof(*dd->ipath_lastrcvhdrqtails) | ||
| 250 | * dd->ipath_cfgports, GFP_KERNEL); | ||
| 251 | |||
| 252 | if (!dd->ipath_lastegrheads || !dd->ipath_lastrcvhdrqtails) { | ||
| 253 | ipath_dev_err(dd, "Unable to allocate head arrays, " | ||
| 254 | "failing\n"); | ||
| 255 | ret = -ENOMEM; | ||
| 256 | goto done; | ||
| 257 | } | ||
| 258 | |||
| 259 | dd->ipath_pd[0] = kzalloc(sizeof(*pd), GFP_KERNEL); | ||
| 260 | |||
| 261 | if (!dd->ipath_pd[0]) { | ||
| 262 | ipath_dev_err(dd, "Unable to allocate portdata for port " | ||
| 263 | "0, failing\n"); | ||
| 264 | ret = -ENOMEM; | ||
| 265 | goto done; | ||
| 266 | } | ||
| 267 | pd = dd->ipath_pd[0]; | ||
| 268 | pd->port_dd = dd; | ||
| 269 | pd->port_port = 0; | ||
| 270 | pd->port_cnt = 1; | ||
| 271 | /* The port 0 pkey table is used by the layer interface. */ | ||
| 272 | pd->port_pkeys[0] = IPS_DEFAULT_P_KEY; | ||
| 273 | dd->ipath_rcvtidcnt = | ||
| 274 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt); | ||
| 275 | dd->ipath_rcvtidbase = | ||
| 276 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidbase); | ||
| 277 | dd->ipath_rcvegrcnt = | ||
| 278 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt); | ||
| 279 | dd->ipath_rcvegrbase = | ||
| 280 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrbase); | ||
| 281 | dd->ipath_palign = | ||
| 282 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign); | ||
| 283 | dd->ipath_piobufbase = | ||
| 284 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufbase); | ||
| 285 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiosize); | ||
| 286 | dd->ipath_piosize2k = val & ~0U; | ||
| 287 | dd->ipath_piosize4k = val >> 32; | ||
| 288 | dd->ipath_ibmtu = 4096; /* default to largest legal MTU */ | ||
| 289 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufcnt); | ||
| 290 | dd->ipath_piobcnt2k = val & ~0U; | ||
| 291 | dd->ipath_piobcnt4k = val >> 32; | ||
| 292 | dd->ipath_pio2kbase = | ||
| 293 | (u32 __iomem *) (((char __iomem *) dd->ipath_kregbase) + | ||
| 294 | (dd->ipath_piobufbase & 0xffffffff)); | ||
| 295 | if (dd->ipath_piobcnt4k) { | ||
| 296 | dd->ipath_pio4kbase = (u32 __iomem *) | ||
| 297 | (((char __iomem *) dd->ipath_kregbase) + | ||
| 298 | (dd->ipath_piobufbase >> 32)); | ||
| 299 | /* | ||
| 300 | * 4K buffers take 2 pages; we use roundup just to be | ||
| 301 | * paranoid; we calculate it once here, rather than on | ||
| 302 | * ever buf allocate | ||
| 303 | */ | ||
| 304 | dd->ipath_4kalign = ALIGN(dd->ipath_piosize4k, | ||
| 305 | dd->ipath_palign); | ||
| 306 | ipath_dbg("%u 2k(%x) piobufs @ %p, %u 4k(%x) @ %p " | ||
| 307 | "(%x aligned)\n", | ||
| 308 | dd->ipath_piobcnt2k, dd->ipath_piosize2k, | ||
| 309 | dd->ipath_pio2kbase, dd->ipath_piobcnt4k, | ||
| 310 | dd->ipath_piosize4k, dd->ipath_pio4kbase, | ||
| 311 | dd->ipath_4kalign); | ||
| 312 | } | ||
| 313 | else ipath_dbg("%u 2k piobufs @ %p\n", | ||
| 314 | dd->ipath_piobcnt2k, dd->ipath_pio2kbase); | ||
| 315 | |||
| 316 | spin_lock_init(&dd->ipath_tid_lock); | ||
| 317 | |||
| 318 | done: | ||
| 319 | *pdp = pd; | ||
| 320 | return ret; | ||
| 321 | } | ||
| 322 | |||
| 323 | /** | ||
| 324 | * init_chip_reset - re-initialize after a reset, or enable | ||
| 325 | * @dd: the infinipath device | ||
| 326 | * @pdp: output for port data | ||
| 327 | * | ||
| 328 | * sanity check at least some of the values after reset, and | ||
| 329 | * ensure no receive or transmit (explictly, in case reset | ||
| 330 | * failed | ||
| 331 | */ | ||
| 332 | static int init_chip_reset(struct ipath_devdata *dd, | ||
| 333 | struct ipath_portdata **pdp) | ||
| 334 | { | ||
| 335 | struct ipath_portdata *pd; | ||
| 336 | u32 rtmp; | ||
| 337 | |||
| 338 | *pdp = pd = dd->ipath_pd[0]; | ||
| 339 | /* ensure chip does no sends or receives while we re-initialize */ | ||
| 340 | dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U; | ||
| 341 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 0); | ||
| 342 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0); | ||
| 343 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0); | ||
| 344 | |||
| 345 | rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt); | ||
| 346 | if (dd->ipath_portcnt != rtmp) | ||
| 347 | dev_info(&dd->pcidev->dev, "portcnt was %u before " | ||
| 348 | "reset, now %u, using original\n", | ||
| 349 | dd->ipath_portcnt, rtmp); | ||
| 350 | rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt); | ||
| 351 | if (rtmp != dd->ipath_rcvtidcnt) | ||
| 352 | dev_info(&dd->pcidev->dev, "tidcnt was %u before " | ||
| 353 | "reset, now %u, using original\n", | ||
| 354 | dd->ipath_rcvtidcnt, rtmp); | ||
| 355 | rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidbase); | ||
| 356 | if (rtmp != dd->ipath_rcvtidbase) | ||
| 357 | dev_info(&dd->pcidev->dev, "tidbase was %u before " | ||
| 358 | "reset, now %u, using original\n", | ||
| 359 | dd->ipath_rcvtidbase, rtmp); | ||
| 360 | rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt); | ||
| 361 | if (rtmp != dd->ipath_rcvegrcnt) | ||
| 362 | dev_info(&dd->pcidev->dev, "egrcnt was %u before " | ||
| 363 | "reset, now %u, using original\n", | ||
| 364 | dd->ipath_rcvegrcnt, rtmp); | ||
| 365 | rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrbase); | ||
| 366 | if (rtmp != dd->ipath_rcvegrbase) | ||
| 367 | dev_info(&dd->pcidev->dev, "egrbase was %u before " | ||
| 368 | "reset, now %u, using original\n", | ||
| 369 | dd->ipath_rcvegrbase, rtmp); | ||
| 370 | |||
| 371 | return 0; | ||
| 372 | } | ||
| 373 | |||
| 374 | static int init_pioavailregs(struct ipath_devdata *dd) | ||
| 375 | { | ||
| 376 | int ret; | ||
| 377 | |||
| 378 | dd->ipath_pioavailregs_dma = dma_alloc_coherent( | ||
| 379 | &dd->pcidev->dev, PAGE_SIZE, &dd->ipath_pioavailregs_phys, | ||
| 380 | GFP_KERNEL); | ||
| 381 | if (!dd->ipath_pioavailregs_dma) { | ||
| 382 | ipath_dev_err(dd, "failed to allocate PIOavail reg area " | ||
| 383 | "in memory\n"); | ||
| 384 | ret = -ENOMEM; | ||
| 385 | goto done; | ||
| 386 | } | ||
| 387 | |||
| 388 | /* | ||
| 389 | * we really want L2 cache aligned, but for current CPUs of | ||
| 390 | * interest, they are the same. | ||
| 391 | */ | ||
| 392 | dd->ipath_statusp = (u64 *) | ||
| 393 | ((char *)dd->ipath_pioavailregs_dma + | ||
| 394 | ((2 * L1_CACHE_BYTES + | ||
| 395 | dd->ipath_pioavregs * sizeof(u64)) & ~L1_CACHE_BYTES)); | ||
| 396 | /* copy the current value now that it's really allocated */ | ||
| 397 | *dd->ipath_statusp = dd->_ipath_status; | ||
| 398 | /* | ||
| 399 | * setup buffer to hold freeze msg, accessible to apps, | ||
| 400 | * following statusp | ||
| 401 | */ | ||
| 402 | dd->ipath_freezemsg = (char *)&dd->ipath_statusp[1]; | ||
| 403 | /* and its length */ | ||
| 404 | dd->ipath_freezelen = L1_CACHE_BYTES - sizeof(dd->ipath_statusp[0]); | ||
| 405 | |||
| 406 | if (dd->ipath_unit * 64 > (IPATH_PORT0_RCVHDRTAIL_SIZE - 64)) { | ||
| 407 | ipath_dev_err(dd, "unit %u too large for port 0 " | ||
| 408 | "rcvhdrtail buffer size\n", dd->ipath_unit); | ||
| 409 | ret = -ENODEV; | ||
| 410 | } | ||
| 411 | else | ||
| 412 | ret = 0; | ||
| 413 | |||
| 414 | /* so we can get current tail in ipath_kreceive(), per chip */ | ||
| 415 | dd->ipath_hdrqtailptr = &ipath_port0_rcvhdrtail[ | ||
| 416 | dd->ipath_unit * (64 / sizeof(*ipath_port0_rcvhdrtail))]; | ||
| 417 | done: | ||
| 418 | return ret; | ||
| 419 | } | ||
| 420 | |||
| 421 | /** | ||
| 422 | * init_shadow_tids - allocate the shadow TID array | ||
| 423 | * @dd: the infinipath device | ||
| 424 | * | ||
| 425 | * allocate the shadow TID array, so we can ipath_munlock previous | ||
| 426 | * entries. It may make more sense to move the pageshadow to the | ||
| 427 | * port data structure, so we only allocate memory for ports actually | ||
| 428 | * in use, since we at 8k per port, now. | ||
| 429 | */ | ||
| 430 | static void init_shadow_tids(struct ipath_devdata *dd) | ||
| 431 | { | ||
| 432 | dd->ipath_pageshadow = (struct page **) | ||
| 433 | vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt * | ||
| 434 | sizeof(struct page *)); | ||
| 435 | if (!dd->ipath_pageshadow) | ||
| 436 | ipath_dev_err(dd, "failed to allocate shadow page * " | ||
| 437 | "array, no expected sends!\n"); | ||
| 438 | else | ||
| 439 | memset(dd->ipath_pageshadow, 0, | ||
| 440 | dd->ipath_cfgports * dd->ipath_rcvtidcnt * | ||
| 441 | sizeof(struct page *)); | ||
| 442 | } | ||
| 443 | |||
| 444 | static void enable_chip(struct ipath_devdata *dd, | ||
| 445 | struct ipath_portdata *pd, int reinit) | ||
| 446 | { | ||
| 447 | u32 val; | ||
| 448 | int i; | ||
| 449 | |||
| 450 | if (!reinit) { | ||
| 451 | init_waitqueue_head(&ipath_sma_state_wait); | ||
| 452 | } | ||
| 453 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | ||
| 454 | dd->ipath_rcvctrl); | ||
| 455 | |||
| 456 | /* Enable PIO send, and update of PIOavail regs to memory. */ | ||
| 457 | dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE | | ||
| 458 | INFINIPATH_S_PIOBUFAVAILUPD; | ||
| 459 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | ||
| 460 | dd->ipath_sendctrl); | ||
| 461 | |||
| 462 | /* | ||
| 463 | * enable port 0 receive, and receive interrupt. other ports | ||
| 464 | * done as user opens and inits them. | ||
| 465 | */ | ||
| 466 | dd->ipath_rcvctrl = INFINIPATH_R_TAILUPD | | ||
| 467 | (1ULL << INFINIPATH_R_PORTENABLE_SHIFT) | | ||
| 468 | (1ULL << INFINIPATH_R_INTRAVAIL_SHIFT); | ||
| 469 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | ||
| 470 | dd->ipath_rcvctrl); | ||
| 471 | |||
| 472 | /* | ||
| 473 | * now ready for use. this should be cleared whenever we | ||
| 474 | * detect a reset, or initiate one. | ||
| 475 | */ | ||
| 476 | dd->ipath_flags |= IPATH_INITTED; | ||
| 477 | |||
| 478 | /* | ||
| 479 | * init our shadow copies of head from tail values, and write | ||
| 480 | * head values to match. | ||
| 481 | */ | ||
| 482 | val = ipath_read_ureg32(dd, ur_rcvegrindextail, 0); | ||
| 483 | (void)ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0); | ||
| 484 | dd->ipath_port0head = ipath_read_ureg32(dd, ur_rcvhdrtail, 0); | ||
| 485 | |||
| 486 | /* Initialize so we interrupt on next packet received */ | ||
| 487 | (void)ipath_write_ureg(dd, ur_rcvhdrhead, | ||
| 488 | dd->ipath_rhdrhead_intr_off | | ||
| 489 | dd->ipath_port0head, 0); | ||
| 490 | |||
| 491 | /* | ||
| 492 | * by now pioavail updates to memory should have occurred, so | ||
| 493 | * copy them into our working/shadow registers; this is in | ||
| 494 | * case something went wrong with abort, but mostly to get the | ||
| 495 | * initial values of the generation bit correct. | ||
| 496 | */ | ||
| 497 | for (i = 0; i < dd->ipath_pioavregs; i++) { | ||
| 498 | __le64 val; | ||
| 499 | |||
| 500 | /* | ||
| 501 | * Chip Errata bug 6641; even and odd qwords>3 are swapped. | ||
| 502 | */ | ||
| 503 | if (i > 3) { | ||
| 504 | if (i & 1) | ||
| 505 | val = dd->ipath_pioavailregs_dma[i - 1]; | ||
| 506 | else | ||
| 507 | val = dd->ipath_pioavailregs_dma[i + 1]; | ||
| 508 | } | ||
| 509 | else | ||
| 510 | val = dd->ipath_pioavailregs_dma[i]; | ||
| 511 | dd->ipath_pioavailshadow[i] = le64_to_cpu(val); | ||
| 512 | } | ||
| 513 | /* can get counters, stats, etc. */ | ||
| 514 | dd->ipath_flags |= IPATH_PRESENT; | ||
| 515 | } | ||
| 516 | |||
| 517 | static int init_housekeeping(struct ipath_devdata *dd, | ||
| 518 | struct ipath_portdata **pdp, int reinit) | ||
| 519 | { | ||
| 520 | char boardn[32]; | ||
| 521 | int ret = 0; | ||
| 522 | |||
| 523 | /* | ||
| 524 | * have to clear shadow copies of registers at init that are | ||
| 525 | * not otherwise set here, or all kinds of bizarre things | ||
| 526 | * happen with driver on chip reset | ||
| 527 | */ | ||
| 528 | dd->ipath_rcvhdrsize = 0; | ||
| 529 | |||
| 530 | /* | ||
| 531 | * Don't clear ipath_flags as 8bit mode was set before | ||
| 532 | * entering this func. However, we do set the linkstate to | ||
| 533 | * unknown, so we can watch for a transition. | ||
| 534 | */ | ||
| 535 | dd->ipath_flags |= IPATH_LINKUNK; | ||
| 536 | dd->ipath_flags &= ~(IPATH_LINKACTIVE | IPATH_LINKARMED | | ||
| 537 | IPATH_LINKDOWN | IPATH_LINKINIT); | ||
| 538 | |||
| 539 | ipath_cdbg(VERBOSE, "Try to read spc chip revision\n"); | ||
| 540 | dd->ipath_revision = | ||
| 541 | ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision); | ||
| 542 | |||
| 543 | /* | ||
| 544 | * set up fundamental info we need to use the chip; we assume | ||
| 545 | * if the revision reg and these regs are OK, we don't need to | ||
| 546 | * special case the rest | ||
| 547 | */ | ||
| 548 | dd->ipath_sregbase = | ||
| 549 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_sendregbase); | ||
| 550 | dd->ipath_cregbase = | ||
| 551 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_counterregbase); | ||
| 552 | dd->ipath_uregbase = | ||
| 553 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_userregbase); | ||
| 554 | ipath_cdbg(VERBOSE, "ipath_kregbase %p, sendbase %x usrbase %x, " | ||
| 555 | "cntrbase %x\n", dd->ipath_kregbase, dd->ipath_sregbase, | ||
| 556 | dd->ipath_uregbase, dd->ipath_cregbase); | ||
| 557 | if ((dd->ipath_revision & 0xffffffff) == 0xffffffff | ||
| 558 | || (dd->ipath_sregbase & 0xffffffff) == 0xffffffff | ||
| 559 | || (dd->ipath_cregbase & 0xffffffff) == 0xffffffff | ||
| 560 | || (dd->ipath_uregbase & 0xffffffff) == 0xffffffff) { | ||
| 561 | ipath_dev_err(dd, "Register read failures from chip, " | ||
| 562 | "giving up initialization\n"); | ||
| 563 | ret = -ENODEV; | ||
| 564 | goto done; | ||
| 565 | } | ||
| 566 | |||
| 567 | /* clear the initial reset flag, in case first driver load */ | ||
| 568 | ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, | ||
| 569 | INFINIPATH_E_RESET); | ||
| 570 | |||
| 571 | if (reinit) | ||
| 572 | ret = init_chip_reset(dd, pdp); | ||
| 573 | else | ||
| 574 | ret = init_chip_first(dd, pdp); | ||
| 575 | |||
| 576 | if (ret) | ||
| 577 | goto done; | ||
| 578 | |||
| 579 | ipath_cdbg(VERBOSE, "Revision %llx (PCI %x), %u ports, %u tids, " | ||
| 580 | "%u egrtids\n", (unsigned long long) dd->ipath_revision, | ||
| 581 | dd->ipath_pcirev, dd->ipath_portcnt, dd->ipath_rcvtidcnt, | ||
| 582 | dd->ipath_rcvegrcnt); | ||
| 583 | |||
| 584 | if (((dd->ipath_revision >> INFINIPATH_R_SOFTWARE_SHIFT) & | ||
| 585 | INFINIPATH_R_SOFTWARE_MASK) != IPATH_CHIP_SWVERSION) { | ||
| 586 | ipath_dev_err(dd, "Driver only handles version %d, " | ||
| 587 | "chip swversion is %d (%llx), failng\n", | ||
| 588 | IPATH_CHIP_SWVERSION, | ||
| 589 | (int)(dd->ipath_revision >> | ||
| 590 | INFINIPATH_R_SOFTWARE_SHIFT) & | ||
| 591 | INFINIPATH_R_SOFTWARE_MASK, | ||
| 592 | (unsigned long long) dd->ipath_revision); | ||
| 593 | ret = -ENOSYS; | ||
| 594 | goto done; | ||
| 595 | } | ||
| 596 | dd->ipath_majrev = (u8) ((dd->ipath_revision >> | ||
| 597 | INFINIPATH_R_CHIPREVMAJOR_SHIFT) & | ||
| 598 | INFINIPATH_R_CHIPREVMAJOR_MASK); | ||
| 599 | dd->ipath_minrev = (u8) ((dd->ipath_revision >> | ||
| 600 | INFINIPATH_R_CHIPREVMINOR_SHIFT) & | ||
| 601 | INFINIPATH_R_CHIPREVMINOR_MASK); | ||
| 602 | dd->ipath_boardrev = (u8) ((dd->ipath_revision >> | ||
| 603 | INFINIPATH_R_BOARDID_SHIFT) & | ||
| 604 | INFINIPATH_R_BOARDID_MASK); | ||
| 605 | |||
| 606 | ret = dd->ipath_f_get_boardname(dd, boardn, sizeof boardn); | ||
| 607 | |||
| 608 | snprintf(dd->ipath_boardversion, sizeof(dd->ipath_boardversion), | ||
| 609 | "Driver %u.%u, %s, InfiniPath%u %u.%u, PCI %u, " | ||
| 610 | "SW Compat %u\n", | ||
| 611 | IPATH_CHIP_VERS_MAJ, IPATH_CHIP_VERS_MIN, boardn, | ||
| 612 | (unsigned)(dd->ipath_revision >> INFINIPATH_R_ARCH_SHIFT) & | ||
| 613 | INFINIPATH_R_ARCH_MASK, | ||
| 614 | dd->ipath_majrev, dd->ipath_minrev, dd->ipath_pcirev, | ||
| 615 | (unsigned)(dd->ipath_revision >> | ||
| 616 | INFINIPATH_R_SOFTWARE_SHIFT) & | ||
| 617 | INFINIPATH_R_SOFTWARE_MASK); | ||
| 618 | |||
| 619 | ipath_dbg("%s", dd->ipath_boardversion); | ||
| 620 | |||
| 621 | done: | ||
| 622 | return ret; | ||
| 623 | } | ||
| 624 | |||
| 625 | |||
| 626 | /** | ||
| 627 | * ipath_init_chip - do the actual initialization sequence on the chip | ||
| 628 | * @dd: the infinipath device | ||
| 629 | * @reinit: reinitializing, so don't allocate new memory | ||
| 630 | * | ||
| 631 | * Do the actual initialization sequence on the chip. This is done | ||
| 632 | * both from the init routine called from the PCI infrastructure, and | ||
| 633 | * when we reset the chip, or detect that it was reset internally, | ||
| 634 | * or it's administratively re-enabled. | ||
| 635 | * | ||
| 636 | * Memory allocation here and in called routines is only done in | ||
| 637 | * the first case (reinit == 0). We have to be careful, because even | ||
| 638 | * without memory allocation, we need to re-write all the chip registers | ||
| 639 | * TIDs, etc. after the reset or enable has completed. | ||
| 640 | */ | ||
| 641 | int ipath_init_chip(struct ipath_devdata *dd, int reinit) | ||
| 642 | { | ||
| 643 | int ret = 0, i; | ||
| 644 | u32 val32, kpiobufs; | ||
| 645 | u64 val, atmp; | ||
| 646 | struct ipath_portdata *pd = NULL; /* keep gcc4 happy */ | ||
| 647 | |||
| 648 | ret = init_housekeeping(dd, &pd, reinit); | ||
| 649 | if (ret) | ||
| 650 | goto done; | ||
| 651 | |||
| 652 | /* | ||
| 653 | * we ignore most issues after reporting them, but have to specially | ||
| 654 | * handle hardware-disabled chips. | ||
| 655 | */ | ||
| 656 | if (ret == 2) { | ||
| 657 | /* unique error, known to ipath_init_one */ | ||
| 658 | ret = -EPERM; | ||
| 659 | goto done; | ||
| 660 | } | ||
| 661 | |||
| 662 | /* | ||
| 663 | * We could bump this to allow for full rcvegrcnt + rcvtidcnt, | ||
| 664 | * but then it no longer nicely fits power of two, and since | ||
| 665 | * we now use routines that backend onto __get_free_pages, the | ||
| 666 | * rest would be wasted. | ||
| 667 | */ | ||
| 668 | dd->ipath_rcvhdrcnt = dd->ipath_rcvegrcnt; | ||
| 669 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrcnt, | ||
| 670 | dd->ipath_rcvhdrcnt); | ||
| 671 | |||
| 672 | /* | ||
| 673 | * Set up the shadow copies of the piobufavail registers, | ||
| 674 | * which we compare against the chip registers for now, and | ||
| 675 | * the in memory DMA'ed copies of the registers. This has to | ||
| 676 | * be done early, before we calculate lastport, etc. | ||
| 677 | */ | ||
| 678 | val = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k; | ||
| 679 | /* | ||
| 680 | * calc number of pioavail registers, and save it; we have 2 | ||
| 681 | * bits per buffer. | ||
| 682 | */ | ||
| 683 | dd->ipath_pioavregs = ALIGN(val, sizeof(u64) * BITS_PER_BYTE / 2) | ||
| 684 | / (sizeof(u64) * BITS_PER_BYTE / 2); | ||
| 685 | if (!ipath_kpiobufs) /* have to have at least 1, for SMA */ | ||
| 686 | kpiobufs = ipath_kpiobufs = 1; | ||
| 687 | else if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) < | ||
| 688 | (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT)) { | ||
| 689 | dev_info(&dd->pcidev->dev, "Too few PIO buffers (%u) " | ||
| 690 | "for %u ports to have %u each!\n", | ||
| 691 | dd->ipath_piobcnt2k + dd->ipath_piobcnt4k, | ||
| 692 | dd->ipath_cfgports, IPATH_MIN_USER_PORT_BUFCNT); | ||
| 693 | kpiobufs = 1; /* reserve just the minimum for SMA/ether */ | ||
| 694 | } else | ||
| 695 | kpiobufs = ipath_kpiobufs; | ||
| 696 | |||
| 697 | if (kpiobufs > | ||
| 698 | (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - | ||
| 699 | (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT))) { | ||
| 700 | i = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - | ||
| 701 | (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT); | ||
| 702 | if (i < 0) | ||
| 703 | i = 0; | ||
| 704 | dev_info(&dd->pcidev->dev, "Allocating %d PIO bufs for " | ||
| 705 | "kernel leaves too few for %d user ports " | ||
| 706 | "(%d each); using %u\n", kpiobufs, | ||
| 707 | dd->ipath_cfgports - 1, | ||
| 708 | IPATH_MIN_USER_PORT_BUFCNT, i); | ||
| 709 | /* | ||
| 710 | * shouldn't change ipath_kpiobufs, because could be | ||
| 711 | * different for different devices... | ||
| 712 | */ | ||
| 713 | kpiobufs = i; | ||
| 714 | } | ||
| 715 | dd->ipath_lastport_piobuf = | ||
| 716 | dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - kpiobufs; | ||
| 717 | dd->ipath_pbufsport = dd->ipath_cfgports > 1 | ||
| 718 | ? dd->ipath_lastport_piobuf / (dd->ipath_cfgports - 1) | ||
| 719 | : 0; | ||
| 720 | val32 = dd->ipath_lastport_piobuf - | ||
| 721 | (dd->ipath_pbufsport * (dd->ipath_cfgports - 1)); | ||
| 722 | if (val32 > 0) { | ||
| 723 | ipath_dbg("allocating %u pbufs/port leaves %u unused, " | ||
| 724 | "add to kernel\n", dd->ipath_pbufsport, val32); | ||
| 725 | dd->ipath_lastport_piobuf -= val32; | ||
| 726 | ipath_dbg("%u pbufs/port leaves %u unused, add to kernel\n", | ||
| 727 | dd->ipath_pbufsport, val32); | ||
| 728 | } | ||
| 729 | dd->ipath_lastpioindex = dd->ipath_lastport_piobuf; | ||
| 730 | ipath_cdbg(VERBOSE, "%d PIO bufs for kernel out of %d total %u " | ||
| 731 | "each for %u user ports\n", kpiobufs, | ||
| 732 | dd->ipath_piobcnt2k + dd->ipath_piobcnt4k, | ||
| 733 | dd->ipath_pbufsport, dd->ipath_cfgports - 1); | ||
| 734 | |||
| 735 | dd->ipath_f_early_init(dd); | ||
| 736 | |||
| 737 | /* early_init sets rcvhdrentsize and rcvhdrsize, so this must be | ||
| 738 | * done after early_init */ | ||
| 739 | dd->ipath_hdrqlast = | ||
| 740 | dd->ipath_rcvhdrentsize * (dd->ipath_rcvhdrcnt - 1); | ||
| 741 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrentsize, | ||
| 742 | dd->ipath_rcvhdrentsize); | ||
| 743 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrsize, | ||
| 744 | dd->ipath_rcvhdrsize); | ||
| 745 | |||
| 746 | if (!reinit) { | ||
| 747 | ret = init_pioavailregs(dd); | ||
| 748 | init_shadow_tids(dd); | ||
| 749 | if (ret) | ||
| 750 | goto done; | ||
| 751 | } | ||
| 752 | |||
| 753 | (void)ipath_write_kreg(dd, dd->ipath_kregs->kr_sendpioavailaddr, | ||
| 754 | dd->ipath_pioavailregs_phys); | ||
| 755 | /* | ||
| 756 | * this is to detect s/w errors, which the h/w works around by | ||
| 757 | * ignoring the low 6 bits of address, if it wasn't aligned. | ||
| 758 | */ | ||
| 759 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpioavailaddr); | ||
| 760 | if (val != dd->ipath_pioavailregs_phys) { | ||
| 761 | ipath_dev_err(dd, "Catastrophic software error, " | ||
| 762 | "SendPIOAvailAddr written as %lx, " | ||
| 763 | "read back as %llx\n", | ||
| 764 | (unsigned long) dd->ipath_pioavailregs_phys, | ||
| 765 | (unsigned long long) val); | ||
| 766 | ret = -EINVAL; | ||
| 767 | goto done; | ||
| 768 | } | ||
| 769 | |||
| 770 | val = ipath_port0_rcvhdrtail_dma + dd->ipath_unit * 64; | ||
| 771 | |||
| 772 | /* verify that the alignment requirement was met */ | ||
| 773 | ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr, | ||
| 774 | 0, val); | ||
| 775 | atmp = ipath_read_kreg64_port( | ||
| 776 | dd, dd->ipath_kregs->kr_rcvhdrtailaddr, 0); | ||
| 777 | if (val != atmp) { | ||
| 778 | ipath_dev_err(dd, "Catastrophic software error, " | ||
| 779 | "RcvHdrTailAddr0 written as %llx, " | ||
| 780 | "read back as %llx from %x\n", | ||
| 781 | (unsigned long long) val, | ||
| 782 | (unsigned long long) atmp, | ||
| 783 | dd->ipath_kregs->kr_rcvhdrtailaddr); | ||
| 784 | ret = -EINVAL; | ||
| 785 | goto done; | ||
| 786 | } | ||
| 787 | |||
| 788 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvbthqp, IPATH_KD_QP); | ||
| 789 | |||
| 790 | /* | ||
| 791 | * make sure we are not in freeze, and PIO send enabled, so | ||
| 792 | * writes to pbc happen | ||
| 793 | */ | ||
| 794 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, 0ULL); | ||
| 795 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, | ||
| 796 | ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED); | ||
| 797 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL); | ||
| 798 | ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, | ||
| 799 | INFINIPATH_S_PIOENABLE); | ||
| 800 | |||
| 801 | /* | ||
| 802 | * before error clears, since we expect serdes pll errors during | ||
| 803 | * this, the first time after reset | ||
| 804 | */ | ||
| 805 | if (bringup_link(dd)) { | ||
| 806 | dev_info(&dd->pcidev->dev, "Failed to bringup IB link\n"); | ||
| 807 | ret = -ENETDOWN; | ||
| 808 | goto done; | ||
| 809 | } | ||
| 810 | |||
| 811 | /* | ||
| 812 | * clear any "expected" hwerrs from reset and/or initialization | ||
| 813 | * clear any that aren't enabled (at least this once), and then | ||
| 814 | * set the enable mask | ||
| 815 | */ | ||
| 816 | dd->ipath_f_init_hwerrors(dd); | ||
| 817 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, | ||
| 818 | ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED); | ||
| 819 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, | ||
| 820 | dd->ipath_hwerrmask); | ||
| 821 | |||
| 822 | dd->ipath_maskederrs = dd->ipath_ignorederrs; | ||
| 823 | /* clear all */ | ||
| 824 | ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL); | ||
| 825 | /* enable errors that are masked, at least this first time. */ | ||
| 826 | ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, | ||
| 827 | ~dd->ipath_maskederrs); | ||
| 828 | /* clear any interrups up to this point (ints still not enabled) */ | ||
| 829 | ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL); | ||
| 830 | |||
| 831 | ipath_stats.sps_lid[dd->ipath_unit] = dd->ipath_lid; | ||
| 832 | |||
| 833 | /* | ||
| 834 | * Set up the port 0 (kernel) rcvhdr q and egr TIDs. If doing | ||
| 835 | * re-init, the simplest way to handle this is to free | ||
| 836 | * existing, and re-allocate. | ||
| 837 | */ | ||
| 838 | if (reinit) | ||
| 839 | ipath_free_pddata(dd, 0, 0); | ||
| 840 | dd->ipath_f_tidtemplate(dd); | ||
| 841 | ret = ipath_create_rcvhdrq(dd, pd); | ||
| 842 | if (!ret) | ||
| 843 | ret = create_port0_egr(dd); | ||
| 844 | if (ret) | ||
| 845 | ipath_dev_err(dd, "failed to allocate port 0 (kernel) " | ||
| 846 | "rcvhdrq and/or egr bufs\n"); | ||
| 847 | else | ||
| 848 | enable_chip(dd, pd, reinit); | ||
| 849 | |||
| 850 | /* | ||
| 851 | * cause retrigger of pending interrupts ignored during init, | ||
| 852 | * even if we had errors | ||
| 853 | */ | ||
| 854 | ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL); | ||
| 855 | |||
| 856 | if(!dd->ipath_stats_timer_active) { | ||
| 857 | /* | ||
| 858 | * first init, or after an admin disable/enable | ||
| 859 | * set up stats retrieval timer, even if we had errors | ||
| 860 | * in last portion of setup | ||
| 861 | */ | ||
| 862 | init_timer(&dd->ipath_stats_timer); | ||
| 863 | dd->ipath_stats_timer.function = ipath_get_faststats; | ||
| 864 | dd->ipath_stats_timer.data = (unsigned long) dd; | ||
| 865 | /* every 5 seconds; */ | ||
| 866 | dd->ipath_stats_timer.expires = jiffies + 5 * HZ; | ||
| 867 | /* takes ~16 seconds to overflow at full IB 4x bandwdith */ | ||
| 868 | add_timer(&dd->ipath_stats_timer); | ||
| 869 | dd->ipath_stats_timer_active = 1; | ||
| 870 | } | ||
| 871 | |||
| 872 | done: | ||
| 873 | if (!ret) { | ||
| 874 | ipath_get_guid(dd); | ||
| 875 | *dd->ipath_statusp |= IPATH_STATUS_CHIP_PRESENT; | ||
| 876 | if (!dd->ipath_f_intrsetup(dd)) { | ||
| 877 | /* now we can enable all interrupts from the chip */ | ||
| 878 | ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, | ||
| 879 | -1LL); | ||
| 880 | /* force re-interrupt of any pending interrupts. */ | ||
| 881 | ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, | ||
| 882 | 0ULL); | ||
| 883 | /* chip is usable; mark it as initialized */ | ||
| 884 | *dd->ipath_statusp |= IPATH_STATUS_INITTED; | ||
| 885 | } else | ||
| 886 | ipath_dev_err(dd, "No interrupts enabled, couldn't " | ||
| 887 | "setup interrupt address\n"); | ||
| 888 | |||
| 889 | if (dd->ipath_cfgports > ipath_stats.sps_nports) | ||
| 890 | /* | ||
| 891 | * sps_nports is a global, so, we set it to | ||
| 892 | * the highest number of ports of any of the | ||
| 893 | * chips we find; we never decrement it, at | ||
| 894 | * least for now. Since this might have changed | ||
| 895 | * over disable/enable or prior to reset, always | ||
| 896 | * do the check and potentially adjust. | ||
| 897 | */ | ||
| 898 | ipath_stats.sps_nports = dd->ipath_cfgports; | ||
| 899 | } else | ||
| 900 | ipath_dbg("Failed (%d) to initialize chip\n", ret); | ||
| 901 | |||
| 902 | /* if ret is non-zero, we probably should do some cleanup | ||
| 903 | here... */ | ||
| 904 | return ret; | ||
| 905 | } | ||
| 906 | |||
| 907 | static int ipath_set_kpiobufs(const char *str, struct kernel_param *kp) | ||
| 908 | { | ||
| 909 | struct ipath_devdata *dd; | ||
| 910 | unsigned long flags; | ||
| 911 | unsigned short val; | ||
| 912 | int ret; | ||
| 913 | |||
| 914 | ret = ipath_parse_ushort(str, &val); | ||
| 915 | |||
| 916 | spin_lock_irqsave(&ipath_devs_lock, flags); | ||
| 917 | |||
| 918 | if (ret < 0) | ||
| 919 | goto bail; | ||
| 920 | |||
| 921 | if (val == 0) { | ||
| 922 | ret = -EINVAL; | ||
| 923 | goto bail; | ||
| 924 | } | ||
| 925 | |||
| 926 | list_for_each_entry(dd, &ipath_dev_list, ipath_list) { | ||
| 927 | if (dd->ipath_kregbase) | ||
| 928 | continue; | ||
| 929 | if (val > (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - | ||
| 930 | (dd->ipath_cfgports * | ||
| 931 | IPATH_MIN_USER_PORT_BUFCNT))) | ||
| 932 | { | ||
| 933 | ipath_dev_err( | ||
| 934 | dd, | ||
| 935 | "Allocating %d PIO bufs for kernel leaves " | ||
| 936 | "too few for %d user ports (%d each)\n", | ||
| 937 | val, dd->ipath_cfgports - 1, | ||
| 938 | IPATH_MIN_USER_PORT_BUFCNT); | ||
| 939 | ret = -EINVAL; | ||
| 940 | goto bail; | ||
| 941 | } | ||
| 942 | dd->ipath_lastport_piobuf = | ||
| 943 | dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - val; | ||
| 944 | } | ||
| 945 | |||
| 946 | ret = 0; | ||
| 947 | bail: | ||
| 948 | spin_unlock_irqrestore(&ipath_devs_lock, flags); | ||
| 949 | |||
| 950 | return ret; | ||
| 951 | } | ||
