diff options
author | Bryan O'Sullivan <bos@pathscale.com> | 2006-07-01 07:35:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-01 12:55:58 -0400 |
commit | a2acb2ff36876fdfa5f7a8bf811765aadc74c1c1 (patch) | |
tree | ea0e6aaacd36cac011dacae3554b6576dea56d9d /drivers | |
parent | 6700efdfc06d2dc9ef77988a00182c2ede0f1be0 (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.c | 85 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 6 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_file_ops.c | 28 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 19 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_layer.c | 2 |
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 | ||
70 | static struct cdev *diag_cdev; | 70 | int ipath_diag_add(struct ipath_devdata *dd) |
71 | static struct class_device *diag_class_dev; | ||
72 | |||
73 | int 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 | ||
79 | void ipath_diag_cleanup(void) | 81 | void 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 | ||
241 | static int ipath_diag_open(struct inode *in, struct file *fp) | 241 | static 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; | |
279 | bail: | 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 | ||
271 | bail: | ||
287 | mutex_unlock(&ipath_mutex); | 272 | mutex_unlock(&ipath_mutex); |
288 | 273 | ||
289 | return ret; | 274 | return ret; |
290 | } | 275 | } |
291 | 276 | ||
292 | static int ipath_diag_release(struct inode *i, struct file *f) | 277 | static 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) | |||
300 | static ssize_t ipath_diag_read(struct file *fp, char __user *data, | 286 | static 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 | ||
332 | bail: | ||
333 | return ret; | 311 | return ret; |
334 | } | 312 | } |
335 | 313 | ||
336 | static ssize_t ipath_diag_write(struct file *fp, const char __user *data, | 314 | static 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 | ||
367 | bail: | ||
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 | ||
1444 | static int ipath_open(struct inode *in, struct file *fp) | 1444 | static 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 | ||
1891 | bail_diag: | ||
1892 | ipath_diag_cleanup(); | ||
1893 | bail_sma: | 1884 | bail_sma: |
1894 | user_cleanup(); | 1885 | user_cleanup(); |
1895 | bail: | 1886 | bail: |
1896 | return ret; | 1887 | return ret; |
1897 | } | 1888 | } |
1898 | 1889 | ||
1899 | void ipath_user_del(struct ipath_devdata *dd) | 1890 | void 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 *); | |||
538 | extern int __ipath_verbs_rcv(struct ipath_devdata *, void *, void *, u32); | 540 | extern int __ipath_verbs_rcv(struct ipath_devdata *, void *, void *, u32); |
539 | 541 | ||
540 | void ipath_layer_add(struct ipath_devdata *); | 542 | void ipath_layer_add(struct ipath_devdata *); |
541 | void ipath_layer_del(struct ipath_devdata *); | 543 | void ipath_layer_remove(struct ipath_devdata *); |
542 | 544 | ||
543 | int ipath_init_chip(struct ipath_devdata *, int); | 545 | int ipath_init_chip(struct ipath_devdata *, int); |
544 | int ipath_enable_wc(struct ipath_devdata *dd); | 546 | int ipath_enable_wc(struct ipath_devdata *dd); |
@@ -552,14 +554,14 @@ int ipath_cdev_init(int minor, char *name, struct file_operations *fops, | |||
552 | void ipath_cdev_cleanup(struct cdev **cdevp, | 554 | void ipath_cdev_cleanup(struct cdev **cdevp, |
553 | struct class_device **class_devp); | 555 | struct class_device **class_devp); |
554 | 556 | ||
555 | int ipath_diag_init(void); | 557 | int ipath_diag_add(struct ipath_devdata *); |
556 | void ipath_diag_cleanup(void); | 558 | void ipath_diag_remove(struct ipath_devdata *); |
557 | void ipath_diag_bringup_link(struct ipath_devdata *); | 559 | void ipath_diag_bringup_link(struct ipath_devdata *); |
558 | 560 | ||
559 | extern wait_queue_head_t ipath_sma_state_wait; | 561 | extern wait_queue_head_t ipath_sma_state_wait; |
560 | 562 | ||
561 | int ipath_user_add(struct ipath_devdata *dd); | 563 | int ipath_user_add(struct ipath_devdata *dd); |
562 | void ipath_user_del(struct ipath_devdata *dd); | 564 | void ipath_user_remove(struct ipath_devdata *dd); |
563 | 565 | ||
564 | struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t); | 566 | struct 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 | ||
407 | void ipath_layer_del(struct ipath_devdata *dd) | 407 | void ipath_layer_remove(struct ipath_devdata *dd) |
408 | { | 408 | { |
409 | mutex_lock(&ipath_layer_mutex); | 409 | mutex_lock(&ipath_layer_mutex); |
410 | 410 | ||