diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 22:43:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 22:43:13 -0400 |
commit | ce9d3c9a6a9aef61525be07fe6ba27d937236aa2 (patch) | |
tree | 1b29bcb8f60fc6b59fa0d7b833cc733b8ebe17c9 /drivers/net | |
parent | 038a5008b2f395c85e6e71d6ddf3c684e7c405b0 (diff) | |
parent | 3d73c2884f45f9a297cbc956cea101405a9703f2 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband: (87 commits)
mlx4_core: Fix section mismatches
IPoIB: Allow setting policy to ignore multicast groups
IB/mthca: Mark error paths as unlikely() in post_srq_recv functions
IB/ipath: Minor fix to ordering of freeing and zeroing of tid pages.
IB/ipath: Remove redundant link state checks
IB/ipath: Fix IB_EVENT_PORT_ERR event
IB/ipath: Better handling of unexpected GPIO interrupts
IB/ipath: Maintain active time on all chips
IB/ipath: Fix QHT7040 serial number check
IB/ipath: Indicate a couple of chip bugs to userspace
IB/ipath: iba6110 rev4 no longer needs recv header overrun workaround
IB/ipath: Use counters in ipath_poll and cleanup interrupts in ipath_close
IB/ipath: Remove duplicate copy of LMC
IB/ipath: Add ability to set the LMC via the sysfs debugging interface
IB/ipath: Optimize completion queue entry insertion and polling
IB/ipath: Implement IB_EVENT_QP_LAST_WQE_REACHED
IB/ipath: Generate flush CQE when QP is in error state
IB/ipath: Remove redundant code
IB/ipath: Future proof eeprom checksum code (contents reading)
IB/ipath: UC RDMA WRITE with IMMEDIATE doesn't send the immediate
...
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/mlx4/cmd.c | 11 | ||||
-rw-r--r-- | drivers/net/mlx4/cq.c | 2 | ||||
-rw-r--r-- | drivers/net/mlx4/eq.c | 13 | ||||
-rw-r--r-- | drivers/net/mlx4/fw.c | 2 | ||||
-rw-r--r-- | drivers/net/mlx4/icm.c | 134 | ||||
-rw-r--r-- | drivers/net/mlx4/icm.h | 9 | ||||
-rw-r--r-- | drivers/net/mlx4/main.c | 130 | ||||
-rw-r--r-- | drivers/net/mlx4/mcg.c | 2 | ||||
-rw-r--r-- | drivers/net/mlx4/mlx4.h | 10 | ||||
-rw-r--r-- | drivers/net/mlx4/mr.c | 242 | ||||
-rw-r--r-- | drivers/net/mlx4/pd.c | 2 | ||||
-rw-r--r-- | drivers/net/mlx4/qp.c | 5 | ||||
-rw-r--r-- | drivers/net/mlx4/srq.c | 4 |
13 files changed, 415 insertions, 151 deletions
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c index a9f31753661..db49051b97b 100644 --- a/drivers/net/mlx4/cmd.c +++ b/drivers/net/mlx4/cmd.c | |||
@@ -95,7 +95,7 @@ enum { | |||
95 | }; | 95 | }; |
96 | 96 | ||
97 | enum { | 97 | enum { |
98 | GO_BIT_TIMEOUT = 10000 | 98 | GO_BIT_TIMEOUT_MSECS = 10000 |
99 | }; | 99 | }; |
100 | 100 | ||
101 | struct mlx4_cmd_context { | 101 | struct mlx4_cmd_context { |
@@ -155,7 +155,7 @@ static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param, | |||
155 | 155 | ||
156 | end = jiffies; | 156 | end = jiffies; |
157 | if (event) | 157 | if (event) |
158 | end += HZ * 10; | 158 | end += msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS); |
159 | 159 | ||
160 | while (cmd_pending(dev)) { | 160 | while (cmd_pending(dev)) { |
161 | if (time_after_eq(jiffies, end)) | 161 | if (time_after_eq(jiffies, end)) |
@@ -184,6 +184,13 @@ static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param, | |||
184 | (event ? (1 << HCR_E_BIT) : 0) | | 184 | (event ? (1 << HCR_E_BIT) : 0) | |
185 | (op_modifier << HCR_OPMOD_SHIFT) | | 185 | (op_modifier << HCR_OPMOD_SHIFT) | |
186 | op), hcr + 6); | 186 | op), hcr + 6); |
187 | |||
188 | /* | ||
189 | * Make sure that our HCR writes don't get mixed in with | ||
190 | * writes from another CPU starting a FW command. | ||
191 | */ | ||
192 | mmiowb(); | ||
193 | |||
187 | cmd->toggle = cmd->toggle ^ 1; | 194 | cmd->toggle = cmd->toggle ^ 1; |
188 | 195 | ||
189 | ret = 0; | 196 | ret = 0; |
diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c index 39253d0c159..d4441fee3d8 100644 --- a/drivers/net/mlx4/cq.c +++ b/drivers/net/mlx4/cq.c | |||
@@ -231,7 +231,7 @@ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq) | |||
231 | } | 231 | } |
232 | EXPORT_SYMBOL_GPL(mlx4_cq_free); | 232 | EXPORT_SYMBOL_GPL(mlx4_cq_free); |
233 | 233 | ||
234 | int __devinit mlx4_init_cq_table(struct mlx4_dev *dev) | 234 | int mlx4_init_cq_table(struct mlx4_dev *dev) |
235 | { | 235 | { |
236 | struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table; | 236 | struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table; |
237 | int err; | 237 | int err; |
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c index 2095c843fa1..9c36c203403 100644 --- a/drivers/net/mlx4/eq.c +++ b/drivers/net/mlx4/eq.c | |||
@@ -300,8 +300,7 @@ static int mlx4_HW2SW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, | |||
300 | MLX4_CMD_TIME_CLASS_A); | 300 | MLX4_CMD_TIME_CLASS_A); |
301 | } | 301 | } |
302 | 302 | ||
303 | static void __devinit __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, | 303 | static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq) |
304 | struct mlx4_eq *eq) | ||
305 | { | 304 | { |
306 | struct mlx4_priv *priv = mlx4_priv(dev); | 305 | struct mlx4_priv *priv = mlx4_priv(dev); |
307 | int index; | 306 | int index; |
@@ -323,8 +322,8 @@ static void __devinit __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, | |||
323 | return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4); | 322 | return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4); |
324 | } | 323 | } |
325 | 324 | ||
326 | static int __devinit mlx4_create_eq(struct mlx4_dev *dev, int nent, | 325 | static int mlx4_create_eq(struct mlx4_dev *dev, int nent, |
327 | u8 intr, struct mlx4_eq *eq) | 326 | u8 intr, struct mlx4_eq *eq) |
328 | { | 327 | { |
329 | struct mlx4_priv *priv = mlx4_priv(dev); | 328 | struct mlx4_priv *priv = mlx4_priv(dev); |
330 | struct mlx4_cmd_mailbox *mailbox; | 329 | struct mlx4_cmd_mailbox *mailbox; |
@@ -485,7 +484,7 @@ static void mlx4_free_irqs(struct mlx4_dev *dev) | |||
485 | free_irq(eq_table->eq[i].irq, eq_table->eq + i); | 484 | free_irq(eq_table->eq[i].irq, eq_table->eq + i); |
486 | } | 485 | } |
487 | 486 | ||
488 | static int __devinit mlx4_map_clr_int(struct mlx4_dev *dev) | 487 | static int mlx4_map_clr_int(struct mlx4_dev *dev) |
489 | { | 488 | { |
490 | struct mlx4_priv *priv = mlx4_priv(dev); | 489 | struct mlx4_priv *priv = mlx4_priv(dev); |
491 | 490 | ||
@@ -506,7 +505,7 @@ static void mlx4_unmap_clr_int(struct mlx4_dev *dev) | |||
506 | iounmap(priv->clr_base); | 505 | iounmap(priv->clr_base); |
507 | } | 506 | } |
508 | 507 | ||
509 | int __devinit mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt) | 508 | int mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt) |
510 | { | 509 | { |
511 | struct mlx4_priv *priv = mlx4_priv(dev); | 510 | struct mlx4_priv *priv = mlx4_priv(dev); |
512 | int ret; | 511 | int ret; |
@@ -548,7 +547,7 @@ void mlx4_unmap_eq_icm(struct mlx4_dev *dev) | |||
548 | __free_page(priv->eq_table.icm_page); | 547 | __free_page(priv->eq_table.icm_page); |
549 | } | 548 | } |
550 | 549 | ||
551 | int __devinit mlx4_init_eq_table(struct mlx4_dev *dev) | 550 | int mlx4_init_eq_table(struct mlx4_dev *dev) |
552 | { | 551 | { |
553 | struct mlx4_priv *priv = mlx4_priv(dev); | 552 | struct mlx4_priv *priv = mlx4_priv(dev); |
554 | int err; | 553 | int err; |
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index c45cbe43a0c..6471d33afb7 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c | |||
@@ -76,7 +76,7 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags) | |||
76 | [ 0] = "RC transport", | 76 | [ 0] = "RC transport", |
77 | [ 1] = "UC transport", | 77 | [ 1] = "UC transport", |
78 | [ 2] = "UD transport", | 78 | [ 2] = "UD transport", |
79 | [ 3] = "SRC transport", | 79 | [ 3] = "XRC transport", |
80 | [ 4] = "reliable multicast", | 80 | [ 4] = "reliable multicast", |
81 | [ 5] = "FCoIB support", | 81 | [ 5] = "FCoIB support", |
82 | [ 6] = "SRQ support", | 82 | [ 6] = "SRQ support", |
diff --git a/drivers/net/mlx4/icm.c b/drivers/net/mlx4/icm.c index b7a4aa8476f..4b3c109d5ea 100644 --- a/drivers/net/mlx4/icm.c +++ b/drivers/net/mlx4/icm.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/errno.h> | 35 | #include <linux/errno.h> |
36 | #include <linux/mm.h> | 36 | #include <linux/mm.h> |
37 | #include <linux/scatterlist.h> | ||
37 | 38 | ||
38 | #include <linux/mlx4/cmd.h> | 39 | #include <linux/mlx4/cmd.h> |
39 | 40 | ||
@@ -50,19 +51,41 @@ enum { | |||
50 | MLX4_TABLE_CHUNK_SIZE = 1 << 18 | 51 | MLX4_TABLE_CHUNK_SIZE = 1 << 18 |
51 | }; | 52 | }; |
52 | 53 | ||
53 | void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm) | 54 | static void mlx4_free_icm_pages(struct mlx4_dev *dev, struct mlx4_icm_chunk *chunk) |
54 | { | 55 | { |
55 | struct mlx4_icm_chunk *chunk, *tmp; | ||
56 | int i; | 56 | int i; |
57 | 57 | ||
58 | list_for_each_entry_safe(chunk, tmp, &icm->chunk_list, list) { | 58 | if (chunk->nsg > 0) |
59 | if (chunk->nsg > 0) | 59 | pci_unmap_sg(dev->pdev, chunk->mem, chunk->npages, |
60 | pci_unmap_sg(dev->pdev, chunk->mem, chunk->npages, | 60 | PCI_DMA_BIDIRECTIONAL); |
61 | PCI_DMA_BIDIRECTIONAL); | 61 | |
62 | for (i = 0; i < chunk->npages; ++i) | ||
63 | __free_pages(chunk->mem[i].page, | ||
64 | get_order(chunk->mem[i].length)); | ||
65 | } | ||
66 | |||
67 | static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *chunk) | ||
68 | { | ||
69 | int i; | ||
70 | |||
71 | for (i = 0; i < chunk->npages; ++i) | ||
72 | dma_free_coherent(&dev->pdev->dev, chunk->mem[i].length, | ||
73 | lowmem_page_address(chunk->mem[i].page), | ||
74 | sg_dma_address(&chunk->mem[i])); | ||
75 | } | ||
76 | |||
77 | void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent) | ||
78 | { | ||
79 | struct mlx4_icm_chunk *chunk, *tmp; | ||
62 | 80 | ||
63 | for (i = 0; i < chunk->npages; ++i) | 81 | if (!icm) |
64 | __free_pages(chunk->mem[i].page, | 82 | return; |
65 | get_order(chunk->mem[i].length)); | 83 | |
84 | list_for_each_entry_safe(chunk, tmp, &icm->chunk_list, list) { | ||
85 | if (coherent) | ||
86 | mlx4_free_icm_coherent(dev, chunk); | ||
87 | else | ||
88 | mlx4_free_icm_pages(dev, chunk); | ||
66 | 89 | ||
67 | kfree(chunk); | 90 | kfree(chunk); |
68 | } | 91 | } |
@@ -70,16 +93,45 @@ void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm) | |||
70 | kfree(icm); | 93 | kfree(icm); |
71 | } | 94 | } |
72 | 95 | ||
96 | static int mlx4_alloc_icm_pages(struct scatterlist *mem, int order, gfp_t gfp_mask) | ||
97 | { | ||
98 | mem->page = alloc_pages(gfp_mask, order); | ||
99 | if (!mem->page) | ||
100 | return -ENOMEM; | ||
101 | |||
102 | mem->length = PAGE_SIZE << order; | ||
103 | mem->offset = 0; | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem, | ||
108 | int order, gfp_t gfp_mask) | ||
109 | { | ||
110 | void *buf = dma_alloc_coherent(dev, PAGE_SIZE << order, | ||
111 | &sg_dma_address(mem), gfp_mask); | ||
112 | if (!buf) | ||
113 | return -ENOMEM; | ||
114 | |||
115 | sg_set_buf(mem, buf, PAGE_SIZE << order); | ||
116 | BUG_ON(mem->offset); | ||
117 | sg_dma_len(mem) = PAGE_SIZE << order; | ||
118 | return 0; | ||
119 | } | ||
120 | |||
73 | struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, | 121 | struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, |
74 | gfp_t gfp_mask) | 122 | gfp_t gfp_mask, int coherent) |
75 | { | 123 | { |
76 | struct mlx4_icm *icm; | 124 | struct mlx4_icm *icm; |
77 | struct mlx4_icm_chunk *chunk = NULL; | 125 | struct mlx4_icm_chunk *chunk = NULL; |
78 | int cur_order; | 126 | int cur_order; |
127 | int ret; | ||
128 | |||
129 | /* We use sg_set_buf for coherent allocs, which assumes low memory */ | ||
130 | BUG_ON(coherent && (gfp_mask & __GFP_HIGHMEM)); | ||
79 | 131 | ||
80 | icm = kmalloc(sizeof *icm, gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN)); | 132 | icm = kmalloc(sizeof *icm, gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN)); |
81 | if (!icm) | 133 | if (!icm) |
82 | return icm; | 134 | return NULL; |
83 | 135 | ||
84 | icm->refcount = 0; | 136 | icm->refcount = 0; |
85 | INIT_LIST_HEAD(&icm->chunk_list); | 137 | INIT_LIST_HEAD(&icm->chunk_list); |
@@ -101,12 +153,20 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, | |||
101 | while (1 << cur_order > npages) | 153 | while (1 << cur_order > npages) |
102 | --cur_order; | 154 | --cur_order; |
103 | 155 | ||
104 | chunk->mem[chunk->npages].page = alloc_pages(gfp_mask, cur_order); | 156 | if (coherent) |
105 | if (chunk->mem[chunk->npages].page) { | 157 | ret = mlx4_alloc_icm_coherent(&dev->pdev->dev, |
106 | chunk->mem[chunk->npages].length = PAGE_SIZE << cur_order; | 158 | &chunk->mem[chunk->npages], |
107 | chunk->mem[chunk->npages].offset = 0; | 159 | cur_order, gfp_mask); |
160 | else | ||
161 | ret = mlx4_alloc_icm_pages(&chunk->mem[chunk->npages], | ||
162 | cur_order, gfp_mask); | ||
163 | |||
164 | if (!ret) { | ||
165 | ++chunk->npages; | ||
108 | 166 | ||
109 | if (++chunk->npages == MLX4_ICM_CHUNK_LEN) { | 167 | if (coherent) |
168 | ++chunk->nsg; | ||
169 | else if (chunk->npages == MLX4_ICM_CHUNK_LEN) { | ||
110 | chunk->nsg = pci_map_sg(dev->pdev, chunk->mem, | 170 | chunk->nsg = pci_map_sg(dev->pdev, chunk->mem, |
111 | chunk->npages, | 171 | chunk->npages, |
112 | PCI_DMA_BIDIRECTIONAL); | 172 | PCI_DMA_BIDIRECTIONAL); |
@@ -125,7 +185,7 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, | |||
125 | } | 185 | } |
126 | } | 186 | } |
127 | 187 | ||
128 | if (chunk) { | 188 | if (!coherent && chunk) { |
129 | chunk->nsg = pci_map_sg(dev->pdev, chunk->mem, | 189 | chunk->nsg = pci_map_sg(dev->pdev, chunk->mem, |
130 | chunk->npages, | 190 | chunk->npages, |
131 | PCI_DMA_BIDIRECTIONAL); | 191 | PCI_DMA_BIDIRECTIONAL); |
@@ -137,7 +197,7 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, | |||
137 | return icm; | 197 | return icm; |
138 | 198 | ||
139 | fail: | 199 | fail: |
140 | mlx4_free_icm(dev, icm); | 200 | mlx4_free_icm(dev, icm, coherent); |
141 | return NULL; | 201 | return NULL; |
142 | } | 202 | } |
143 | 203 | ||
@@ -202,7 +262,7 @@ int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) | |||
202 | 262 | ||
203 | table->icm[i] = mlx4_alloc_icm(dev, MLX4_TABLE_CHUNK_SIZE >> PAGE_SHIFT, | 263 | table->icm[i] = mlx4_alloc_icm(dev, MLX4_TABLE_CHUNK_SIZE >> PAGE_SHIFT, |
204 | (table->lowmem ? GFP_KERNEL : GFP_HIGHUSER) | | 264 | (table->lowmem ? GFP_KERNEL : GFP_HIGHUSER) | |
205 | __GFP_NOWARN); | 265 | __GFP_NOWARN, table->coherent); |
206 | if (!table->icm[i]) { | 266 | if (!table->icm[i]) { |
207 | ret = -ENOMEM; | 267 | ret = -ENOMEM; |
208 | goto out; | 268 | goto out; |
@@ -210,7 +270,7 @@ int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) | |||
210 | 270 | ||
211 | if (mlx4_MAP_ICM(dev, table->icm[i], table->virt + | 271 | if (mlx4_MAP_ICM(dev, table->icm[i], table->virt + |
212 | (u64) i * MLX4_TABLE_CHUNK_SIZE)) { | 272 | (u64) i * MLX4_TABLE_CHUNK_SIZE)) { |
213 | mlx4_free_icm(dev, table->icm[i]); | 273 | mlx4_free_icm(dev, table->icm[i], table->coherent); |
214 | table->icm[i] = NULL; | 274 | table->icm[i] = NULL; |
215 | ret = -ENOMEM; | 275 | ret = -ENOMEM; |
216 | goto out; | 276 | goto out; |
@@ -234,16 +294,16 @@ void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) | |||
234 | if (--table->icm[i]->refcount == 0) { | 294 | if (--table->icm[i]->refcount == 0) { |
235 | mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, | 295 | mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, |
236 | MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); | 296 | MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); |
237 | mlx4_free_icm(dev, table->icm[i]); | 297 | mlx4_free_icm(dev, table->icm[i], table->coherent); |
238 | table->icm[i] = NULL; | 298 | table->icm[i] = NULL; |
239 | } | 299 | } |
240 | 300 | ||
241 | mutex_unlock(&table->mutex); | 301 | mutex_unlock(&table->mutex); |
242 | } | 302 | } |
243 | 303 | ||
244 | void *mlx4_table_find(struct mlx4_icm_table *table, int obj) | 304 | void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle) |
245 | { | 305 | { |
246 | int idx, offset, i; | 306 | int idx, offset, dma_offset, i; |
247 | struct mlx4_icm_chunk *chunk; | 307 | struct mlx4_icm_chunk *chunk; |
248 | struct mlx4_icm *icm; | 308 | struct mlx4_icm *icm; |
249 | struct page *page = NULL; | 309 | struct page *page = NULL; |
@@ -253,15 +313,26 @@ void *mlx4_table_find(struct mlx4_icm_table *table, int obj) | |||
253 | 313 | ||
254 | mutex_lock(&table->mutex); | 314 | mutex_lock(&table->mutex); |
255 | 315 | ||
256 | idx = obj & (table->num_obj - 1); | 316 | idx = (obj & (table->num_obj - 1)) * table->obj_size; |
257 | icm = table->icm[idx / (MLX4_TABLE_CHUNK_SIZE / table->obj_size)]; | 317 | icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE]; |
258 | offset = idx % (MLX4_TABLE_CHUNK_SIZE / table->obj_size); | 318 | dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE; |
259 | 319 | ||
260 | if (!icm) | 320 | if (!icm) |
261 | goto out; | 321 | goto out; |
262 | 322 | ||
263 | list_for_each_entry(chunk, &icm->chunk_list, list) { | 323 | list_for_each_entry(chunk, &icm->chunk_list, list) { |
264 | for (i = 0; i < chunk->npages; ++i) { | 324 | for (i = 0; i < chunk->npages; ++i) { |
325 | if (dma_handle && dma_offset >= 0) { | ||
326 | if (sg_dma_len(&chunk->mem[i]) > dma_offset) | ||
327 | *dma_handle = sg_dma_address(&chunk->mem[i]) + | ||
328 | dma_offset; | ||
329 | dma_offset -= sg_dma_len(&chunk->mem[i]); | ||
330 | } | ||
331 | /* | ||
332 | * DMA mapping can merge pages but not split them, | ||
333 | * so if we found the page, dma_handle has already | ||
334 | * been assigned to. | ||
335 | */ | ||
265 | if (chunk->mem[i].length > offset) { | 336 | if (chunk->mem[i].length > offset) { |
266 | page = chunk->mem[i].page; | 337 | page = chunk->mem[i].page; |
267 | goto out; | 338 | goto out; |
@@ -309,7 +380,7 @@ void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, | |||
309 | 380 | ||
310 | int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, | 381 | int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, |
311 | u64 virt, int obj_size, int nobj, int reserved, | 382 | u64 virt, int obj_size, int nobj, int reserved, |
312 | int use_lowmem) | 383 | int use_lowmem, int use_coherent) |
313 | { | 384 | { |
314 | int obj_per_chunk; | 385 | int obj_per_chunk; |
315 | int num_icm; | 386 | int num_icm; |
@@ -327,6 +398,7 @@ int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, | |||
327 | table->num_obj = nobj; | 398 | table->num_obj = nobj; |
328 | table->obj_size = obj_size; | 399 | table->obj_size = obj_size; |
329 | table->lowmem = use_lowmem; | 400 | table->lowmem = use_lowmem; |
401 | table->coherent = use_coherent; | ||
330 | mutex_init(&table->mutex); | 402 | mutex_init(&table->mutex); |
331 | 403 | ||
332 | for (i = 0; i * MLX4_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) { | 404 | for (i = 0; i * MLX4_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) { |
@@ -336,11 +408,11 @@ int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, | |||
336 | 408 | ||
337 | table->icm[i] = mlx4_alloc_icm(dev, chunk_size >> PAGE_SHIFT, | 409 | table->icm[i] = mlx4_alloc_icm(dev, chunk_size >> PAGE_SHIFT, |
338 | (use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) | | 410 | (use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) | |
339 | __GFP_NOWARN); | 411 | __GFP_NOWARN, use_coherent); |
340 | if (!table->icm[i]) | 412 | if (!table->icm[i]) |
341 | goto err; | 413 | goto err; |
342 | if (mlx4_MAP_ICM(dev, table->icm[i], virt + i * MLX4_TABLE_CHUNK_SIZE)) { | 414 | if (mlx4_MAP_ICM(dev, table->icm[i], virt + i * MLX4_TABLE_CHUNK_SIZE)) { |
343 | mlx4_free_icm(dev, table->icm[i]); | 415 | mlx4_free_icm(dev, table->icm[i], use_coherent); |
344 | table->icm[i] = NULL; | 416 | table->icm[i] = NULL; |
345 | goto err; | 417 | goto err; |
346 | } | 418 | } |
@@ -359,7 +431,7 @@ err: | |||
359 | if (table->icm[i]) { | 431 | if (table->icm[i]) { |
360 | mlx4_UNMAP_ICM(dev, virt + i * MLX4_TABLE_CHUNK_SIZE, | 432 | mlx4_UNMAP_ICM(dev, virt + i * MLX4_TABLE_CHUNK_SIZE, |
361 | MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); | 433 | MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); |
362 | mlx4_free_icm(dev, table->icm[i]); | 434 | mlx4_free_icm(dev, table->icm[i], use_coherent); |
363 | } | 435 | } |
364 | 436 | ||
365 | return -ENOMEM; | 437 | return -ENOMEM; |
@@ -373,7 +445,7 @@ void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table) | |||
373 | if (table->icm[i]) { | 445 | if (table->icm[i]) { |
374 | mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, | 446 | mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, |
375 | MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); | 447 | MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); |
376 | mlx4_free_icm(dev, table->icm[i]); | 448 | mlx4_free_icm(dev, table->icm[i], table->coherent); |
377 | } | 449 | } |
378 | 450 | ||
379 | kfree(table->icm); | 451 | kfree(table->icm); |
diff --git a/drivers/net/mlx4/icm.h b/drivers/net/mlx4/icm.h index bea223d879a..6c44edf3584 100644 --- a/drivers/net/mlx4/icm.h +++ b/drivers/net/mlx4/icm.h | |||
@@ -67,8 +67,9 @@ struct mlx4_icm_iter { | |||
67 | 67 | ||
68 | struct mlx4_dev; | 68 | struct mlx4_dev; |
69 | 69 | ||
70 | struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, gfp_t gfp_mask); | 70 | struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, |
71 | void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm); | 71 | gfp_t gfp_mask, int coherent); |
72 | void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent); | ||
72 | 73 | ||
73 | int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); | 74 | int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); |
74 | void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); | 75 | void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); |
@@ -78,11 +79,11 @@ void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, | |||
78 | int start, int end); | 79 | int start, int end); |
79 | int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, | 80 | int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, |
80 | u64 virt, int obj_size, int nobj, int reserved, | 81 | u64 virt, int obj_size, int nobj, int reserved, |
81 | int use_lowmem); | 82 | int use_lowmem, int use_coherent); |
82 | void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); | 83 | void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); |
83 | int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); | 84 | int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); |
84 | void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); | 85 | void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); |
85 | void *mlx4_table_find(struct mlx4_icm_table *table, int obj); | 86 | void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle); |
86 | int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, | 87 | int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, |
87 | int start, int end); | 88 | int start, int end); |
88 | void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, | 89 | void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, |
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 4dc9dc19b71..e029b8afbd3 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c | |||
@@ -61,7 +61,7 @@ MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0"); | |||
61 | 61 | ||
62 | #ifdef CONFIG_PCI_MSI | 62 | #ifdef CONFIG_PCI_MSI |
63 | 63 | ||
64 | static int msi_x; | 64 | static int msi_x = 1; |
65 | module_param(msi_x, int, 0444); | 65 | module_param(msi_x, int, 0444); |
66 | MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero"); | 66 | MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero"); |
67 | 67 | ||
@@ -85,7 +85,7 @@ static struct mlx4_profile default_profile = { | |||
85 | .num_mtt = 1 << 20, | 85 | .num_mtt = 1 << 20, |
86 | }; | 86 | }; |
87 | 87 | ||
88 | static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | 88 | static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) |
89 | { | 89 | { |
90 | int err; | 90 | int err; |
91 | int i; | 91 | int i; |
@@ -149,7 +149,8 @@ static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev | |||
149 | dev->caps.max_cqes = dev_cap->max_cq_sz - 1; | 149 | dev->caps.max_cqes = dev_cap->max_cq_sz - 1; |
150 | dev->caps.reserved_cqs = dev_cap->reserved_cqs; | 150 | dev->caps.reserved_cqs = dev_cap->reserved_cqs; |
151 | dev->caps.reserved_eqs = dev_cap->reserved_eqs; | 151 | dev->caps.reserved_eqs = dev_cap->reserved_eqs; |
152 | dev->caps.reserved_mtts = dev_cap->reserved_mtts; | 152 | dev->caps.reserved_mtts = DIV_ROUND_UP(dev_cap->reserved_mtts, |
153 | MLX4_MTT_ENTRY_PER_SEG); | ||
153 | dev->caps.reserved_mrws = dev_cap->reserved_mrws; | 154 | dev->caps.reserved_mrws = dev_cap->reserved_mrws; |
154 | dev->caps.reserved_uars = dev_cap->reserved_uars; | 155 | dev->caps.reserved_uars = dev_cap->reserved_uars; |
155 | dev->caps.reserved_pds = dev_cap->reserved_pds; | 156 | dev->caps.reserved_pds = dev_cap->reserved_pds; |
@@ -168,7 +169,7 @@ static int __devinit mlx4_load_fw(struct mlx4_dev *dev) | |||
168 | int err; | 169 | int err; |
169 | 170 | ||
170 | priv->fw.fw_icm = mlx4_alloc_icm(dev, priv->fw.fw_pages, | 171 | priv->fw.fw_icm = mlx4_alloc_icm(dev, priv->fw.fw_pages, |
171 | GFP_HIGHUSER | __GFP_NOWARN); | 172 | GFP_HIGHUSER | __GFP_NOWARN, 0); |
172 | if (!priv->fw.fw_icm) { | 173 | if (!priv->fw.fw_icm) { |
173 | mlx4_err(dev, "Couldn't allocate FW area, aborting.\n"); | 174 | mlx4_err(dev, "Couldn't allocate FW area, aborting.\n"); |
174 | return -ENOMEM; | 175 | return -ENOMEM; |
@@ -192,7 +193,7 @@ err_unmap_fa: | |||
192 | mlx4_UNMAP_FA(dev); | 193 | mlx4_UNMAP_FA(dev); |
193 | 194 | ||
194 | err_free: | 195 | err_free: |
195 | mlx4_free_icm(dev, priv->fw.fw_icm); | 196 | mlx4_free_icm(dev, priv->fw.fw_icm, 0); |
196 | return err; | 197 | return err; |
197 | } | 198 | } |
198 | 199 | ||
@@ -207,7 +208,7 @@ static int __devinit mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, | |||
207 | ((u64) (MLX4_CMPT_TYPE_QP * | 208 | ((u64) (MLX4_CMPT_TYPE_QP * |
208 | cmpt_entry_sz) << MLX4_CMPT_SHIFT), | 209 | cmpt_entry_sz) << MLX4_CMPT_SHIFT), |
209 | cmpt_entry_sz, dev->caps.num_qps, | 210 | cmpt_entry_sz, dev->caps.num_qps, |
210 | dev->caps.reserved_qps, 0); | 211 | dev->caps.reserved_qps, 0, 0); |
211 | if (err) | 212 | if (err) |
212 | goto err; | 213 | goto err; |
213 | 214 | ||
@@ -216,7 +217,7 @@ static int __devinit mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, | |||
216 | ((u64) (MLX4_CMPT_TYPE_SRQ * | 217 | ((u64) (MLX4_CMPT_TYPE_SRQ * |
217 | cmpt_entry_sz) << MLX4_CMPT_SHIFT), | 218 | cmpt_entry_sz) << MLX4_CMPT_SHIFT), |
218 | cmpt_entry_sz, dev->caps.num_srqs, | 219 | cmpt_entry_sz, dev->caps.num_srqs, |
219 | dev->caps.reserved_srqs, 0); | 220 | dev->caps.reserved_srqs, 0, 0); |
220 | if (err) | 221 | if (err) |
221 | goto err_qp; | 222 | goto err_qp; |
222 | 223 | ||
@@ -225,7 +226,7 @@ static int __devinit mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, | |||
225 | ((u64) (MLX4_CMPT_TYPE_CQ * | 226 | ((u64) (MLX4_CMPT_TYPE_CQ * |
226 | cmpt_entry_sz) << MLX4_CMPT_SHIFT), | 227 | cmpt_entry_sz) << MLX4_CMPT_SHIFT), |
227 | cmpt_entry_sz, dev->caps.num_cqs, | 228 | cmpt_entry_sz, dev->caps.num_cqs, |
228 | dev->caps.reserved_cqs, 0); | 229 | dev->caps.reserved_cqs, 0, 0); |
229 | if (err) | 230 | if (err) |
230 | goto err_srq; | 231 | goto err_srq; |
231 | 232 | ||
@@ -236,7 +237,7 @@ static int __devinit mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, | |||
236 | cmpt_entry_sz, | 237 | cmpt_entry_sz, |
237 | roundup_pow_of_two(MLX4_NUM_EQ + | 238 | roundup_pow_of_two(MLX4_NUM_EQ + |
238 | dev->caps.reserved_eqs), | 239 | dev->caps.reserved_eqs), |
239 | MLX4_NUM_EQ + dev->caps.reserved_eqs, 0); | 240 | MLX4_NUM_EQ + dev->caps.reserved_eqs, 0, 0); |
240 | if (err) | 241 | if (err) |
241 | goto err_cq; | 242 | goto err_cq; |
242 | 243 | ||
@@ -255,10 +256,8 @@ err: | |||
255 | return err; | 256 | return err; |
256 | } | 257 | } |
257 | 258 | ||
258 | static int __devinit mlx4_init_icm(struct mlx4_dev *dev, | 259 | static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, |
259 | struct mlx4_dev_cap *dev_cap, | 260 | struct mlx4_init_hca_param *init_hca, u64 icm_size) |
260 | struct mlx4_init_hca_param *init_hca, | ||
261 | u64 icm_size) | ||
262 | { | 261 | { |
263 | struct mlx4_priv *priv = mlx4_priv(dev); | 262 | struct mlx4_priv *priv = mlx4_priv(dev); |
264 | u64 aux_pages; | 263 | u64 aux_pages; |
@@ -275,7 +274,7 @@ static int __devinit mlx4_init_icm(struct mlx4_dev *dev, | |||
275 | (unsigned long long) aux_pages << 2); | 274 | (unsigned long long) aux_pages << 2); |
276 | 275 | ||
277 | priv->fw.aux_icm = mlx4_alloc_icm(dev, aux_pages, | 276 | priv->fw.aux_icm = mlx4_alloc_icm(dev, aux_pages, |
278 | GFP_HIGHUSER | __GFP_NOWARN); | 277 | GFP_HIGHUSER | __GFP_NOWARN, 0); |
279 | if (!priv->fw.aux_icm) { | 278 | if (!priv->fw.aux_icm) { |
280 | mlx4_err(dev, "Couldn't allocate aux memory, aborting.\n"); | 279 | mlx4_err(dev, "Couldn't allocate aux memory, aborting.\n"); |
281 | return -ENOMEM; | 280 | return -ENOMEM; |
@@ -299,11 +298,22 @@ static int __devinit mlx4_init_icm(struct mlx4_dev *dev, | |||
299 | goto err_unmap_cmpt; | 298 | goto err_unmap_cmpt; |
300 | } | 299 | } |
301 | 300 | ||
301 | /* | ||
302 | * Reserved MTT entries must be aligned up to a cacheline | ||
303 | * boundary, since the FW will write to them, while the driver | ||
304 | * writes to all other MTT entries. (The variable | ||
305 | * dev->caps.mtt_entry_sz below is really the MTT segment | ||
306 | * size, not the raw entry size) | ||
307 | */ | ||
308 | dev->caps.reserved_mtts = | ||
309 | ALIGN(dev->caps.reserved_mtts * dev->caps.mtt_entry_sz, | ||
310 | dma_get_cache_alignment()) / dev->caps.mtt_entry_sz; | ||
311 | |||
302 | err = mlx4_init_icm_table(dev, &priv->mr_table.mtt_table, | 312 | err = mlx4_init_icm_table(dev, &priv->mr_table.mtt_table, |
303 | init_hca->mtt_base, | 313 | init_hca->mtt_base, |
304 | dev->caps.mtt_entry_sz, | 314 | dev->caps.mtt_entry_sz, |
305 | dev->caps.num_mtt_segs, | 315 | dev->caps.num_mtt_segs, |
306 | dev->caps.reserved_mtts, 1); | 316 | dev->caps.reserved_mtts, 1, 0); |
307 | if (err) { | 317 | if (err) { |
308 | mlx4_err(dev, "Failed to map MTT context memory, aborting.\n"); | 318 | mlx4_err(dev, "Failed to map MTT context memory, aborting.\n"); |
309 | goto err_unmap_eq; | 319 | goto err_unmap_eq; |
@@ -313,7 +323,7 @@ static int __devinit mlx4_init_icm(struct mlx4_dev *dev, | |||
313 | init_hca->dmpt_base, | 323 | init_hca->dmpt_base, |
314 | dev_cap->dmpt_entry_sz, | 324 | dev_cap->dmpt_entry_sz, |
315 | dev->caps.num_mpts, | 325 | dev->caps.num_mpts, |
316 | dev->caps.reserved_mrws, 1); | 326 | dev->caps.reserved_mrws, 1, 1); |
317 | if (err) { | 327 | if (err) { |
318 | mlx4_err(dev, "Failed to map dMPT context memory, aborting.\n"); | 328 | mlx4_err(dev, "Failed to map dMPT context memory, aborting.\n"); |
319 | goto err_unmap_mtt; | 329 | goto err_unmap_mtt; |
@@ -323,7 +333,7 @@ static int __devinit mlx4_init_icm(struct mlx4_dev *dev, | |||
323 | init_hca->qpc_base, | 333 | init_hca->qpc_base, |
324 | dev_cap->qpc_entry_sz, | 334 | dev_cap->qpc_entry_sz, |
325 | dev->caps.num_qps, | 335 | dev->caps.num_qps, |
326 | dev->caps.reserved_qps, 0); | 336 | dev->caps.reserved_qps, 0, 0); |
327 | if (err) { | 337 | if (err) { |
328 | mlx4_err(dev, "Failed to map QP context memory, aborting.\n"); | 338 | mlx4_err(dev, "Failed to map QP context memory, aborting.\n"); |
329 | goto err_unmap_dmpt; | 339 | goto err_unmap_dmpt; |
@@ -333,7 +343,7 @@ static int __devinit mlx4_init_icm(struct mlx4_dev *dev, | |||
333 | init_hca->auxc_base, | 343 | init_hca->auxc_base, |
334 | dev_cap->aux_entry_sz, | 344 | dev_cap->aux_entry_sz, |
335 | dev->caps.num_qps, | 345 | dev->caps.num_qps, |
336 | dev->caps.reserved_qps, 0); | 346 | dev->caps.reserved_qps, 0, 0); |
337 | if (err) { | 347 | if (err) { |
338 | mlx4_err(dev, "Failed to map AUXC context memory, aborting.\n"); | 348 | mlx4_err(dev, "Failed to map AUXC context memory, aborting.\n"); |
339 | goto err_unmap_qp; | 349 | goto err_unmap_qp; |
@@ -343,7 +353,7 @@ static int __devinit mlx4_init_icm(struct mlx4_dev *dev, | |||
343 | init_hca->altc_base, | 353 | init_hca->altc_base, |
344 | dev_cap->altc_entry_sz, | 354 | dev_cap->altc_entry_sz, |
345 | dev->caps.num_qps, | 355 | dev->caps.num_qps, |
346 | dev->caps.reserved_qps, 0); | 356 | dev->caps.reserved_qps, 0, 0); |
347 | if (err) { | 357 | if (err) { |
348 | mlx4_err(dev, "Failed to map ALTC context memory, aborting.\n"); | 358 | mlx4_err(dev, "Failed to map ALTC context memory, aborting.\n"); |
349 | goto err_unmap_auxc; | 359 | goto err_unmap_auxc; |
@@ -353,7 +363,7 @@ static int __devinit mlx4_init_icm(struct mlx4_dev *dev, | |||
353 | init_hca->rdmarc_base, | 363 | init_hca->rdmarc_base, |
354 | dev_cap->rdmarc_entry_sz << priv->qp_table.rdmarc_shift, | 364 | dev_cap->rdmarc_entry_sz << priv->qp_table.rdmarc_shift, |
355 | dev->caps.num_qps, | 365 | dev->caps.num_qps, |
356 | dev->caps.reserved_qps, 0); | 366 | dev->caps.reserved_qps, 0, 0); |
357 | if (err) { | 367 | if (err) { |
358 | mlx4_err(dev, "Failed to map RDMARC context memory, aborting\n"); | 368 | mlx4_err(dev, "Failed to map RDMARC context memory, aborting\n"); |
359 | goto err_unmap_altc; | 369 | goto err_unmap_altc; |
@@ -363,7 +373,7 @@ static int __devinit mlx4_init_icm(struct mlx4_dev *dev, | |||
363 | init_hca->cqc_base, | 373 | init_hca->cqc_base, |
364 | dev_cap->cqc_entry_sz, | 374 | dev_cap->cqc_entry_sz, |
365 | dev->caps.num_cqs, | 375 | dev->caps.num_cqs, |
366 | dev->caps.reserved_cqs, 0); | 376 | dev->caps.reserved_cqs, 0, 0); |
367 | if (err) { | 377 | if (err) { |
368 | mlx4_err(dev, "Failed to map CQ context memory, aborting.\n"); | 378 | mlx4_err(dev, "Failed to map CQ context memory, aborting.\n"); |
369 | goto err_unmap_rdmarc; | 379 | goto err_unmap_rdmarc; |
@@ -373,7 +383,7 @@ static int __devinit mlx4_init_icm(struct mlx4_dev *dev, | |||
373 | init_hca->srqc_base, | 383 | init_hca->srqc_base, |
374 | dev_cap->srq_entry_sz, | 384 | dev_cap->srq_entry_sz, |
375 | dev->caps.num_srqs, | 385 | dev->caps.num_srqs, |
376 | dev->caps.reserved_srqs, 0); | 386 | dev->caps.reserved_srqs, 0, 0); |
377 | if (err) { | 387 | if (err) { |
378 | mlx4_err(dev, "Failed to map SRQ context memory, aborting.\n"); | 388 | mlx4_err(dev, "Failed to map SRQ context memory, aborting.\n"); |
379 | goto err_unmap_cq; | 389 | goto err_unmap_cq; |
@@ -388,7 +398,7 @@ static int __devinit mlx4_init_icm(struct mlx4_dev *dev, | |||
388 | init_hca->mc_base, MLX4_MGM_ENTRY_SIZE, | 398 | init_hca->mc_base, MLX4_MGM_ENTRY_SIZE, |
389 | dev->caps.num_mgms + dev->caps.num_amgms, | 399 | dev->caps.num_mgms + dev->caps.num_amgms, |
390 | dev->caps.num_mgms + dev->caps.num_amgms, | 400 | dev->caps.num_mgms + dev->caps.num_amgms, |
391 | 0); | 401 | 0, 0); |
392 | if (err) { | 402 | if (err) { |
393 | mlx4_err(dev, "Failed to map MCG context memory, aborting.\n"); | 403 | mlx4_err(dev, "Failed to map MCG context memory, aborting.\n"); |
394 | goto err_unmap_srq; | 404 | goto err_unmap_srq; |
@@ -433,7 +443,7 @@ err_unmap_aux: | |||
433 | mlx4_UNMAP_ICM_AUX(dev); | 443 | mlx4_UNMAP_ICM_AUX(dev); |
434 | 444 | ||
435 | err_free_aux: | 445 | err_free_aux: |
436 | mlx4_free_icm(dev, priv->fw.aux_icm); | 446 | mlx4_free_icm(dev, priv->fw.aux_icm, 0); |
437 | 447 | ||
438 | return err; | 448 | return err; |
439 | } | 449 | } |
@@ -458,7 +468,7 @@ static void mlx4_free_icms(struct mlx4_dev *dev) | |||
458 | mlx4_unmap_eq_icm(dev); | 468 | mlx4_unmap_eq_icm(dev); |
459 | 469 | ||
460 | mlx4_UNMAP_ICM_AUX(dev); | 470 | mlx4_UNMAP_ICM_AUX(dev); |
461 | mlx4_free_icm(dev, priv->fw.aux_icm); | 471 | mlx4_free_icm(dev, priv->fw.aux_icm, 0); |
462 | } | 472 | } |
463 | 473 | ||
464 | static void mlx4_close_hca(struct mlx4_dev *dev) | 474 | static void mlx4_close_hca(struct mlx4_dev *dev) |
@@ -466,10 +476,10 @@ static void mlx4_close_hca(struct mlx4_dev *dev) | |||
466 | mlx4_CLOSE_HCA(dev, 0); | 476 | mlx4_CLOSE_HCA(dev, 0); |
467 | mlx4_free_icms(dev); | 477 | mlx4_free_icms(dev); |
468 | mlx4_UNMAP_FA(dev); | 478 | mlx4_UNMAP_FA(dev); |
469 | mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm); | 479 | mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm, 0); |
470 | } | 480 | } |
471 | 481 | ||
472 | static int __devinit mlx4_init_hca(struct mlx4_dev *dev) | 482 | static int mlx4_init_hca(struct mlx4_dev *dev) |
473 | { | 483 | { |
474 | struct mlx4_priv *priv = mlx4_priv(dev); | 484 | struct mlx4_priv *priv = mlx4_priv(dev); |
475 | struct mlx4_adapter adapter; | 485 | struct mlx4_adapter adapter; |
@@ -524,8 +534,8 @@ static int __devinit mlx4_init_hca(struct mlx4_dev *dev) | |||
524 | } | 534 | } |
525 | 535 | ||
526 | priv->eq_table.inta_pin = adapter.inta_pin; | 536 | priv->eq_table.inta_pin = adapter.inta_pin; |
527 | priv->rev_id = adapter.revision_id; | 537 | dev->rev_id = adapter.revision_id; |
528 | memcpy(priv->board_id, adapter.board_id, sizeof priv->board_id); | 538 | memcpy(dev->board_id, adapter.board_id, sizeof dev->board_id); |
529 | 539 | ||
530 | return 0; | 540 | return 0; |
531 | 541 | ||
@@ -537,12 +547,12 @@ err_free_icm: | |||
537 | 547 | ||
538 | err_stop_fw: | 548 | err_stop_fw: |
539 | mlx4_UNMAP_FA(dev); | 549 | mlx4_UNMAP_FA(dev); |
540 | mlx4_free_icm(dev, priv->fw.fw_icm); | 550 | mlx4_free_icm(dev, priv->fw.fw_icm, 0); |
541 | 551 | ||
542 | return err; | 552 | return err; |
543 | } | 553 | } |
544 | 554 | ||
545 | static int __devinit mlx4_setup_hca(struct mlx4_dev *dev) | 555 | static int mlx4_setup_hca(struct mlx4_dev *dev) |
546 | { | 556 | { |
547 | struct mlx4_priv *priv = mlx4_priv(dev); | 557 | struct mlx4_priv *priv = mlx4_priv(dev); |
548 | int err; | 558 | int err; |
@@ -599,13 +609,17 @@ static int __devinit mlx4_setup_hca(struct mlx4_dev *dev) | |||
599 | 609 | ||
600 | err = mlx4_NOP(dev); | 610 | err = mlx4_NOP(dev); |
601 | if (err) { | 611 | if (err) { |
602 | mlx4_err(dev, "NOP command failed to generate interrupt " | 612 | if (dev->flags & MLX4_FLAG_MSI_X) { |
603 | "(IRQ %d), aborting.\n", | 613 | mlx4_warn(dev, "NOP command failed to generate MSI-X " |
604 | priv->eq_table.eq[MLX4_EQ_ASYNC].irq); | 614 | "interrupt IRQ %d).\n", |
605 | if (dev->flags & MLX4_FLAG_MSI_X) | 615 | priv->eq_table.eq[MLX4_EQ_ASYNC].irq); |
606 | mlx4_err(dev, "Try again with MSI-X disabled.\n"); | 616 | mlx4_warn(dev, "Trying again without MSI-X.\n"); |
607 | else | 617 | } else { |
618 | mlx4_err(dev, "NOP command failed to generate interrupt " | ||
619 | "(IRQ %d), aborting.\n", | ||
620 | priv->eq_table.eq[MLX4_EQ_ASYNC].irq); | ||
608 | mlx4_err(dev, "BIOS or ACPI interrupt routing problem?\n"); | 621 | mlx4_err(dev, "BIOS or ACPI interrupt routing problem?\n"); |
622 | } | ||
609 | 623 | ||
610 | goto err_cmd_poll; | 624 | goto err_cmd_poll; |
611 | } | 625 | } |
@@ -705,19 +719,12 @@ no_msi: | |||
705 | priv->eq_table.eq[i].irq = dev->pdev->irq; | 719 | priv->eq_table.eq[i].irq = dev->pdev->irq; |
706 | } | 720 | } |
707 | 721 | ||
708 | static int __devinit mlx4_init_one(struct pci_dev *pdev, | 722 | static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
709 | const struct pci_device_id *id) | ||
710 | { | 723 | { |
711 | static int mlx4_version_printed; | ||
712 | struct mlx4_priv *priv; | 724 | struct mlx4_priv *priv; |
713 | struct mlx4_dev *dev; | 725 | struct mlx4_dev *dev; |
714 | int err; | 726 | int err; |
715 | 727 | ||
716 | if (!mlx4_version_printed) { | ||
717 | printk(KERN_INFO "%s", mlx4_version); | ||
718 | ++mlx4_version_printed; | ||
719 | } | ||
720 | |||
721 | printk(KERN_INFO PFX "Initializing %s\n", | 728 | printk(KERN_INFO PFX "Initializing %s\n", |
722 | pci_name(pdev)); | 729 | pci_name(pdev)); |
723 | 730 | ||
@@ -803,8 +810,6 @@ static int __devinit mlx4_init_one(struct pci_dev *pdev, | |||
803 | goto err_free_dev; | 810 | goto err_free_dev; |
804 | } | 811 | } |
805 | 812 | ||
806 | mlx4_enable_msi_x(dev); | ||
807 | |||
808 | if (mlx4_cmd_init(dev)) { | 813 | if (mlx4_cmd_init(dev)) { |
809 | mlx4_err(dev, "Failed to init command interface, aborting.\n"); | 814 | mlx4_err(dev, "Failed to init command interface, aborting.\n"); |
810 | goto err_free_dev; | 815 | goto err_free_dev; |
@@ -814,7 +819,15 @@ static int __devinit mlx4_init_one(struct pci_dev *pdev, | |||
814 | if (err) | 819 | if (err) |
815 | goto err_cmd; | 820 | goto err_cmd; |
816 | 821 | ||
822 | mlx4_enable_msi_x(dev); | ||
823 | |||
817 | err = mlx4_setup_hca(dev); | 824 | err = mlx4_setup_hca(dev); |
825 | if (err == -EBUSY && (dev->flags & MLX4_FLAG_MSI_X)) { | ||
826 | dev->flags &= ~MLX4_FLAG_MSI_X; | ||
827 | pci_disable_msix(pdev); | ||
828 | err = mlx4_setup_hca(dev); | ||
829 | } | ||
830 | |||
818 | if (err) | 831 | if (err) |
819 | goto err_close; | 832 | goto err_close; |
820 | 833 | ||
@@ -838,15 +851,15 @@ err_cleanup: | |||
838 | mlx4_cleanup_uar_table(dev); | 851 | mlx4_cleanup_uar_table(dev); |
839 | 852 | ||
840 | err_close: | 853 | err_close: |
854 | if (dev->flags & MLX4_FLAG_MSI_X) | ||
855 | pci_disable_msix(pdev); | ||
856 | |||
841 | mlx4_close_hca(dev); | 857 | mlx4_close_hca(dev); |
842 | 858 | ||
843 | err_cmd: | 859 | err_cmd: |
844 | mlx4_cmd_cleanup(dev); | 860 | mlx4_cmd_cleanup(dev); |
845 | 861 | ||
846 | err_free_dev: | 862 | err_free_dev: |
847 | if (dev->flags & MLX4_FLAG_MSI_X) | ||
848 | pci_disable_msix(pdev); | ||
849 | |||
850 | kfree(priv); | 863 | kfree(priv); |
851 | 864 | ||
852 | err_release_bar2: | 865 | err_release_bar2: |
@@ -861,7 +874,20 @@ err_disable_pdev: | |||
861 | return err; | 874 | return err; |
862 | } | 875 | } |
863 | 876 | ||
864 | static void __devexit mlx4_remove_one(struct pci_dev *pdev) | 877 | static int __devinit mlx4_init_one(struct pci_dev *pdev, |
878 | const struct pci_device_id *id) | ||
879 | { | ||
880 | static int mlx4_version_printed; | ||
881 | |||
882 | if (!mlx4_version_printed) { | ||
883 | printk(KERN_INFO "%s", mlx4_version); | ||
884 | ++mlx4_version_printed; | ||
885 | } | ||
886 | |||
887 | return mlx4_init_one(pdev, id); | ||
888 | } | ||
889 | |||
890 | static void mlx4_remove_one(struct pci_dev *pdev) | ||
865 | { | 891 | { |
866 | struct mlx4_dev *dev = pci_get_drvdata(pdev); | 892 | struct mlx4_dev *dev = pci_get_drvdata(pdev); |
867 | struct mlx4_priv *priv = mlx4_priv(dev); | 893 | struct mlx4_priv *priv = mlx4_priv(dev); |
@@ -902,7 +928,7 @@ static void __devexit mlx4_remove_one(struct pci_dev *pdev) | |||
902 | int mlx4_restart_one(struct pci_dev *pdev) | 928 | int mlx4_restart_one(struct pci_dev *pdev) |
903 | { | 929 | { |
904 | mlx4_remove_one(pdev); | 930 | mlx4_remove_one(pdev); |
905 | return mlx4_init_one(pdev, NULL); | 931 | return __mlx4_init_one(pdev, NULL); |
906 | } | 932 | } |
907 | 933 | ||
908 | static struct pci_device_id mlx4_pci_table[] = { | 934 | static struct pci_device_id mlx4_pci_table[] = { |
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c index 672024a0ee7..a99e7729d33 100644 --- a/drivers/net/mlx4/mcg.c +++ b/drivers/net/mlx4/mcg.c | |||
@@ -359,7 +359,7 @@ out: | |||
359 | } | 359 | } |
360 | EXPORT_SYMBOL_GPL(mlx4_multicast_detach); | 360 | EXPORT_SYMBOL_GPL(mlx4_multicast_detach); |
361 | 361 | ||
362 | int __devinit mlx4_init_mcg_table(struct mlx4_dev *dev) | 362 | int mlx4_init_mcg_table(struct mlx4_dev *dev) |
363 | { | 363 | { |
364 | struct mlx4_priv *priv = mlx4_priv(dev); | 364 | struct mlx4_priv *priv = mlx4_priv(dev); |
365 | int err; | 365 | int err; |
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index be304a7c2c9..53a1cdddfc1 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h | |||
@@ -56,11 +56,7 @@ enum { | |||
56 | }; | 56 | }; |
57 | 57 | ||
58 | enum { | 58 | enum { |
59 | MLX4_BOARD_ID_LEN = 64 | 59 | MLX4_MGM_ENTRY_SIZE = 0x100, |
60 | }; | ||
61 | |||
62 | enum { | ||
63 | MLX4_MGM_ENTRY_SIZE = 0x40, | ||
64 | MLX4_QP_PER_MGM = 4 * (MLX4_MGM_ENTRY_SIZE / 16 - 2), | 60 | MLX4_QP_PER_MGM = 4 * (MLX4_MGM_ENTRY_SIZE / 16 - 2), |
65 | MLX4_MTT_ENTRY_PER_SEG = 8 | 61 | MLX4_MTT_ENTRY_PER_SEG = 8 |
66 | }; | 62 | }; |
@@ -133,6 +129,7 @@ struct mlx4_icm_table { | |||
133 | int num_obj; | 129 | int num_obj; |
134 | int obj_size; | 130 | int obj_size; |
135 | int lowmem; | 131 | int lowmem; |
132 | int coherent; | ||
136 | struct mutex mutex; | 133 | struct mutex mutex; |
137 | struct mlx4_icm **icm; | 134 | struct mlx4_icm **icm; |
138 | }; | 135 | }; |
@@ -277,9 +274,6 @@ struct mlx4_priv { | |||
277 | 274 | ||
278 | struct mlx4_uar driver_uar; | 275 | struct mlx4_uar driver_uar; |
279 | void __iomem *kar; | 276 | void __iomem *kar; |
280 | |||
281 | u32 rev_id; | ||
282 | char board_id[MLX4_BOARD_ID_LEN]; | ||
283 | }; | 277 | }; |
284 | 278 | ||
285 | static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) | 279 | static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) |
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c index 5b87183e62c..0c05a10bae3 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c | |||
@@ -68,6 +68,9 @@ struct mlx4_mpt_entry { | |||
68 | 68 | ||
69 | #define MLX4_MTT_FLAG_PRESENT 1 | 69 | #define MLX4_MTT_FLAG_PRESENT 1 |
70 | 70 | ||
71 | #define MLX4_MPT_STATUS_SW 0xF0 | ||
72 | #define MLX4_MPT_STATUS_HW 0x00 | ||
73 | |||
71 | static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order) | 74 | static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order) |
72 | { | 75 | { |
73 | int o; | 76 | int o; |
@@ -349,58 +352,57 @@ err_table: | |||
349 | } | 352 | } |
350 | EXPORT_SYMBOL_GPL(mlx4_mr_enable); | 353 | EXPORT_SYMBOL_GPL(mlx4_mr_enable); |
351 | 354 | ||
352 | static int mlx4_WRITE_MTT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, | 355 | static int mlx4_write_mtt_chunk(struct mlx4_dev *dev, struct mlx4_mtt *mtt, |
353 | int num_mtt) | 356 | int start_index, int npages, u64 *page_list) |
354 | { | 357 | { |
355 | return mlx4_cmd(dev, mailbox->dma, num_mtt, 0, MLX4_CMD_WRITE_MTT, | 358 | struct mlx4_priv *priv = mlx4_priv(dev); |
356 | MLX4_CMD_TIME_CLASS_B); | 359 | __be64 *mtts; |
360 | dma_addr_t dma_handle; | ||
361 | int i; | ||
362 | int s = start_index * sizeof (u64); | ||
363 | |||
364 | /* All MTTs must fit in the same page */ | ||
365 | if (start_index / (PAGE_SIZE / sizeof (u64)) != | ||
366 | (start_index + npages - 1) / (PAGE_SIZE / sizeof (u64))) | ||
367 | return -EINVAL; | ||
368 | |||
369 | if (start_index & (MLX4_MTT_ENTRY_PER_SEG - 1)) | ||
370 | return -EINVAL; | ||
371 | |||
372 | mtts = mlx4_table_find(&priv->mr_table.mtt_table, mtt->first_seg + | ||
373 | s / dev->caps.mtt_entry_sz, &dma_handle); | ||
374 | if (!mtts) | ||
375 | return -ENOMEM; | ||
376 | |||
377 | for (i = 0; i < npages; ++i) | ||
378 | mtts[i] = cpu_to_be64(page_list[i] | MLX4_MTT_FLAG_PRESENT); | ||
379 | |||
380 | dma_sync_single(&dev->pdev->dev, dma_handle, npages * sizeof (u64), DMA_TO_DEVICE); | ||
381 | |||
382 | return 0; | ||
357 | } | 383 | } |
358 | 384 | ||
359 | int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, | 385 | int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, |
360 | int start_index, int npages, u64 *page_list) | 386 | int start_index, int npages, u64 *page_list) |
361 | { | 387 | { |
362 | struct mlx4_cmd_mailbox *mailbox; | 388 | int chunk; |
363 | __be64 *mtt_entry; | 389 | int err; |
364 | int i; | ||
365 | int err = 0; | ||
366 | 390 | ||
367 | if (mtt->order < 0) | 391 | if (mtt->order < 0) |
368 | return -EINVAL; | 392 | return -EINVAL; |
369 | 393 | ||
370 | mailbox = mlx4_alloc_cmd_mailbox(dev); | ||
371 | if (IS_ERR(mailbox)) | ||
372 | return PTR_ERR(mailbox); | ||
373 | |||
374 | mtt_entry = mailbox->buf; | ||
375 | |||
376 | while (npages > 0) { | 394 | while (npages > 0) { |
377 | mtt_entry[0] = cpu_to_be64(mlx4_mtt_addr(dev, mtt) + start_index * 8); | 395 | chunk = min_t(int, PAGE_SIZE / sizeof(u64), npages); |
378 | mtt_entry[1] = 0; | 396 | err = mlx4_write_mtt_chunk(dev, mtt, start_index, chunk, page_list); |
379 | |||
380 | for (i = 0; i < npages && i < MLX4_MAILBOX_SIZE / 8 - 2; ++i) | ||
381 | mtt_entry[i + 2] = cpu_to_be64(page_list[i] | | ||
382 | MLX4_MTT_FLAG_PRESENT); | ||
383 | |||
384 | /* | ||
385 | * If we have an odd number of entries to write, add | ||
386 | * one more dummy entry for firmware efficiency. | ||
387 | */ | ||
388 | if (i & 1) | ||
389 | mtt_entry[i + 2] = 0; | ||
390 | |||
391 | err = mlx4_WRITE_MTT(dev, mailbox, (i + 1) & ~1); | ||
392 | if (err) | 397 | if (err) |
393 | goto out; | 398 | return err; |
394 | 399 | ||
395 | npages -= i; | 400 | npages -= chunk; |
396 | start_index += i; | 401 | start_index += chunk; |
397 | page_list += i; | 402 | page_list += chunk; |
398 | } | 403 | } |
399 | 404 | ||
400 | out: | 405 | return 0; |
401 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
402 | |||
403 | return err; | ||
404 | } | 406 | } |
405 | EXPORT_SYMBOL_GPL(mlx4_write_mtt); | 407 | EXPORT_SYMBOL_GPL(mlx4_write_mtt); |
406 | 408 | ||
@@ -428,7 +430,7 @@ int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, | |||
428 | } | 430 | } |
429 | EXPORT_SYMBOL_GPL(mlx4_buf_write_mtt); | 431 | EXPORT_SYMBOL_GPL(mlx4_buf_write_mtt); |
430 | 432 | ||
431 | int __devinit mlx4_init_mr_table(struct mlx4_dev *dev) | 433 | int mlx4_init_mr_table(struct mlx4_dev *dev) |
432 | { | 434 | { |
433 | struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; | 435 | struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; |
434 | int err; | 436 | int err; |
@@ -444,7 +446,7 @@ int __devinit mlx4_init_mr_table(struct mlx4_dev *dev) | |||
444 | goto err_buddy; | 446 | goto err_buddy; |
445 | 447 | ||
446 | if (dev->caps.reserved_mtts) { | 448 | if (dev->caps.reserved_mtts) { |
447 | if (mlx4_alloc_mtt_range(dev, ilog2(dev->caps.reserved_mtts)) == -1) { | 449 | if (mlx4_alloc_mtt_range(dev, fls(dev->caps.reserved_mtts - 1)) == -1) { |
448 | mlx4_warn(dev, "MTT table of order %d is too small.\n", | 450 | mlx4_warn(dev, "MTT table of order %d is too small.\n", |
449 | mr_table->mtt_buddy.max_order); | 451 | mr_table->mtt_buddy.max_order); |
450 | err = -ENOMEM; | 452 | err = -ENOMEM; |
@@ -470,3 +472,165 @@ void mlx4_cleanup_mr_table(struct mlx4_dev *dev) | |||
470 | mlx4_buddy_cleanup(&mr_table->mtt_buddy); | 472 | mlx4_buddy_cleanup(&mr_table->mtt_buddy); |
471 | mlx4_bitmap_cleanup(&mr_table->mpt_bitmap); | 473 | mlx4_bitmap_cleanup(&mr_table->mpt_bitmap); |
472 | } | 474 | } |
475 | |||
476 | static inline int mlx4_check_fmr(struct mlx4_fmr *fmr, u64 *page_list, | ||
477 | int npages, u64 iova) | ||
478 | { | ||
479 | int i, page_mask; | ||
480 | |||
481 | if (npages > fmr->max_pages) | ||
482 | return -EINVAL; | ||
483 | |||
484 | page_mask = (1 << fmr->page_shift) - 1; | ||
485 | |||
486 | /* We are getting page lists, so va must be page aligned. */ | ||
487 | if (iova & page_mask) | ||
488 | return -EINVAL; | ||
489 | |||
490 | /* Trust the user not to pass misaligned data in page_list */ | ||
491 | if (0) | ||
492 | for (i = 0; i < npages; ++i) { | ||
493 | if (page_list[i] & ~page_mask) | ||
494 | return -EINVAL; | ||
495 | } | ||
496 | |||
497 | if (fmr->maps >= fmr->max_maps) | ||
498 | return -EINVAL; | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | int mlx4_map_phys_fmr(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u64 *page_list, | ||
504 | int npages, u64 iova, u32 *lkey, u32 *rkey) | ||
505 | { | ||
506 | u32 key; | ||
507 | int i, err; | ||
508 | |||
509 | err = mlx4_check_fmr(fmr, page_list, npages, iova); | ||
510 | if (err) | ||
511 | return err; | ||
512 | |||
513 | ++fmr->maps; | ||
514 | |||
515 | key = key_to_hw_index(fmr->mr.key); | ||
516 | key += dev->caps.num_mpts; | ||
517 | *lkey = *rkey = fmr->mr.key = hw_index_to_key(key); | ||
518 | |||
519 | *(u8 *) fmr->mpt = MLX4_MPT_STATUS_SW; | ||
520 | |||
521 | /* Make sure MPT status is visible before writing MTT entries */ | ||
522 | wmb(); | ||
523 | |||
524 | for (i = 0; i < npages; ++i) | ||
525 | fmr->mtts[i] = cpu_to_be64(page_list[i] | MLX4_MTT_FLAG_PRESENT); | ||
526 | |||
527 | dma_sync_single(&dev->pdev->dev, fmr->dma_handle, | ||
528 | npages * sizeof(u64), DMA_TO_DEVICE); | ||
529 | |||
530 | fmr->mpt->key = cpu_to_be32(key); | ||
531 | fmr->mpt->lkey = cpu_to_be32(key); | ||
532 | fmr->mpt->length = cpu_to_be64(npages * (1ull << fmr->page_shift)); | ||
533 | fmr->mpt->start = cpu_to_be64(iova); | ||
534 | |||
535 | /* Make MTT entries are visible before setting MPT status */ | ||
536 | wmb(); | ||
537 | |||
538 | *(u8 *) fmr->mpt = MLX4_MPT_STATUS_HW; | ||
539 | |||
540 | /* Make sure MPT status is visible before consumer can use FMR */ | ||
541 | wmb(); | ||
542 | |||
543 | return 0; | ||
544 | } | ||
545 | EXPORT_SYMBOL_GPL(mlx4_map_phys_fmr); | ||
546 | |||
547 | int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages, | ||
548 | int max_maps, u8 page_shift, struct mlx4_fmr *fmr) | ||
549 | { | ||
550 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
551 | u64 mtt_seg; | ||
552 | int err = -ENOMEM; | ||
553 | |||
554 | if (page_shift < 12 || page_shift >= 32) | ||
555 | return -EINVAL; | ||
556 | |||
557 | /* All MTTs must fit in the same page */ | ||
558 | if (max_pages * sizeof *fmr->mtts > PAGE_SIZE) | ||
559 | return -EINVAL; | ||
560 | |||
561 | fmr->page_shift = page_shift; | ||
562 | fmr->max_pages = max_pages; | ||
563 | fmr->max_maps = max_maps; | ||
564 | fmr->maps = 0; | ||
565 | |||
566 | err = mlx4_mr_alloc(dev, pd, 0, 0, access, max_pages, | ||
567 | page_shift, &fmr->mr); | ||
568 | if (err) | ||
569 | return err; | ||
570 | |||
571 | mtt_seg = fmr->mr.mtt.first_seg * dev->caps.mtt_entry_sz; | ||
572 | |||
573 | fmr->mtts = mlx4_table_find(&priv->mr_table.mtt_table, | ||
574 | fmr->mr.mtt.first_seg, | ||
575 | &fmr->dma_handle); | ||
576 | if (!fmr->mtts) { | ||
577 | err = -ENOMEM; | ||
578 | goto err_free; | ||
579 | } | ||
580 | |||
581 | fmr->mpt = mlx4_table_find(&priv->mr_table.dmpt_table, | ||
582 | key_to_hw_index(fmr->mr.key), NULL); | ||
583 | if (!fmr->mpt) { | ||
584 | err = -ENOMEM; | ||
585 | goto err_free; | ||
586 | } | ||
587 | |||
588 | return 0; | ||
589 | |||
590 | err_free: | ||
591 | mlx4_mr_free(dev, &fmr->mr); | ||
592 | return err; | ||
593 | } | ||
594 | EXPORT_SYMBOL_GPL(mlx4_fmr_alloc); | ||
595 | |||
596 | int mlx4_fmr_enable(struct mlx4_dev *dev, struct mlx4_fmr *fmr) | ||
597 | { | ||
598 | return mlx4_mr_enable(dev, &fmr->mr); | ||
599 | } | ||
600 | EXPORT_SYMBOL_GPL(mlx4_fmr_enable); | ||
601 | |||
602 | void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr, | ||
603 | u32 *lkey, u32 *rkey) | ||
604 | { | ||
605 | u32 key; | ||
606 | |||
607 | if (!fmr->maps) | ||
608 | return; | ||
609 | |||
610 | key = key_to_hw_index(fmr->mr.key); | ||
611 | key &= dev->caps.num_mpts - 1; | ||
612 | *lkey = *rkey = fmr->mr.key = hw_index_to_key(key); | ||
613 | |||
614 | fmr->maps = 0; | ||
615 | |||
616 | *(u8 *) fmr->mpt = MLX4_MPT_STATUS_SW; | ||
617 | } | ||
618 | EXPORT_SYMBOL_GPL(mlx4_fmr_unmap); | ||
619 | |||
620 | int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr) | ||
621 | { | ||
622 | if (fmr->maps) | ||
623 | return -EBUSY; | ||
624 | |||
625 | fmr->mr.enabled = 0; | ||
626 | mlx4_mr_free(dev, &fmr->mr); | ||
627 | |||
628 | return 0; | ||
629 | } | ||
630 | EXPORT_SYMBOL_GPL(mlx4_fmr_free); | ||
631 | |||
632 | int mlx4_SYNC_TPT(struct mlx4_dev *dev) | ||
633 | { | ||
634 | return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_SYNC_TPT, 1000); | ||
635 | } | ||
636 | EXPORT_SYMBOL_GPL(mlx4_SYNC_TPT); | ||
diff --git a/drivers/net/mlx4/pd.c b/drivers/net/mlx4/pd.c index 23dea1ee775..3a93c5f0f7a 100644 --- a/drivers/net/mlx4/pd.c +++ b/drivers/net/mlx4/pd.c | |||
@@ -57,7 +57,7 @@ void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn) | |||
57 | } | 57 | } |
58 | EXPORT_SYMBOL_GPL(mlx4_pd_free); | 58 | EXPORT_SYMBOL_GPL(mlx4_pd_free); |
59 | 59 | ||
60 | int __devinit mlx4_init_pd_table(struct mlx4_dev *dev) | 60 | int mlx4_init_pd_table(struct mlx4_dev *dev) |
61 | { | 61 | { |
62 | struct mlx4_priv *priv = mlx4_priv(dev); | 62 | struct mlx4_priv *priv = mlx4_priv(dev); |
63 | 63 | ||
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c index 19b48c71cf7..cc4b1be1821 100644 --- a/drivers/net/mlx4/qp.c +++ b/drivers/net/mlx4/qp.c | |||
@@ -240,7 +240,8 @@ void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp) | |||
240 | mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); | 240 | mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); |
241 | mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); | 241 | mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); |
242 | 242 | ||
243 | mlx4_bitmap_free(&qp_table->bitmap, qp->qpn); | 243 | if (qp->qpn < dev->caps.sqp_start + 8) |
244 | mlx4_bitmap_free(&qp_table->bitmap, qp->qpn); | ||
244 | } | 245 | } |
245 | EXPORT_SYMBOL_GPL(mlx4_qp_free); | 246 | EXPORT_SYMBOL_GPL(mlx4_qp_free); |
246 | 247 | ||
@@ -250,7 +251,7 @@ static int mlx4_CONF_SPECIAL_QP(struct mlx4_dev *dev, u32 base_qpn) | |||
250 | MLX4_CMD_TIME_CLASS_B); | 251 | MLX4_CMD_TIME_CLASS_B); |
251 | } | 252 | } |
252 | 253 | ||
253 | int __devinit mlx4_init_qp_table(struct mlx4_dev *dev) | 254 | int mlx4_init_qp_table(struct mlx4_dev *dev) |
254 | { | 255 | { |
255 | struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; | 256 | struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; |
256 | int err; | 257 | int err; |
diff --git a/drivers/net/mlx4/srq.c b/drivers/net/mlx4/srq.c index b061c86d683..d23f46d692e 100644 --- a/drivers/net/mlx4/srq.c +++ b/drivers/net/mlx4/srq.c | |||
@@ -227,7 +227,7 @@ int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_waterm | |||
227 | err = mlx4_QUERY_SRQ(dev, mailbox, srq->srqn); | 227 | err = mlx4_QUERY_SRQ(dev, mailbox, srq->srqn); |
228 | if (err) | 228 | if (err) |
229 | goto err_out; | 229 | goto err_out; |
230 | *limit_watermark = srq_context->limit_watermark; | 230 | *limit_watermark = be16_to_cpu(srq_context->limit_watermark); |
231 | 231 | ||
232 | err_out: | 232 | err_out: |
233 | mlx4_free_cmd_mailbox(dev, mailbox); | 233 | mlx4_free_cmd_mailbox(dev, mailbox); |
@@ -235,7 +235,7 @@ err_out: | |||
235 | } | 235 | } |
236 | EXPORT_SYMBOL_GPL(mlx4_srq_query); | 236 | EXPORT_SYMBOL_GPL(mlx4_srq_query); |
237 | 237 | ||
238 | int __devinit mlx4_init_srq_table(struct mlx4_dev *dev) | 238 | int mlx4_init_srq_table(struct mlx4_dev *dev) |
239 | { | 239 | { |
240 | struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; | 240 | struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; |
241 | int err; | 241 | int err; |