aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mlx4
diff options
context:
space:
mode:
authorEli Cohen <eli@mellanox.co.il>2011-03-22 18:38:41 -0400
committerDavid S. Miller <davem@davemloft.net>2011-03-23 15:24:23 -0400
commitc1b43dca137f2154845122417fba86d4bae67182 (patch)
tree36237582bfd5baf0e9a3ccea5377b949be289440 /drivers/net/mlx4
parent1679200f91da6a054b06954c9bd3eeed29b6731f (diff)
mlx4: Add blue flame support for kernel consumers
Using blue flame can improve latency by allowing the HW to more efficiently access the WQE. This patch presents two functions that are used to allocate or release HW resources for using blue flame; the caller need to supply a struct mlx4_bf object when allocating resources. Consumers that make use of this API should post doorbells to the UAR object pointed by the initialized struct mlx4_bf; Signed-off-by: Eli Cohen <eli@mellanox.co.il> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/mlx4')
-rw-r--r--drivers/net/mlx4/main.c31
-rw-r--r--drivers/net/mlx4/mlx4.h3
-rw-r--r--drivers/net/mlx4/pd.c94
3 files changed, 128 insertions, 0 deletions
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index c8e276138f81..05c5671749aa 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -39,6 +39,7 @@
39#include <linux/pci.h> 39#include <linux/pci.h>
40#include <linux/dma-mapping.h> 40#include <linux/dma-mapping.h>
41#include <linux/slab.h> 41#include <linux/slab.h>
42#include <linux/io-mapping.h>
42 43
43#include <linux/mlx4/device.h> 44#include <linux/mlx4/device.h>
44#include <linux/mlx4/doorbell.h> 45#include <linux/mlx4/doorbell.h>
@@ -721,8 +722,31 @@ static void mlx4_free_icms(struct mlx4_dev *dev)
721 mlx4_free_icm(dev, priv->fw.aux_icm, 0); 722 mlx4_free_icm(dev, priv->fw.aux_icm, 0);
722} 723}
723 724
725static int map_bf_area(struct mlx4_dev *dev)
726{
727 struct mlx4_priv *priv = mlx4_priv(dev);
728 resource_size_t bf_start;
729 resource_size_t bf_len;
730 int err = 0;
731
732 bf_start = pci_resource_start(dev->pdev, 2) + (dev->caps.num_uars << PAGE_SHIFT);
733 bf_len = pci_resource_len(dev->pdev, 2) - (dev->caps.num_uars << PAGE_SHIFT);
734 priv->bf_mapping = io_mapping_create_wc(bf_start, bf_len);
735 if (!priv->bf_mapping)
736 err = -ENOMEM;
737
738 return err;
739}
740
741static void unmap_bf_area(struct mlx4_dev *dev)
742{
743 if (mlx4_priv(dev)->bf_mapping)
744 io_mapping_free(mlx4_priv(dev)->bf_mapping);
745}
746
724static void mlx4_close_hca(struct mlx4_dev *dev) 747static void mlx4_close_hca(struct mlx4_dev *dev)
725{ 748{
749 unmap_bf_area(dev);
726 mlx4_CLOSE_HCA(dev, 0); 750 mlx4_CLOSE_HCA(dev, 0);
727 mlx4_free_icms(dev); 751 mlx4_free_icms(dev);
728 mlx4_UNMAP_FA(dev); 752 mlx4_UNMAP_FA(dev);
@@ -775,6 +799,9 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
775 goto err_stop_fw; 799 goto err_stop_fw;
776 } 800 }
777 801
802 if (map_bf_area(dev))
803 mlx4_dbg(dev, "Failed to map blue flame area\n");
804
778 init_hca.log_uar_sz = ilog2(dev->caps.num_uars); 805 init_hca.log_uar_sz = ilog2(dev->caps.num_uars);
779 806
780 err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size); 807 err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size);
@@ -805,6 +832,7 @@ err_free_icm:
805 mlx4_free_icms(dev); 832 mlx4_free_icms(dev);
806 833
807err_stop_fw: 834err_stop_fw:
835 unmap_bf_area(dev);
808 mlx4_UNMAP_FA(dev); 836 mlx4_UNMAP_FA(dev);
809 mlx4_free_icm(dev, priv->fw.fw_icm, 0); 837 mlx4_free_icm(dev, priv->fw.fw_icm, 0);
810 838
@@ -1196,6 +1224,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
1196 1224
1197 pci_read_config_byte(pdev, PCI_REVISION_ID, &dev->rev_id); 1225 pci_read_config_byte(pdev, PCI_REVISION_ID, &dev->rev_id);
1198 1226
1227 INIT_LIST_HEAD(&priv->bf_list);
1228 mutex_init(&priv->bf_mutex);
1229
1199 /* 1230 /*
1200 * Now reset the HCA before we touch the PCI capabilities or 1231 * Now reset the HCA before we touch the PCI capabilities or
1201 * attempt a firmware command, since a boot ROM may have left 1232 * attempt a firmware command, since a boot ROM may have left
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index d8bb4418581b..bc9a21657a4f 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -353,6 +353,9 @@ struct mlx4_priv {
353 struct mutex port_mutex; 353 struct mutex port_mutex;
354 struct mlx4_msix_ctl msix_ctl; 354 struct mlx4_msix_ctl msix_ctl;
355 struct mlx4_steer *steer; 355 struct mlx4_steer *steer;
356 struct list_head bf_list;
357 struct mutex bf_mutex;
358 struct io_mapping *bf_mapping;
356}; 359};
357 360
358static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) 361static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
diff --git a/drivers/net/mlx4/pd.c b/drivers/net/mlx4/pd.c
index c4988d6bd5b2..5210a0f31413 100644
--- a/drivers/net/mlx4/pd.c
+++ b/drivers/net/mlx4/pd.c
@@ -32,6 +32,7 @@
32 */ 32 */
33 33
34#include <linux/errno.h> 34#include <linux/errno.h>
35#include <linux/io-mapping.h>
35 36
36#include <asm/page.h> 37#include <asm/page.h>
37 38
@@ -77,6 +78,7 @@ int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar)
77 return -ENOMEM; 78 return -ENOMEM;
78 79
79 uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + uar->index; 80 uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + uar->index;
81 uar->map = NULL;
80 82
81 return 0; 83 return 0;
82} 84}
@@ -88,6 +90,98 @@ void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar)
88} 90}
89EXPORT_SYMBOL_GPL(mlx4_uar_free); 91EXPORT_SYMBOL_GPL(mlx4_uar_free);
90 92
93int mlx4_bf_alloc(struct mlx4_dev *dev, struct mlx4_bf *bf)
94{
95 struct mlx4_priv *priv = mlx4_priv(dev);
96 struct mlx4_uar *uar;
97 int err = 0;
98 int idx;
99
100 if (!priv->bf_mapping)
101 return -ENOMEM;
102
103 mutex_lock(&priv->bf_mutex);
104 if (!list_empty(&priv->bf_list))
105 uar = list_entry(priv->bf_list.next, struct mlx4_uar, bf_list);
106 else {
107 uar = kmalloc(sizeof *uar, GFP_KERNEL);
108 if (!uar) {
109 err = -ENOMEM;
110 goto out;
111 }
112 err = mlx4_uar_alloc(dev, uar);
113 if (err)
114 goto free_kmalloc;
115
116 uar->map = ioremap(uar->pfn << PAGE_SHIFT, PAGE_SIZE);
117 if (!uar->map) {
118 err = -ENOMEM;
119 goto free_uar;
120 }
121
122 uar->bf_map = io_mapping_map_wc(priv->bf_mapping, uar->index << PAGE_SHIFT);
123 if (!uar->bf_map) {
124 err = -ENOMEM;
125 goto unamp_uar;
126 }
127 uar->free_bf_bmap = 0;
128 list_add(&uar->bf_list, &priv->bf_list);
129 }
130
131 bf->uar = uar;
132 idx = ffz(uar->free_bf_bmap);
133 uar->free_bf_bmap |= 1 << idx;
134 bf->uar = uar;
135 bf->offset = 0;
136 bf->buf_size = dev->caps.bf_reg_size / 2;
137 bf->reg = uar->bf_map + idx * dev->caps.bf_reg_size;
138 if (uar->free_bf_bmap == (1 << dev->caps.bf_regs_per_page) - 1)
139 list_del_init(&uar->bf_list);
140
141 goto out;
142
143unamp_uar:
144 bf->uar = NULL;
145 iounmap(uar->map);
146
147free_uar:
148 mlx4_uar_free(dev, uar);
149
150free_kmalloc:
151 kfree(uar);
152
153out:
154 mutex_unlock(&priv->bf_mutex);
155 return err;
156}
157EXPORT_SYMBOL_GPL(mlx4_bf_alloc);
158
159void mlx4_bf_free(struct mlx4_dev *dev, struct mlx4_bf *bf)
160{
161 struct mlx4_priv *priv = mlx4_priv(dev);
162 int idx;
163
164 if (!bf->uar || !bf->uar->bf_map)
165 return;
166
167 mutex_lock(&priv->bf_mutex);
168 idx = (bf->reg - bf->uar->bf_map) / dev->caps.bf_reg_size;
169 bf->uar->free_bf_bmap &= ~(1 << idx);
170 if (!bf->uar->free_bf_bmap) {
171 if (!list_empty(&bf->uar->bf_list))
172 list_del(&bf->uar->bf_list);
173
174 io_mapping_unmap(bf->uar->bf_map);
175 iounmap(bf->uar->map);
176 mlx4_uar_free(dev, bf->uar);
177 kfree(bf->uar);
178 } else if (list_empty(&bf->uar->bf_list))
179 list_add(&bf->uar->bf_list, &priv->bf_list);
180
181 mutex_unlock(&priv->bf_mutex);
182}
183EXPORT_SYMBOL_GPL(mlx4_bf_free);
184
91int mlx4_init_uar_table(struct mlx4_dev *dev) 185int mlx4_init_uar_table(struct mlx4_dev *dev)
92{ 186{
93 if (dev->caps.num_uars <= 128) { 187 if (dev->caps.num_uars <= 128) {