Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
  3  * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  4  *
  5  * This software is available to you under a choice of one of two
  6  * licenses.  You may choose to be licensed under the terms of the GNU
  7  * General Public License (GPL) Version 2, available from the file
  8  * COPYING in the main directory of this source tree, or the
  9  * OpenIB.org BSD license below:
 10  *
 11  *     Redistribution and use in source and binary forms, with or
 12  *     without modification, are permitted provided that the following
 13  *     conditions are met:
 14  *
 15  *      - Redistributions of source code must retain the above
 16  *        copyright notice, this list of conditions and the following
 17  *        disclaimer.
 18  *
 19  *      - Redistributions in binary form must reproduce the above
 20  *        copyright notice, this list of conditions and the following
 21  *        disclaimer in the documentation and/or other materials
 22  *        provided with the distribution.
 23  *
 24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 31  * SOFTWARE.
 32  */
 33 
 34 #include "mlx4.h"
 35 
 36 struct mlx4_device_context {
 37         struct list_head        list;
 38         struct mlx4_interface  *intf;
 39         void                   *context;
 40 };
 41 
 42 static LIST_HEAD(intf_list);
 43 static LIST_HEAD(dev_list);
 44 static DEFINE_MUTEX(intf_mutex);
 45 
 46 static void mlx4_add_device(struct mlx4_interface *intf, struct mlx4_priv *priv)
 47 {
 48         struct mlx4_device_context *dev_ctx;
 49 
 50         dev_ctx = kmalloc(sizeof *dev_ctx, GFP_KERNEL);
 51         if (!dev_ctx)
 52                 return;
 53 
 54         dev_ctx->intf    = intf;
 55         dev_ctx->context = intf->add(&priv->dev);
 56 
 57         if (dev_ctx->context) {
 58                 spin_lock_irq(&priv->ctx_lock);
 59                 list_add_tail(&dev_ctx->list, &priv->ctx_list);
 60                 spin_unlock_irq(&priv->ctx_lock);
 61         } else
 62                 kfree(dev_ctx);
 63 }
 64 
 65 static void mlx4_remove_device(struct mlx4_interface *intf, struct mlx4_priv *priv)
 66 {
 67         struct mlx4_device_context *dev_ctx;
 68 
 69         list_for_each_entry(dev_ctx, &priv->ctx_list, list)
 70                 if (dev_ctx->intf == intf) {
 71                         spin_lock_irq(&priv->ctx_lock);
 72                         list_del(&dev_ctx->list);
 73                         spin_unlock_irq(&priv->ctx_lock);
 74 
 75                         intf->remove(&priv->dev, dev_ctx->context);
 76                         kfree(dev_ctx);
 77                         return;
 78                 }
 79 }
 80 
 81 int mlx4_register_interface(struct mlx4_interface *intf)
 82 {
 83         struct mlx4_priv *priv;
 84 
 85         if (!intf->add || !intf->remove)
 86                 return -EINVAL;
 87 
 88         mutex_lock(&intf_mutex);
 89 
 90         list_add_tail(&intf->list, &intf_list);
 91         list_for_each_entry(priv, &dev_list, dev_list)
 92                 mlx4_add_device(intf, priv);
 93 
 94         mutex_unlock(&intf_mutex);
 95 
 96         return 0;
 97 }
 98 EXPORT_SYMBOL_GPL(mlx4_register_interface);
 99 
100 void mlx4_unregister_interface(struct mlx4_interface *intf)
101 {
102         struct mlx4_priv *priv;
103 
104         mutex_lock(&intf_mutex);
105 
106         list_for_each_entry(priv, &dev_list, dev_list)
107                 mlx4_remove_device(intf, priv);
108 
109         list_del(&intf->list);
110 
111         mutex_unlock(&intf_mutex);
112 }
113 EXPORT_SYMBOL_GPL(mlx4_unregister_interface);
114 
115 void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, int port)
116 {
117         struct mlx4_priv *priv = mlx4_priv(dev);
118         struct mlx4_device_context *dev_ctx;
119         unsigned long flags;
120 
121         spin_lock_irqsave(&priv->ctx_lock, flags);
122 
123         list_for_each_entry(dev_ctx, &priv->ctx_list, list)
124                 if (dev_ctx->intf->event)
125                         dev_ctx->intf->event(dev, dev_ctx->context, type, port);
126 
127         spin_unlock_irqrestore(&priv->ctx_lock, flags);
128 }
129 
130 int mlx4_register_device(struct mlx4_dev *dev)
131 {
132         struct mlx4_priv *priv = mlx4_priv(dev);
133         struct mlx4_interface *intf;
134 
135         mutex_lock(&intf_mutex);
136 
137         list_add_tail(&priv->dev_list, &dev_list);
138         list_for_each_entry(intf, &intf_list, list)
139                 mlx4_add_device(intf, priv);
140 
141         mutex_unlock(&intf_mutex);
142         mlx4_start_catas_poll(dev);
143 
144         return 0;
145 }
146 
147 void mlx4_unregister_device(struct mlx4_dev *dev)
148 {
149         struct mlx4_priv *priv = mlx4_priv(dev);
150         struct mlx4_interface *intf;
151 
152         mlx4_stop_catas_poll(dev);
153         mutex_lock(&intf_mutex);
154 
155         list_for_each_entry(intf, &intf_list, list)
156                 mlx4_remove_device(intf, priv);
157 
158         list_del(&priv->dev_list);
159 
160         mutex_unlock(&intf_mutex);
161 }
162 
  This page was automatically generated by the LXR engine.