| .. | .. |
|---|
| 65 | 65 | #include <linux/in6.h> |
|---|
| 66 | 66 | |
|---|
| 67 | 67 | #include <rdma/ib_verbs.h> |
|---|
| 68 | | -#include <rdma/ib_fmr_pool.h> |
|---|
| 69 | 68 | #include <rdma/rdma_cm.h> |
|---|
| 70 | 69 | |
|---|
| 71 | 70 | #define DRV_NAME "iser" |
|---|
| .. | .. |
|---|
| 96 | 95 | #define iser_err(fmt, arg...) \ |
|---|
| 97 | 96 | pr_err(PFX "%s: " fmt, __func__ , ## arg) |
|---|
| 98 | 97 | |
|---|
| 99 | | -#define SHIFT_4K 12 |
|---|
| 100 | | -#define SIZE_4K (1ULL << SHIFT_4K) |
|---|
| 101 | | -#define MASK_4K (~(SIZE_4K-1)) |
|---|
| 102 | | - |
|---|
| 103 | 98 | /* Default support is 512KB I/O size */ |
|---|
| 104 | 99 | #define ISER_DEF_MAX_SECTORS 1024 |
|---|
| 105 | | -#define ISCSI_ISER_DEF_SG_TABLESIZE ((ISER_DEF_MAX_SECTORS * 512) >> SHIFT_4K) |
|---|
| 106 | | -/* Maximum support is 8MB I/O size */ |
|---|
| 107 | | -#define ISCSI_ISER_MAX_SG_TABLESIZE ((16384 * 512) >> SHIFT_4K) |
|---|
| 100 | +#define ISCSI_ISER_DEF_SG_TABLESIZE \ |
|---|
| 101 | + ((ISER_DEF_MAX_SECTORS * SECTOR_SIZE) >> ilog2(SZ_4K)) |
|---|
| 102 | +/* Maximum support is 16MB I/O size */ |
|---|
| 103 | +#define ISCSI_ISER_MAX_SG_TABLESIZE ((32768 * SECTOR_SIZE) >> ilog2(SZ_4K)) |
|---|
| 108 | 104 | |
|---|
| 109 | 105 | #define ISER_DEF_XMIT_CMDS_DEFAULT 512 |
|---|
| 110 | 106 | #if ISCSI_DEF_XMIT_CMDS_MAX > ISER_DEF_XMIT_CMDS_DEFAULT |
|---|
| .. | .. |
|---|
| 225 | 221 | ISCSI_TX_DATAOUT |
|---|
| 226 | 222 | }; |
|---|
| 227 | 223 | |
|---|
| 228 | | -/* Maximum number of work requests per task: |
|---|
| 229 | | - * Data memory region local invalidate + fast registration |
|---|
| 230 | | - * Protection memory region local invalidate + fast registration |
|---|
| 231 | | - * Signature memory region local invalidate + fast registration |
|---|
| 232 | | - * PDU send |
|---|
| 233 | | - */ |
|---|
| 234 | | -#define ISER_MAX_WRS 7 |
|---|
| 235 | | - |
|---|
| 236 | 224 | /** |
|---|
| 237 | 225 | * struct iser_tx_desc - iSER TX descriptor |
|---|
| 238 | 226 | * |
|---|
| 239 | 227 | * @iser_header: iser header |
|---|
| 240 | 228 | * @iscsi_header: iscsi header |
|---|
| 241 | 229 | * @type: command/control/dataout |
|---|
| 242 | | - * @dam_addr: header buffer dma_address |
|---|
| 230 | + * @dma_addr: header buffer dma_address |
|---|
| 243 | 231 | * @tx_sg: sg[0] points to iser/iscsi headers |
|---|
| 244 | 232 | * sg[1] optionally points to either of immediate data |
|---|
| 245 | 233 | * unsolicited data-out or control |
|---|
| 246 | 234 | * @num_sge: number sges used on this TX task |
|---|
| 235 | + * @cqe: completion handler |
|---|
| 247 | 236 | * @mapped: Is the task header mapped |
|---|
| 248 | | - * @wr_idx: Current WR index |
|---|
| 249 | | - * @wrs: Array of WRs per task |
|---|
| 250 | | - * @data_reg: Data buffer registration details |
|---|
| 251 | | - * @prot_reg: Protection buffer registration details |
|---|
| 252 | | - * @sig_attrs: Signature attributes |
|---|
| 237 | + * @reg_wr: registration WR |
|---|
| 238 | + * @send_wr: send WR |
|---|
| 239 | + * @inv_wr: invalidate WR |
|---|
| 253 | 240 | */ |
|---|
| 254 | 241 | struct iser_tx_desc { |
|---|
| 255 | 242 | struct iser_ctrl iser_header; |
|---|
| .. | .. |
|---|
| 260 | 247 | int num_sge; |
|---|
| 261 | 248 | struct ib_cqe cqe; |
|---|
| 262 | 249 | bool mapped; |
|---|
| 263 | | - u8 wr_idx; |
|---|
| 264 | | - union iser_wr { |
|---|
| 265 | | - struct ib_send_wr send; |
|---|
| 266 | | - struct ib_reg_wr fast_reg; |
|---|
| 267 | | - struct ib_sig_handover_wr sig; |
|---|
| 268 | | - } wrs[ISER_MAX_WRS]; |
|---|
| 269 | | - struct iser_mem_reg data_reg; |
|---|
| 270 | | - struct iser_mem_reg prot_reg; |
|---|
| 271 | | - struct ib_sig_attrs sig_attrs; |
|---|
| 250 | + struct ib_reg_wr reg_wr; |
|---|
| 251 | + struct ib_send_wr send_wr; |
|---|
| 252 | + struct ib_send_wr inv_wr; |
|---|
| 272 | 253 | }; |
|---|
| 273 | 254 | |
|---|
| 274 | 255 | #define ISER_RX_PAD_SIZE (256 - (ISER_RX_PAYLOAD_SIZE + \ |
|---|
| .. | .. |
|---|
| 282 | 263 | * @data: received data segment |
|---|
| 283 | 264 | * @dma_addr: receive buffer dma address |
|---|
| 284 | 265 | * @rx_sg: ib_sge of receive buffer |
|---|
| 266 | + * @cqe: completion handler |
|---|
| 285 | 267 | * @pad: for sense data TODO: Modify to maximum sense length supported |
|---|
| 286 | 268 | */ |
|---|
| 287 | 269 | struct iser_rx_desc { |
|---|
| .. | .. |
|---|
| 298 | 280 | * struct iser_login_desc - iSER login descriptor |
|---|
| 299 | 281 | * |
|---|
| 300 | 282 | * @req: pointer to login request buffer |
|---|
| 301 | | - * @resp: pointer to login response buffer |
|---|
| 283 | + * @rsp: pointer to login response buffer |
|---|
| 302 | 284 | * @req_dma: DMA address of login request buffer |
|---|
| 303 | | - * @rsp_dma: DMA address of login response buffer |
|---|
| 285 | + * @rsp_dma: DMA address of login response buffer |
|---|
| 304 | 286 | * @sge: IB sge for login post recv |
|---|
| 305 | 287 | * @cqe: completion handler |
|---|
| 306 | 288 | */ |
|---|
| .. | .. |
|---|
| 311 | 293 | u64 rsp_dma; |
|---|
| 312 | 294 | struct ib_sge sge; |
|---|
| 313 | 295 | struct ib_cqe cqe; |
|---|
| 314 | | -} __attribute__((packed)); |
|---|
| 296 | +} __packed; |
|---|
| 315 | 297 | |
|---|
| 316 | 298 | struct iser_conn; |
|---|
| 317 | 299 | struct ib_conn; |
|---|
| 318 | 300 | struct iscsi_iser_task; |
|---|
| 319 | | - |
|---|
| 320 | | -/** |
|---|
| 321 | | - * struct iser_comp - iSER completion context |
|---|
| 322 | | - * |
|---|
| 323 | | - * @cq: completion queue |
|---|
| 324 | | - * @active_qps: Number of active QPs attached |
|---|
| 325 | | - * to completion context |
|---|
| 326 | | - */ |
|---|
| 327 | | -struct iser_comp { |
|---|
| 328 | | - struct ib_cq *cq; |
|---|
| 329 | | - int active_qps; |
|---|
| 330 | | -}; |
|---|
| 331 | | - |
|---|
| 332 | | -/** |
|---|
| 333 | | - * struct iser_device - Memory registration operations |
|---|
| 334 | | - * per-device registration schemes |
|---|
| 335 | | - * |
|---|
| 336 | | - * @alloc_reg_res: Allocate registration resources |
|---|
| 337 | | - * @free_reg_res: Free registration resources |
|---|
| 338 | | - * @fast_reg_mem: Register memory buffers |
|---|
| 339 | | - * @unreg_mem: Un-register memory buffers |
|---|
| 340 | | - * @reg_desc_get: Get a registration descriptor for pool |
|---|
| 341 | | - * @reg_desc_put: Get a registration descriptor to pool |
|---|
| 342 | | - */ |
|---|
| 343 | | -struct iser_reg_ops { |
|---|
| 344 | | - int (*alloc_reg_res)(struct ib_conn *ib_conn, |
|---|
| 345 | | - unsigned cmds_max, |
|---|
| 346 | | - unsigned int size); |
|---|
| 347 | | - void (*free_reg_res)(struct ib_conn *ib_conn); |
|---|
| 348 | | - int (*reg_mem)(struct iscsi_iser_task *iser_task, |
|---|
| 349 | | - struct iser_data_buf *mem, |
|---|
| 350 | | - struct iser_reg_resources *rsc, |
|---|
| 351 | | - struct iser_mem_reg *reg); |
|---|
| 352 | | - void (*unreg_mem)(struct iscsi_iser_task *iser_task, |
|---|
| 353 | | - enum iser_data_dir cmd_dir); |
|---|
| 354 | | - struct iser_fr_desc * (*reg_desc_get)(struct ib_conn *ib_conn); |
|---|
| 355 | | - void (*reg_desc_put)(struct ib_conn *ib_conn, |
|---|
| 356 | | - struct iser_fr_desc *desc); |
|---|
| 357 | | -}; |
|---|
| 358 | 301 | |
|---|
| 359 | 302 | /** |
|---|
| 360 | 303 | * struct iser_device - iSER device handle |
|---|
| .. | .. |
|---|
| 365 | 308 | * @event_handler: IB events handle routine |
|---|
| 366 | 309 | * @ig_list: entry in devices list |
|---|
| 367 | 310 | * @refcount: Reference counter, dominated by open iser connections |
|---|
| 368 | | - * @comps_used: Number of completion contexts used, Min between online |
|---|
| 369 | | - * cpus and device max completion vectors |
|---|
| 370 | | - * @comps: Dinamically allocated array of completion handlers |
|---|
| 371 | | - * @reg_ops: Registration ops |
|---|
| 372 | | - * @remote_inv_sup: Remote invalidate is supported on this device |
|---|
| 373 | 311 | */ |
|---|
| 374 | 312 | struct iser_device { |
|---|
| 375 | 313 | struct ib_device *ib_device; |
|---|
| .. | .. |
|---|
| 377 | 315 | struct ib_event_handler event_handler; |
|---|
| 378 | 316 | struct list_head ig_list; |
|---|
| 379 | 317 | int refcount; |
|---|
| 380 | | - int comps_used; |
|---|
| 381 | | - struct iser_comp *comps; |
|---|
| 382 | | - const struct iser_reg_ops *reg_ops; |
|---|
| 383 | | - bool remote_inv_sup; |
|---|
| 384 | 318 | }; |
|---|
| 385 | 319 | |
|---|
| 386 | 320 | /** |
|---|
| 387 | | - * struct iser_reg_resources - Fast registration recources |
|---|
| 321 | + * struct iser_reg_resources - Fast registration resources |
|---|
| 388 | 322 | * |
|---|
| 389 | 323 | * @mr: memory region |
|---|
| 390 | | - * @fmr_pool: pool of fmrs |
|---|
| 391 | | - * @page_vec: fast reg page list used by fmr pool |
|---|
| 324 | + * @sig_mr: signature memory region |
|---|
| 392 | 325 | * @mr_valid: is mr valid indicator |
|---|
| 393 | 326 | */ |
|---|
| 394 | 327 | struct iser_reg_resources { |
|---|
| 395 | | - union { |
|---|
| 396 | | - struct ib_mr *mr; |
|---|
| 397 | | - struct ib_fmr_pool *fmr_pool; |
|---|
| 398 | | - }; |
|---|
| 399 | | - struct iser_page_vec *page_vec; |
|---|
| 328 | + struct ib_mr *mr; |
|---|
| 329 | + struct ib_mr *sig_mr; |
|---|
| 400 | 330 | u8 mr_valid:1; |
|---|
| 401 | | -}; |
|---|
| 402 | | - |
|---|
| 403 | | -/** |
|---|
| 404 | | - * struct iser_pi_context - Protection information context |
|---|
| 405 | | - * |
|---|
| 406 | | - * @rsc: protection buffer registration resources |
|---|
| 407 | | - * @sig_mr: signature enable memory region |
|---|
| 408 | | - * @sig_mr_valid: is sig_mr valid indicator |
|---|
| 409 | | - * @sig_protected: is region protected indicator |
|---|
| 410 | | - */ |
|---|
| 411 | | -struct iser_pi_context { |
|---|
| 412 | | - struct iser_reg_resources rsc; |
|---|
| 413 | | - struct ib_mr *sig_mr; |
|---|
| 414 | | - u8 sig_mr_valid:1; |
|---|
| 415 | | - u8 sig_protected:1; |
|---|
| 416 | 331 | }; |
|---|
| 417 | 332 | |
|---|
| 418 | 333 | /** |
|---|
| .. | .. |
|---|
| 420 | 335 | * |
|---|
| 421 | 336 | * @list: entry in connection fastreg pool |
|---|
| 422 | 337 | * @rsc: data buffer registration resources |
|---|
| 423 | | - * @pi_ctx: protection information context |
|---|
| 338 | + * @sig_protected: is region protected indicator |
|---|
| 339 | + * @all_list: first and last list members |
|---|
| 424 | 340 | */ |
|---|
| 425 | 341 | struct iser_fr_desc { |
|---|
| 426 | 342 | struct list_head list; |
|---|
| 427 | 343 | struct iser_reg_resources rsc; |
|---|
| 428 | | - struct iser_pi_context *pi_ctx; |
|---|
| 344 | + bool sig_protected; |
|---|
| 429 | 345 | struct list_head all_list; |
|---|
| 430 | 346 | }; |
|---|
| 431 | 347 | |
|---|
| 432 | 348 | /** |
|---|
| 433 | | - * struct iser_fr_pool: connection fast registration pool |
|---|
| 349 | + * struct iser_fr_pool - connection fast registration pool |
|---|
| 434 | 350 | * |
|---|
| 435 | 351 | * @list: list of fastreg descriptors |
|---|
| 436 | | - * @lock: protects fmr/fastreg pool |
|---|
| 352 | + * @lock: protects fastreg pool |
|---|
| 437 | 353 | * @size: size of the pool |
|---|
| 354 | + * @all_list: first and last list members |
|---|
| 438 | 355 | */ |
|---|
| 439 | 356 | struct iser_fr_pool { |
|---|
| 440 | 357 | struct list_head list; |
|---|
| .. | .. |
|---|
| 448 | 365 | * |
|---|
| 449 | 366 | * @cma_id: rdma_cm connection maneger handle |
|---|
| 450 | 367 | * @qp: Connection Queue-pair |
|---|
| 368 | + * @cq: Connection completion queue |
|---|
| 369 | + * @cq_size: The number of max outstanding completions |
|---|
| 451 | 370 | * @post_recv_buf_count: post receive counter |
|---|
| 452 | 371 | * @sig_count: send work request signal count |
|---|
| 453 | 372 | * @rx_wr: receive work request for batch posts |
|---|
| 454 | 373 | * @device: reference to iser device |
|---|
| 455 | | - * @comp: iser completion context |
|---|
| 456 | 374 | * @fr_pool: connection fast registration poool |
|---|
| 457 | 375 | * @pi_support: Indicate device T10-PI support |
|---|
| 376 | + * @reg_cqe: completion handler |
|---|
| 458 | 377 | */ |
|---|
| 459 | 378 | struct ib_conn { |
|---|
| 460 | 379 | struct rdma_cm_id *cma_id; |
|---|
| 461 | 380 | struct ib_qp *qp; |
|---|
| 381 | + struct ib_cq *cq; |
|---|
| 382 | + u32 cq_size; |
|---|
| 462 | 383 | int post_recv_buf_count; |
|---|
| 463 | 384 | u8 sig_count; |
|---|
| 464 | 385 | struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX]; |
|---|
| 465 | 386 | struct iser_device *device; |
|---|
| 466 | | - struct iser_comp *comp; |
|---|
| 467 | 387 | struct iser_fr_pool fr_pool; |
|---|
| 468 | 388 | bool pi_support; |
|---|
| 469 | 389 | struct ib_cqe reg_cqe; |
|---|
| .. | .. |
|---|
| 495 | 415 | * @num_rx_descs: number of rx descriptors |
|---|
| 496 | 416 | * @scsi_sg_tablesize: scsi host sg_tablesize |
|---|
| 497 | 417 | * @pages_per_mr: maximum pages available for registration |
|---|
| 418 | + * @snd_w_inv: connection uses remote invalidation |
|---|
| 498 | 419 | */ |
|---|
| 499 | 420 | struct iser_conn { |
|---|
| 500 | 421 | struct ib_conn ib_conn; |
|---|
| .. | .. |
|---|
| 546 | 467 | struct iser_data_buf prot[ISER_DIRS_NUM]; |
|---|
| 547 | 468 | }; |
|---|
| 548 | 469 | |
|---|
| 549 | | -struct iser_page_vec { |
|---|
| 550 | | - u64 *pages; |
|---|
| 551 | | - int npages; |
|---|
| 552 | | - struct ib_mr fake_mr; |
|---|
| 553 | | -}; |
|---|
| 554 | | - |
|---|
| 555 | 470 | /** |
|---|
| 556 | | - * struct iser_global: iSER global context |
|---|
| 471 | + * struct iser_global - iSER global context |
|---|
| 557 | 472 | * |
|---|
| 558 | 473 | * @device_list_mutex: protects device_list |
|---|
| 559 | 474 | * @device_list: iser devices global list |
|---|
| .. | .. |
|---|
| 575 | 490 | extern int iser_pi_guard; |
|---|
| 576 | 491 | extern unsigned int iser_max_sectors; |
|---|
| 577 | 492 | extern bool iser_always_reg; |
|---|
| 578 | | - |
|---|
| 579 | | -int iser_assign_reg_ops(struct iser_device *device); |
|---|
| 580 | 493 | |
|---|
| 581 | 494 | int iser_send_control(struct iscsi_conn *conn, |
|---|
| 582 | 495 | struct iscsi_task *task); |
|---|
| .. | .. |
|---|
| 619 | 532 | struct iser_data_buf *mem, |
|---|
| 620 | 533 | enum iser_data_dir cmd_dir); |
|---|
| 621 | 534 | |
|---|
| 622 | | -int iser_reg_rdma_mem(struct iscsi_iser_task *task, |
|---|
| 623 | | - enum iser_data_dir dir, |
|---|
| 624 | | - bool all_imm); |
|---|
| 625 | | -void iser_unreg_rdma_mem(struct iscsi_iser_task *task, |
|---|
| 626 | | - enum iser_data_dir dir); |
|---|
| 535 | +int iser_reg_mem_fastreg(struct iscsi_iser_task *task, |
|---|
| 536 | + enum iser_data_dir dir, |
|---|
| 537 | + bool all_imm); |
|---|
| 538 | +void iser_unreg_mem_fastreg(struct iscsi_iser_task *task, |
|---|
| 539 | + enum iser_data_dir dir); |
|---|
| 627 | 540 | |
|---|
| 628 | 541 | int iser_connect(struct iser_conn *iser_conn, |
|---|
| 629 | 542 | struct sockaddr *src_addr, |
|---|
| 630 | 543 | struct sockaddr *dst_addr, |
|---|
| 631 | 544 | int non_blocking); |
|---|
| 632 | | - |
|---|
| 633 | | -void iser_unreg_mem_fmr(struct iscsi_iser_task *iser_task, |
|---|
| 634 | | - enum iser_data_dir cmd_dir); |
|---|
| 635 | | -void iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task, |
|---|
| 636 | | - enum iser_data_dir cmd_dir); |
|---|
| 637 | 545 | |
|---|
| 638 | 546 | int iser_post_recvl(struct iser_conn *iser_conn); |
|---|
| 639 | 547 | int iser_post_recvm(struct iser_conn *iser_conn, int count); |
|---|
| .. | .. |
|---|
| 653 | 561 | struct iser_tx_desc *tx_desc); |
|---|
| 654 | 562 | int iser_alloc_rx_descriptors(struct iser_conn *iser_conn, |
|---|
| 655 | 563 | struct iscsi_session *session); |
|---|
| 656 | | -int iser_alloc_fmr_pool(struct ib_conn *ib_conn, |
|---|
| 657 | | - unsigned cmds_max, |
|---|
| 658 | | - unsigned int size); |
|---|
| 659 | | -void iser_free_fmr_pool(struct ib_conn *ib_conn); |
|---|
| 660 | 564 | int iser_alloc_fastreg_pool(struct ib_conn *ib_conn, |
|---|
| 661 | 565 | unsigned cmds_max, |
|---|
| 662 | 566 | unsigned int size); |
|---|
| 663 | 567 | void iser_free_fastreg_pool(struct ib_conn *ib_conn); |
|---|
| 664 | 568 | u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task, |
|---|
| 665 | 569 | enum iser_data_dir cmd_dir, sector_t *sector); |
|---|
| 666 | | -struct iser_fr_desc * |
|---|
| 667 | | -iser_reg_desc_get_fr(struct ib_conn *ib_conn); |
|---|
| 668 | | -void |
|---|
| 669 | | -iser_reg_desc_put_fr(struct ib_conn *ib_conn, |
|---|
| 670 | | - struct iser_fr_desc *desc); |
|---|
| 671 | | -struct iser_fr_desc * |
|---|
| 672 | | -iser_reg_desc_get_fmr(struct ib_conn *ib_conn); |
|---|
| 673 | | -void |
|---|
| 674 | | -iser_reg_desc_put_fmr(struct ib_conn *ib_conn, |
|---|
| 675 | | - struct iser_fr_desc *desc); |
|---|
| 676 | | - |
|---|
| 677 | | -static inline struct ib_send_wr * |
|---|
| 678 | | -iser_tx_next_wr(struct iser_tx_desc *tx_desc) |
|---|
| 679 | | -{ |
|---|
| 680 | | - struct ib_send_wr *cur_wr = &tx_desc->wrs[tx_desc->wr_idx].send; |
|---|
| 681 | | - struct ib_send_wr *last_wr; |
|---|
| 682 | | - |
|---|
| 683 | | - if (tx_desc->wr_idx) { |
|---|
| 684 | | - last_wr = &tx_desc->wrs[tx_desc->wr_idx - 1].send; |
|---|
| 685 | | - last_wr->next = cur_wr; |
|---|
| 686 | | - } |
|---|
| 687 | | - tx_desc->wr_idx++; |
|---|
| 688 | | - |
|---|
| 689 | | - return cur_wr; |
|---|
| 690 | | -} |
|---|
| 691 | 570 | |
|---|
| 692 | 571 | static inline struct iser_conn * |
|---|
| 693 | 572 | to_iser_conn(struct ib_conn *ib_conn) |
|---|