diff options
-rw-r--r-- | drivers/net/mlx4/main.c | 31 | ||||
-rw-r--r-- | drivers/net/mlx4/mlx4.h | 3 | ||||
-rw-r--r-- | drivers/net/mlx4/pd.c | 94 | ||||
-rw-r--r-- | include/linux/mlx4/device.h | 13 | ||||
-rw-r--r-- | include/linux/mlx4/qp.h | 1 |
5 files changed, 142 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 | ||
725 | static 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 | |||
741 | static 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 | |||
724 | static void mlx4_close_hca(struct mlx4_dev *dev) | 747 | static 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 | ||
807 | err_stop_fw: | 834 | err_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 | ||
358 | static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) | 361 | static 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 | } |
89 | EXPORT_SYMBOL_GPL(mlx4_uar_free); | 91 | EXPORT_SYMBOL_GPL(mlx4_uar_free); |
90 | 92 | ||
93 | int 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 | |||
143 | unamp_uar: | ||
144 | bf->uar = NULL; | ||
145 | iounmap(uar->map); | ||
146 | |||
147 | free_uar: | ||
148 | mlx4_uar_free(dev, uar); | ||
149 | |||
150 | free_kmalloc: | ||
151 | kfree(uar); | ||
152 | |||
153 | out: | ||
154 | mutex_unlock(&priv->bf_mutex); | ||
155 | return err; | ||
156 | } | ||
157 | EXPORT_SYMBOL_GPL(mlx4_bf_alloc); | ||
158 | |||
159 | void 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 | } | ||
183 | EXPORT_SYMBOL_GPL(mlx4_bf_free); | ||
184 | |||
91 | int mlx4_init_uar_table(struct mlx4_dev *dev) | 185 | int mlx4_init_uar_table(struct mlx4_dev *dev) |
92 | { | 186 | { |
93 | if (dev->caps.num_uars <= 128) { | 187 | if (dev->caps.num_uars <= 128) { |
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 56fa5e1cd6d4..8985768e2c0d 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h | |||
@@ -351,6 +351,17 @@ struct mlx4_fmr { | |||
351 | struct mlx4_uar { | 351 | struct mlx4_uar { |
352 | unsigned long pfn; | 352 | unsigned long pfn; |
353 | int index; | 353 | int index; |
354 | struct list_head bf_list; | ||
355 | unsigned free_bf_bmap; | ||
356 | void __iomem *map; | ||
357 | void __iomem *bf_map; | ||
358 | }; | ||
359 | |||
360 | struct mlx4_bf { | ||
361 | unsigned long offset; | ||
362 | int buf_size; | ||
363 | struct mlx4_uar *uar; | ||
364 | void __iomem *reg; | ||
354 | }; | 365 | }; |
355 | 366 | ||
356 | struct mlx4_cq { | 367 | struct mlx4_cq { |
@@ -478,6 +489,8 @@ void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn); | |||
478 | 489 | ||
479 | int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar); | 490 | int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar); |
480 | void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar); | 491 | void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar); |
492 | int mlx4_bf_alloc(struct mlx4_dev *dev, struct mlx4_bf *bf); | ||
493 | void mlx4_bf_free(struct mlx4_dev *dev, struct mlx4_bf *bf); | ||
481 | 494 | ||
482 | int mlx4_mtt_init(struct mlx4_dev *dev, int npages, int page_shift, | 495 | int mlx4_mtt_init(struct mlx4_dev *dev, int npages, int page_shift, |
483 | struct mlx4_mtt *mtt); | 496 | struct mlx4_mtt *mtt); |
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h index 0eeb2a1a867c..9e9eb21056ca 100644 --- a/include/linux/mlx4/qp.h +++ b/include/linux/mlx4/qp.h | |||
@@ -303,6 +303,7 @@ struct mlx4_wqe_data_seg { | |||
303 | 303 | ||
304 | enum { | 304 | enum { |
305 | MLX4_INLINE_ALIGN = 64, | 305 | MLX4_INLINE_ALIGN = 64, |
306 | MLX4_INLINE_SEG = 1 << 31, | ||
306 | }; | 307 | }; |
307 | 308 | ||
308 | struct mlx4_wqe_inline_seg { | 309 | struct mlx4_wqe_inline_seg { |