aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBryan O'Sullivan <bos@pathscale.com>2006-07-01 07:35:52 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-01 12:55:58 -0400
commita2acb2ff36876fdfa5f7a8bf811765aadc74c1c1 (patch)
treeea0e6aaacd36cac011dacae3554b6576dea56d9d /drivers
parent6700efdfc06d2dc9ef77988a00182c2ede0f1be0 (diff)
[PATCH] IB/ipath: allow diags on any unit
There is no longer a /dev/ipath_diag file; instead, there's /dev/ipath_diag0, 1, etc. It's still not possible to have diags run on more than one unit at a time, but that's easy to fix at some point. Signed-off-by: Bryan O'Sullivan <bryan.osullivan@qlogic.com> Cc: "Michael S. Tsirkin" <mst@mellanox.co.il> Cc: Roland Dreier <rolandd@cisco.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_diag.c85
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c6
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c28
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h19
-rw-r--r--drivers/infiniband/hw/ipath/ipath_layer.c2
5 files changed, 53 insertions, 87 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index 0fcd507e7c7d..d7f17f2a436c 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -67,18 +67,20 @@ static struct file_operations diag_file_ops = {
67 .release = ipath_diag_release 67 .release = ipath_diag_release
68}; 68};
69 69
70static struct cdev *diag_cdev; 70int ipath_diag_add(struct ipath_devdata *dd)
71static struct class_device *diag_class_dev;
72
73int ipath_diag_init(void)
74{ 71{
75 return ipath_cdev_init(IPATH_DIAG_MINOR, "ipath_diag", 72 char name[16];
76 &diag_file_ops, &diag_cdev, &diag_class_dev); 73
74 snprintf(name, sizeof(name), "ipath_diag%d", dd->ipath_unit);
75
76 return ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name,
77 &diag_file_ops, &dd->diag_cdev,
78 &dd->diag_class_dev);
77} 79}
78 80
79void ipath_diag_cleanup(void) 81void ipath_diag_remove(struct ipath_devdata *dd)
80{ 82{
81 ipath_cdev_cleanup(&diag_cdev, &diag_class_dev); 83 ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_class_dev);
82} 84}
83 85
84/** 86/**
@@ -102,8 +104,7 @@ static int ipath_read_umem64(struct ipath_devdata *dd, void __user *uaddr,
102 int ret; 104 int ret;
103 105
104 /* not very efficient, but it works for now */ 106 /* not very efficient, but it works for now */
105 if (reg_addr < dd->ipath_kregbase || 107 if (reg_addr < dd->ipath_kregbase || reg_end > dd->ipath_kregend) {
106 reg_end > dd->ipath_kregend) {
107 ret = -EINVAL; 108 ret = -EINVAL;
108 goto bail; 109 goto bail;
109 } 110 }
@@ -140,8 +141,7 @@ static int ipath_write_umem64(struct ipath_devdata *dd, void __iomem *caddr,
140 int ret; 141 int ret;
141 142
142 /* not very efficient, but it works for now */ 143 /* not very efficient, but it works for now */
143 if (reg_addr < dd->ipath_kregbase || 144 if (reg_addr < dd->ipath_kregbase || reg_end > dd->ipath_kregend) {
144 reg_end > dd->ipath_kregend) {
145 ret = -EINVAL; 145 ret = -EINVAL;
146 goto bail; 146 goto bail;
147 } 147 }
@@ -240,59 +240,45 @@ bail:
240 240
241static int ipath_diag_open(struct inode *in, struct file *fp) 241static int ipath_diag_open(struct inode *in, struct file *fp)
242{ 242{
243 int unit = iminor(in) - IPATH_DIAG_MINOR_BASE;
243 struct ipath_devdata *dd; 244 struct ipath_devdata *dd;
244 int unit = 0; /* XXX this is bogus */
245 unsigned long flags;
246 int ret; 245 int ret;
247 246
248 dd = ipath_lookup(unit);
249
250 mutex_lock(&ipath_mutex); 247 mutex_lock(&ipath_mutex);
251 spin_lock_irqsave(&ipath_devs_lock, flags);
252 248
253 if (ipath_diag_inuse) { 249 if (ipath_diag_inuse) {
254 ret = -EBUSY; 250 ret = -EBUSY;
255 goto bail; 251 goto bail;
256 } 252 }
257 253
258 list_for_each_entry(dd, &ipath_dev_list, ipath_list) { 254 dd = ipath_lookup(unit);
259 /* 255
260 * we need at least one infinipath device to be present 256 if (dd == NULL || !(dd->ipath_flags & IPATH_PRESENT) ||
261 * (don't use INITTED, because we want to be able to open 257 !dd->ipath_kregbase) {
262 * even if device is in freeze mode, which cleared INITTED). 258 ret = -ENODEV;
263 * There is a small amount of risk to this, which is why we
264 * also verify kregbase is set.
265 */
266
267 if (!(dd->ipath_flags & IPATH_PRESENT) ||
268 !dd->ipath_kregbase)
269 continue;
270
271 ipath_diag_inuse = 1;
272 diag_set_link = 0;
273 ret = 0;
274 goto bail; 259 goto bail;
275 } 260 }
276 261
277 ret = -ENODEV; 262 fp->private_data = dd;
278 263 ipath_diag_inuse = 1;
279bail: 264 diag_set_link = 0;
280 spin_unlock_irqrestore(&ipath_devs_lock, flags); 265 ret = 0;
281 266
282 /* Only expose a way to reset the device if we 267 /* Only expose a way to reset the device if we
283 make it into diag mode. */ 268 make it into diag mode. */
284 if (ret == 0) 269 ipath_expose_reset(&dd->pcidev->dev);
285 ipath_expose_reset(&dd->pcidev->dev);
286 270
271bail:
287 mutex_unlock(&ipath_mutex); 272 mutex_unlock(&ipath_mutex);
288 273
289 return ret; 274 return ret;
290} 275}
291 276
292static int ipath_diag_release(struct inode *i, struct file *f) 277static int ipath_diag_release(struct inode *in, struct file *fp)
293{ 278{
294 mutex_lock(&ipath_mutex); 279 mutex_lock(&ipath_mutex);
295 ipath_diag_inuse = 0; 280 ipath_diag_inuse = 0;
281 fp->private_data = NULL;
296 mutex_unlock(&ipath_mutex); 282 mutex_unlock(&ipath_mutex);
297 return 0; 283 return 0;
298} 284}
@@ -300,17 +286,10 @@ static int ipath_diag_release(struct inode *i, struct file *f)
300static ssize_t ipath_diag_read(struct file *fp, char __user *data, 286static ssize_t ipath_diag_read(struct file *fp, char __user *data,
301 size_t count, loff_t *off) 287 size_t count, loff_t *off)
302{ 288{
303 int unit = 0; /* XXX provide for reads on other units some day */ 289 struct ipath_devdata *dd = fp->private_data;
304 struct ipath_devdata *dd;
305 void __iomem *kreg_base; 290 void __iomem *kreg_base;
306 ssize_t ret; 291 ssize_t ret;
307 292
308 dd = ipath_lookup(unit);
309 if (!dd) {
310 ret = -ENODEV;
311 goto bail;
312 }
313
314 kreg_base = dd->ipath_kregbase; 293 kreg_base = dd->ipath_kregbase;
315 294
316 if (count == 0) 295 if (count == 0)
@@ -329,23 +308,16 @@ static ssize_t ipath_diag_read(struct file *fp, char __user *data,
329 ret = count; 308 ret = count;
330 } 309 }
331 310
332bail:
333 return ret; 311 return ret;
334} 312}
335 313
336static ssize_t ipath_diag_write(struct file *fp, const char __user *data, 314static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
337 size_t count, loff_t *off) 315 size_t count, loff_t *off)
338{ 316{
339 int unit = 0; /* XXX this is bogus */ 317 struct ipath_devdata *dd = fp->private_data;
340 struct ipath_devdata *dd;
341 void __iomem *kreg_base; 318 void __iomem *kreg_base;
342 ssize_t ret; 319 ssize_t ret;
343 320
344 dd = ipath_lookup(unit);
345 if (!dd) {
346 ret = -ENODEV;
347 goto bail;
348 }
349 kreg_base = dd->ipath_kregbase; 321 kreg_base = dd->ipath_kregbase;
350 322
351 if (count == 0) 323 if (count == 0)
@@ -364,6 +336,5 @@ static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
364 ret = count; 336 ret = count;
365 } 337 }
366 338
367bail:
368 return ret; 339 return ret;
369} 340}
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 05e00ba656e2..0a93e2282beb 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -546,6 +546,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
546 ipath_device_create_group(&pdev->dev, dd); 546 ipath_device_create_group(&pdev->dev, dd);
547 ipathfs_add_device(dd); 547 ipathfs_add_device(dd);
548 ipath_user_add(dd); 548 ipath_user_add(dd);
549 ipath_diag_add(dd);
549 ipath_layer_add(dd); 550 ipath_layer_add(dd);
550 551
551 goto bail; 552 goto bail;
@@ -578,8 +579,9 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev)
578 return; 579 return;
579 580
580 dd = pci_get_drvdata(pdev); 581 dd = pci_get_drvdata(pdev);
581 ipath_layer_del(dd); 582 ipath_layer_remove(dd);
582 ipath_user_del(dd); 583 ipath_diag_remove(dd);
584 ipath_user_remove(dd);
583 ipathfs_remove_device(dd); 585 ipathfs_remove_device(dd);
584 ipath_device_remove_group(&pdev->dev, dd); 586 ipath_device_remove_group(&pdev->dev, dd);
585 ipath_cdbg(VERBOSE, "Releasing pci memory regions, dd %p, " 587 ipath_cdbg(VERBOSE, "Releasing pci memory regions, dd %p, "
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 8ff97e4f97db..cd2d5cd05e88 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -1443,16 +1443,16 @@ done:
1443 1443
1444static int ipath_open(struct inode *in, struct file *fp) 1444static int ipath_open(struct inode *in, struct file *fp)
1445{ 1445{
1446 int ret, minor; 1446 int ret, user_minor;
1447 1447
1448 mutex_lock(&ipath_mutex); 1448 mutex_lock(&ipath_mutex);
1449 1449
1450 minor = iminor(in); 1450 user_minor = iminor(in) - IPATH_USER_MINOR_BASE;
1451 ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n", 1451 ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n",
1452 (long)in->i_rdev, minor); 1452 (long)in->i_rdev, user_minor);
1453 1453
1454 if (minor) 1454 if (user_minor)
1455 ret = find_free_port(minor - 1, fp); 1455 ret = find_free_port(user_minor - 1, fp);
1456 else 1456 else
1457 ret = find_best_unit(fp); 1457 ret = find_best_unit(fp);
1458 1458
@@ -1860,19 +1860,12 @@ int ipath_user_add(struct ipath_devdata *dd)
1860 "error %d\n", -ret); 1860 "error %d\n", -ret);
1861 goto bail; 1861 goto bail;
1862 } 1862 }
1863 ret = ipath_diag_init();
1864 if (ret < 0) {
1865 ipath_dev_err(dd, "Unable to set up diag support: "
1866 "error %d\n", -ret);
1867 goto bail_sma;
1868 }
1869
1870 ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev, 1863 ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev,
1871 &wildcard_class_dev); 1864 &wildcard_class_dev);
1872 if (ret < 0) { 1865 if (ret < 0) {
1873 ipath_dev_err(dd, "Could not create wildcard " 1866 ipath_dev_err(dd, "Could not create wildcard "
1874 "minor: error %d\n", -ret); 1867 "minor: error %d\n", -ret);
1875 goto bail_diag; 1868 goto bail_sma;
1876 } 1869 }
1877 1870
1878 atomic_set(&user_setup, 1); 1871 atomic_set(&user_setup, 1);
@@ -1881,31 +1874,28 @@ int ipath_user_add(struct ipath_devdata *dd)
1881 snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit); 1874 snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit);
1882 1875
1883 ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops, 1876 ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops,
1884 &dd->cdev, &dd->class_dev); 1877 &dd->user_cdev, &dd->user_class_dev);
1885 if (ret < 0) 1878 if (ret < 0)
1886 ipath_dev_err(dd, "Could not create user minor %d, %s\n", 1879 ipath_dev_err(dd, "Could not create user minor %d, %s\n",
1887 dd->ipath_unit + 1, name); 1880 dd->ipath_unit + 1, name);
1888 1881
1889 goto bail; 1882 goto bail;
1890 1883
1891bail_diag:
1892 ipath_diag_cleanup();
1893bail_sma: 1884bail_sma:
1894 user_cleanup(); 1885 user_cleanup();
1895bail: 1886bail:
1896 return ret; 1887 return ret;
1897} 1888}
1898 1889
1899void ipath_user_del(struct ipath_devdata *dd) 1890void ipath_user_remove(struct ipath_devdata *dd)
1900{ 1891{
1901 cleanup_cdev(&dd->cdev, &dd->class_dev); 1892 cleanup_cdev(&dd->user_cdev, &dd->user_class_dev);
1902 1893
1903 if (atomic_dec_return(&user_count) == 0) { 1894 if (atomic_dec_return(&user_count) == 0) {
1904 if (atomic_read(&user_setup) == 0) 1895 if (atomic_read(&user_setup) == 0)
1905 goto bail; 1896 goto bail;
1906 1897
1907 cleanup_cdev(&wildcard_cdev, &wildcard_class_dev); 1898 cleanup_cdev(&wildcard_cdev, &wildcard_class_dev);
1908 ipath_diag_cleanup();
1909 user_cleanup(); 1899 user_cleanup();
1910 1900
1911 atomic_set(&user_setup, 0); 1901 atomic_set(&user_setup, 0);
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 57dea8c443be..412480d1109f 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -355,8 +355,10 @@ struct ipath_devdata {
355 char *ipath_freezemsg; 355 char *ipath_freezemsg;
356 /* pci access data structure */ 356 /* pci access data structure */
357 struct pci_dev *pcidev; 357 struct pci_dev *pcidev;
358 struct cdev *cdev; 358 struct cdev *user_cdev;
359 struct class_device *class_dev; 359 struct cdev *diag_cdev;
360 struct class_device *user_class_dev;
361 struct class_device *diag_class_dev;
360 /* timer used to prevent stats overflow, error throttling, etc. */ 362 /* timer used to prevent stats overflow, error throttling, etc. */
361 struct timer_list ipath_stats_timer; 363 struct timer_list ipath_stats_timer;
362 /* check for stale messages in rcv queue */ 364 /* check for stale messages in rcv queue */
@@ -538,7 +540,7 @@ extern int __ipath_verbs_piobufavail(struct ipath_devdata *);
538extern int __ipath_verbs_rcv(struct ipath_devdata *, void *, void *, u32); 540extern int __ipath_verbs_rcv(struct ipath_devdata *, void *, void *, u32);
539 541
540void ipath_layer_add(struct ipath_devdata *); 542void ipath_layer_add(struct ipath_devdata *);
541void ipath_layer_del(struct ipath_devdata *); 543void ipath_layer_remove(struct ipath_devdata *);
542 544
543int ipath_init_chip(struct ipath_devdata *, int); 545int ipath_init_chip(struct ipath_devdata *, int);
544int ipath_enable_wc(struct ipath_devdata *dd); 546int ipath_enable_wc(struct ipath_devdata *dd);
@@ -552,14 +554,14 @@ int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
552void ipath_cdev_cleanup(struct cdev **cdevp, 554void ipath_cdev_cleanup(struct cdev **cdevp,
553 struct class_device **class_devp); 555 struct class_device **class_devp);
554 556
555int ipath_diag_init(void); 557int ipath_diag_add(struct ipath_devdata *);
556void ipath_diag_cleanup(void); 558void ipath_diag_remove(struct ipath_devdata *);
557void ipath_diag_bringup_link(struct ipath_devdata *); 559void ipath_diag_bringup_link(struct ipath_devdata *);
558 560
559extern wait_queue_head_t ipath_sma_state_wait; 561extern wait_queue_head_t ipath_sma_state_wait;
560 562
561int ipath_user_add(struct ipath_devdata *dd); 563int ipath_user_add(struct ipath_devdata *dd);
562void ipath_user_del(struct ipath_devdata *dd); 564void ipath_user_remove(struct ipath_devdata *dd);
563 565
564struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t); 566struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t);
565 567
@@ -843,9 +845,10 @@ extern struct mutex ipath_mutex;
843 845
844#define IPATH_DRV_NAME "ipath_core" 846#define IPATH_DRV_NAME "ipath_core"
845#define IPATH_MAJOR 233 847#define IPATH_MAJOR 233
848#define IPATH_USER_MINOR_BASE 0
846#define IPATH_SMA_MINOR 128 849#define IPATH_SMA_MINOR 128
847#define IPATH_DIAG_MINOR 129 850#define IPATH_DIAG_MINOR_BASE 129
848#define IPATH_NMINORS 130 851#define IPATH_NMINORS 255
849 852
850#define ipath_dev_err(dd,fmt,...) \ 853#define ipath_dev_err(dd,fmt,...) \
851 do { \ 854 do { \
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c
index fd95b5516409..bb15b17a4225 100644
--- a/drivers/infiniband/hw/ipath/ipath_layer.c
+++ b/drivers/infiniband/hw/ipath/ipath_layer.c
@@ -404,7 +404,7 @@ void ipath_layer_add(struct ipath_devdata *dd)
404 mutex_unlock(&ipath_layer_mutex); 404 mutex_unlock(&ipath_layer_mutex);
405} 405}
406 406
407void ipath_layer_del(struct ipath_devdata *dd) 407void ipath_layer_remove(struct ipath_devdata *dd)
408{ 408{
409 mutex_lock(&ipath_layer_mutex); 409 mutex_lock(&ipath_layer_mutex);
410 410