.. | .. |
---|
55 | 55 | #define TASKLET_MAX_TIME 2 |
---|
56 | 56 | #define TASKLET_MAX_TIME_JIFFIES msecs_to_jiffies(TASKLET_MAX_TIME) |
---|
57 | 57 | |
---|
58 | | -void mlx4_cq_tasklet_cb(unsigned long data) |
---|
| 58 | +void mlx4_cq_tasklet_cb(struct tasklet_struct *t) |
---|
59 | 59 | { |
---|
60 | 60 | unsigned long flags; |
---|
61 | 61 | unsigned long end = jiffies + TASKLET_MAX_TIME_JIFFIES; |
---|
62 | | - struct mlx4_eq_tasklet *ctx = (struct mlx4_eq_tasklet *)data; |
---|
| 62 | + struct mlx4_eq_tasklet *ctx = from_tasklet(ctx, t, task); |
---|
63 | 63 | struct mlx4_cq *mcq, *temp; |
---|
64 | 64 | |
---|
65 | 65 | spin_lock_irqsave(&ctx->lock, flags); |
---|
.. | .. |
---|
144 | 144 | } |
---|
145 | 145 | |
---|
146 | 146 | static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, |
---|
147 | | - int cq_num) |
---|
| 147 | + int cq_num, u8 opmod) |
---|
148 | 148 | { |
---|
149 | | - return mlx4_cmd(dev, mailbox->dma, cq_num, 0, |
---|
| 149 | + return mlx4_cmd(dev, mailbox->dma, cq_num, opmod, |
---|
150 | 150 | MLX4_CMD_SW2HW_CQ, MLX4_CMD_TIME_CLASS_A, |
---|
151 | 151 | MLX4_CMD_WRAPPED); |
---|
152 | 152 | } |
---|
.. | .. |
---|
287 | 287 | __mlx4_cq_free_icm(dev, cqn); |
---|
288 | 288 | } |
---|
289 | 289 | |
---|
| 290 | +static int mlx4_init_user_cqes(void *buf, int entries, int cqe_size) |
---|
| 291 | +{ |
---|
| 292 | + int entries_per_copy = PAGE_SIZE / cqe_size; |
---|
| 293 | + void *init_ents; |
---|
| 294 | + int err = 0; |
---|
| 295 | + int i; |
---|
| 296 | + |
---|
| 297 | + init_ents = kmalloc(PAGE_SIZE, GFP_KERNEL); |
---|
| 298 | + if (!init_ents) |
---|
| 299 | + return -ENOMEM; |
---|
| 300 | + |
---|
| 301 | + /* Populate a list of CQ entries to reduce the number of |
---|
| 302 | + * copy_to_user calls. 0xcc is the initialization value |
---|
| 303 | + * required by the FW. |
---|
| 304 | + */ |
---|
| 305 | + memset(init_ents, 0xcc, PAGE_SIZE); |
---|
| 306 | + |
---|
| 307 | + if (entries_per_copy < entries) { |
---|
| 308 | + for (i = 0; i < entries / entries_per_copy; i++) { |
---|
| 309 | + err = copy_to_user((void __user *)buf, init_ents, PAGE_SIZE) ? |
---|
| 310 | + -EFAULT : 0; |
---|
| 311 | + if (err) |
---|
| 312 | + goto out; |
---|
| 313 | + |
---|
| 314 | + buf += PAGE_SIZE; |
---|
| 315 | + } |
---|
| 316 | + } else { |
---|
| 317 | + err = copy_to_user((void __user *)buf, init_ents, entries * cqe_size) ? |
---|
| 318 | + -EFAULT : 0; |
---|
| 319 | + } |
---|
| 320 | + |
---|
| 321 | +out: |
---|
| 322 | + kfree(init_ents); |
---|
| 323 | + |
---|
| 324 | + return err; |
---|
| 325 | +} |
---|
| 326 | + |
---|
| 327 | +static void mlx4_init_kernel_cqes(struct mlx4_buf *buf, |
---|
| 328 | + int entries, |
---|
| 329 | + int cqe_size) |
---|
| 330 | +{ |
---|
| 331 | + int i; |
---|
| 332 | + |
---|
| 333 | + if (buf->nbufs == 1) |
---|
| 334 | + memset(buf->direct.buf, 0xcc, entries * cqe_size); |
---|
| 335 | + else |
---|
| 336 | + for (i = 0; i < buf->npages; i++) |
---|
| 337 | + memset(buf->page_list[i].buf, 0xcc, |
---|
| 338 | + 1UL << buf->page_shift); |
---|
| 339 | +} |
---|
| 340 | + |
---|
290 | 341 | int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, |
---|
291 | 342 | struct mlx4_mtt *mtt, struct mlx4_uar *uar, u64 db_rec, |
---|
292 | 343 | struct mlx4_cq *cq, unsigned vector, int collapsed, |
---|
293 | | - int timestamp_en) |
---|
| 344 | + int timestamp_en, void *buf_addr, bool user_cq) |
---|
294 | 345 | { |
---|
| 346 | + bool sw_cq_init = dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SW_CQ_INIT; |
---|
295 | 347 | struct mlx4_priv *priv = mlx4_priv(dev); |
---|
296 | 348 | struct mlx4_cq_table *cq_table = &priv->cq_table; |
---|
297 | 349 | struct mlx4_cmd_mailbox *mailbox; |
---|
.. | .. |
---|
336 | 388 | cq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff); |
---|
337 | 389 | cq_context->db_rec_addr = cpu_to_be64(db_rec); |
---|
338 | 390 | |
---|
339 | | - err = mlx4_SW2HW_CQ(dev, mailbox, cq->cqn); |
---|
| 391 | + if (sw_cq_init) { |
---|
| 392 | + if (user_cq) { |
---|
| 393 | + err = mlx4_init_user_cqes(buf_addr, nent, |
---|
| 394 | + dev->caps.cqe_size); |
---|
| 395 | + if (err) |
---|
| 396 | + sw_cq_init = false; |
---|
| 397 | + } else { |
---|
| 398 | + mlx4_init_kernel_cqes(buf_addr, nent, |
---|
| 399 | + dev->caps.cqe_size); |
---|
| 400 | + } |
---|
| 401 | + } |
---|
| 402 | + |
---|
| 403 | + err = mlx4_SW2HW_CQ(dev, mailbox, cq->cqn, sw_cq_init); |
---|
| 404 | + |
---|
340 | 405 | mlx4_free_cmd_mailbox(dev, mailbox); |
---|
341 | 406 | if (err) |
---|
342 | 407 | goto err_radix; |
---|