diff options
Diffstat (limited to 'drivers/scsi/be2iscsi/be_iscsi.c')
-rw-r--r-- | drivers/scsi/be2iscsi/be_iscsi.c | 136 |
1 files changed, 105 insertions, 31 deletions
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index d587b0362f18..29a3aaf35f9f 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * Copyright (C) 2005 - 2009 ServerEngines | 2 | * Copyright (C) 2005 - 2010 ServerEngines |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -101,6 +101,7 @@ void beiscsi_session_destroy(struct iscsi_cls_session *cls_session) | |||
101 | struct iscsi_session *sess = cls_session->dd_data; | 101 | struct iscsi_session *sess = cls_session->dd_data; |
102 | struct beiscsi_session *beiscsi_sess = sess->dd_data; | 102 | struct beiscsi_session *beiscsi_sess = sess->dd_data; |
103 | 103 | ||
104 | SE_DEBUG(DBG_LVL_8, "In beiscsi_session_destroy\n"); | ||
104 | pci_pool_destroy(beiscsi_sess->bhs_pool); | 105 | pci_pool_destroy(beiscsi_sess->bhs_pool); |
105 | iscsi_session_teardown(cls_session); | 106 | iscsi_session_teardown(cls_session); |
106 | } | 107 | } |
@@ -224,6 +225,7 @@ int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, | |||
224 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | 225 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; |
225 | int len = 0; | 226 | int len = 0; |
226 | 227 | ||
228 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_param, param= %d\n", param); | ||
227 | beiscsi_ep = beiscsi_conn->ep; | 229 | beiscsi_ep = beiscsi_conn->ep; |
228 | if (!beiscsi_ep) { | 230 | if (!beiscsi_ep) { |
229 | SE_DEBUG(DBG_LVL_1, | 231 | SE_DEBUG(DBG_LVL_1, |
@@ -254,6 +256,7 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
254 | struct iscsi_session *session = conn->session; | 256 | struct iscsi_session *session = conn->session; |
255 | int ret; | 257 | int ret; |
256 | 258 | ||
259 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_set_param, param= %d\n", param); | ||
257 | ret = iscsi_set_param(cls_conn, param, buf, buflen); | 260 | ret = iscsi_set_param(cls_conn, param, buf, buflen); |
258 | if (ret) | 261 | if (ret) |
259 | return ret; | 262 | return ret; |
@@ -271,8 +274,8 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
271 | conn->max_recv_dlength = 65536; | 274 | conn->max_recv_dlength = 65536; |
272 | break; | 275 | break; |
273 | case ISCSI_PARAM_MAX_BURST: | 276 | case ISCSI_PARAM_MAX_BURST: |
274 | if (session->first_burst > 262144) | 277 | if (session->max_burst > 262144) |
275 | session->first_burst = 262144; | 278 | session->max_burst = 262144; |
276 | break; | 279 | break; |
277 | default: | 280 | default: |
278 | return 0; | 281 | return 0; |
@@ -293,12 +296,41 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, | |||
293 | enum iscsi_host_param param, char *buf) | 296 | enum iscsi_host_param param, char *buf) |
294 | { | 297 | { |
295 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); | 298 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); |
299 | struct be_cmd_resp_get_mac_addr *resp; | ||
300 | struct be_mcc_wrb *wrb; | ||
301 | unsigned int tag, wrb_num; | ||
296 | int len = 0; | 302 | int len = 0; |
303 | unsigned short status, extd_status; | ||
304 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
297 | 305 | ||
306 | SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); | ||
298 | switch (param) { | 307 | switch (param) { |
299 | case ISCSI_HOST_PARAM_HWADDRESS: | 308 | case ISCSI_HOST_PARAM_HWADDRESS: |
300 | be_cmd_get_mac_addr(phba, phba->mac_address); | 309 | tag = be_cmd_get_mac_addr(phba); |
301 | len = sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); | 310 | if (!tag) { |
311 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed \n"); | ||
312 | return -1; | ||
313 | } else | ||
314 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
315 | phba->ctrl.mcc_numtag[tag]); | ||
316 | |||
317 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
318 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
319 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
320 | if (status || extd_status) { | ||
321 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" | ||
322 | " status = %d extd_status = %d \n", | ||
323 | status, extd_status); | ||
324 | free_mcc_tag(&phba->ctrl, tag); | ||
325 | return -1; | ||
326 | } else { | ||
327 | wrb = queue_get_wrb(mccq, wrb_num); | ||
328 | free_mcc_tag(&phba->ctrl, tag); | ||
329 | resp = embedded_payload(wrb); | ||
330 | memcpy(phba->mac_address, resp->mac_address, ETH_ALEN); | ||
331 | len = sysfs_format_mac(buf, phba->mac_address, | ||
332 | ETH_ALEN); | ||
333 | } | ||
302 | break; | 334 | break; |
303 | default: | 335 | default: |
304 | return iscsi_host_get_param(shost, param, buf); | 336 | return iscsi_host_get_param(shost, param, buf); |
@@ -378,6 +410,7 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
378 | struct beiscsi_endpoint *beiscsi_ep; | 410 | struct beiscsi_endpoint *beiscsi_ep; |
379 | struct beiscsi_offload_params params; | 411 | struct beiscsi_offload_params params; |
380 | 412 | ||
413 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_start\n"); | ||
381 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); | 414 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); |
382 | beiscsi_ep = beiscsi_conn->ep; | 415 | beiscsi_ep = beiscsi_conn->ep; |
383 | if (!beiscsi_ep) | 416 | if (!beiscsi_ep) |
@@ -422,8 +455,14 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, | |||
422 | { | 455 | { |
423 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | 456 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; |
424 | struct beiscsi_hba *phba = beiscsi_ep->phba; | 457 | struct beiscsi_hba *phba = beiscsi_ep->phba; |
458 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
459 | struct be_mcc_wrb *wrb; | ||
460 | struct tcp_connect_and_offload_out *ptcpcnct_out; | ||
461 | unsigned short status, extd_status; | ||
462 | unsigned int tag, wrb_num; | ||
425 | int ret = -1; | 463 | int ret = -1; |
426 | 464 | ||
465 | SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn\n"); | ||
427 | beiscsi_ep->ep_cid = beiscsi_get_cid(phba); | 466 | beiscsi_ep->ep_cid = beiscsi_get_cid(phba); |
428 | if (beiscsi_ep->ep_cid == 0xFFFF) { | 467 | if (beiscsi_ep->ep_cid == 0xFFFF) { |
429 | SE_DEBUG(DBG_LVL_1, "No free cid available\n"); | 468 | SE_DEBUG(DBG_LVL_1, "No free cid available\n"); |
@@ -431,15 +470,44 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, | |||
431 | } | 470 | } |
432 | SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d ", | 471 | SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d ", |
433 | beiscsi_ep->ep_cid); | 472 | beiscsi_ep->ep_cid); |
434 | phba->ep_array[beiscsi_ep->ep_cid] = ep; | 473 | phba->ep_array[beiscsi_ep->ep_cid - |
435 | if (beiscsi_ep->ep_cid > | 474 | phba->fw_config.iscsi_cid_start] = ep; |
436 | (phba->fw_config.iscsi_cid_start + phba->params.cxns_per_ctrl)) { | 475 | if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start + |
476 | phba->params.cxns_per_ctrl * 2)) { | ||
437 | SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); | 477 | SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); |
438 | return ret; | 478 | return ret; |
439 | } | 479 | } |
440 | 480 | ||
441 | beiscsi_ep->cid_vld = 0; | 481 | beiscsi_ep->cid_vld = 0; |
442 | return mgmt_open_connection(phba, dst_addr, beiscsi_ep); | 482 | tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep); |
483 | if (!tag) { | ||
484 | SE_DEBUG(DBG_LVL_1, | ||
485 | "mgmt_invalidate_connection Failed for cid=%d \n", | ||
486 | beiscsi_ep->ep_cid); | ||
487 | } else { | ||
488 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
489 | phba->ctrl.mcc_numtag[tag]); | ||
490 | } | ||
491 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
492 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
493 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
494 | if (status || extd_status) { | ||
495 | SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed" | ||
496 | " status = %d extd_status = %d \n", | ||
497 | status, extd_status); | ||
498 | free_mcc_tag(&phba->ctrl, tag); | ||
499 | return -1; | ||
500 | } else { | ||
501 | wrb = queue_get_wrb(mccq, wrb_num); | ||
502 | free_mcc_tag(&phba->ctrl, tag); | ||
503 | |||
504 | ptcpcnct_out = embedded_payload(wrb); | ||
505 | beiscsi_ep = ep->dd_data; | ||
506 | beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle; | ||
507 | beiscsi_ep->cid_vld = 1; | ||
508 | SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n"); | ||
509 | } | ||
510 | return 0; | ||
443 | } | 511 | } |
444 | 512 | ||
445 | /** | 513 | /** |
@@ -459,14 +527,12 @@ static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) | |||
459 | * beiscsi_free_ep - free endpoint | 527 | * beiscsi_free_ep - free endpoint |
460 | * @ep: pointer to iscsi endpoint structure | 528 | * @ep: pointer to iscsi endpoint structure |
461 | */ | 529 | */ |
462 | static void beiscsi_free_ep(struct iscsi_endpoint *ep) | 530 | static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) |
463 | { | 531 | { |
464 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | ||
465 | struct beiscsi_hba *phba = beiscsi_ep->phba; | 532 | struct beiscsi_hba *phba = beiscsi_ep->phba; |
466 | 533 | ||
467 | beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | 534 | beiscsi_put_cid(phba, beiscsi_ep->ep_cid); |
468 | beiscsi_ep->phba = NULL; | 535 | beiscsi_ep->phba = NULL; |
469 | iscsi_destroy_endpoint(ep); | ||
470 | } | 536 | } |
471 | 537 | ||
472 | /** | 538 | /** |
@@ -495,9 +561,9 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, | |||
495 | return ERR_PTR(ret); | 561 | return ERR_PTR(ret); |
496 | } | 562 | } |
497 | 563 | ||
498 | if (phba->state) { | 564 | if (phba->state != BE_ADAPTER_UP) { |
499 | ret = -EBUSY; | 565 | ret = -EBUSY; |
500 | SE_DEBUG(DBG_LVL_1, "The Adapet state is Not UP \n"); | 566 | SE_DEBUG(DBG_LVL_1, "The Adapter state is Not UP \n"); |
501 | return ERR_PTR(ret); | 567 | return ERR_PTR(ret); |
502 | } | 568 | } |
503 | 569 | ||
@@ -509,9 +575,9 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, | |||
509 | 575 | ||
510 | beiscsi_ep = ep->dd_data; | 576 | beiscsi_ep = ep->dd_data; |
511 | beiscsi_ep->phba = phba; | 577 | beiscsi_ep->phba = phba; |
512 | 578 | beiscsi_ep->openiscsi_ep = ep; | |
513 | if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) { | 579 | if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) { |
514 | SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); | 580 | SE_DEBUG(DBG_LVL_1, "Failed in beiscsi_open_conn \n"); |
515 | ret = -ENOMEM; | 581 | ret = -ENOMEM; |
516 | goto free_ep; | 582 | goto free_ep; |
517 | } | 583 | } |
@@ -519,7 +585,7 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, | |||
519 | return ep; | 585 | return ep; |
520 | 586 | ||
521 | free_ep: | 587 | free_ep: |
522 | beiscsi_free_ep(ep); | 588 | beiscsi_free_ep(beiscsi_ep); |
523 | return ERR_PTR(ret); | 589 | return ERR_PTR(ret); |
524 | } | 590 | } |
525 | 591 | ||
@@ -546,20 +612,22 @@ int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) | |||
546 | * @ep: The iscsi endpoint | 612 | * @ep: The iscsi endpoint |
547 | * @flag: The type of connection closure | 613 | * @flag: The type of connection closure |
548 | */ | 614 | */ |
549 | static int beiscsi_close_conn(struct iscsi_endpoint *ep, int flag) | 615 | static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag) |
550 | { | 616 | { |
551 | int ret = 0; | 617 | int ret = 0; |
552 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | 618 | unsigned int tag; |
553 | struct beiscsi_hba *phba = beiscsi_ep->phba; | 619 | struct beiscsi_hba *phba = beiscsi_ep->phba; |
554 | 620 | ||
555 | if (MGMT_STATUS_SUCCESS != | 621 | tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag); |
556 | mgmt_upload_connection(phba, beiscsi_ep->ep_cid, | 622 | if (!tag) { |
557 | CONNECTION_UPLOAD_GRACEFUL)) { | ||
558 | SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x", | 623 | SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x", |
559 | beiscsi_ep->ep_cid); | 624 | beiscsi_ep->ep_cid); |
560 | ret = -1; | 625 | ret = -1; |
626 | } else { | ||
627 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
628 | phba->ctrl.mcc_numtag[tag]); | ||
629 | free_mcc_tag(&phba->ctrl, tag); | ||
561 | } | 630 | } |
562 | |||
563 | return ret; | 631 | return ret; |
564 | } | 632 | } |
565 | 633 | ||
@@ -574,19 +642,17 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) | |||
574 | struct beiscsi_conn *beiscsi_conn; | 642 | struct beiscsi_conn *beiscsi_conn; |
575 | struct beiscsi_endpoint *beiscsi_ep; | 643 | struct beiscsi_endpoint *beiscsi_ep; |
576 | struct beiscsi_hba *phba; | 644 | struct beiscsi_hba *phba; |
577 | int flag = 0; | ||
578 | 645 | ||
579 | beiscsi_ep = ep->dd_data; | 646 | beiscsi_ep = ep->dd_data; |
580 | phba = beiscsi_ep->phba; | 647 | phba = beiscsi_ep->phba; |
581 | SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect\n"); | 648 | SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect for ep_cid = %d\n", |
649 | beiscsi_ep->ep_cid); | ||
582 | 650 | ||
583 | if (beiscsi_ep->conn) { | 651 | if (beiscsi_ep->conn) { |
584 | beiscsi_conn = beiscsi_ep->conn; | 652 | beiscsi_conn = beiscsi_ep->conn; |
585 | iscsi_suspend_queue(beiscsi_conn->conn); | 653 | iscsi_suspend_queue(beiscsi_conn->conn); |
586 | beiscsi_close_conn(ep, flag); | ||
587 | } | 654 | } |
588 | 655 | ||
589 | beiscsi_free_ep(ep); | ||
590 | } | 656 | } |
591 | 657 | ||
592 | /** | 658 | /** |
@@ -619,23 +685,31 @@ void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) | |||
619 | struct iscsi_session *session = conn->session; | 685 | struct iscsi_session *session = conn->session; |
620 | struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session); | 686 | struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session); |
621 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 687 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
622 | unsigned int status; | 688 | unsigned int tag; |
623 | unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; | 689 | unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; |
624 | 690 | ||
625 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop\n"); | ||
626 | beiscsi_ep = beiscsi_conn->ep; | 691 | beiscsi_ep = beiscsi_conn->ep; |
627 | if (!beiscsi_ep) { | 692 | if (!beiscsi_ep) { |
628 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n"); | 693 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n"); |
629 | return; | 694 | return; |
630 | } | 695 | } |
631 | status = mgmt_invalidate_connection(phba, beiscsi_ep, | 696 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop ep_cid = %d\n", |
697 | beiscsi_ep->ep_cid); | ||
698 | tag = mgmt_invalidate_connection(phba, beiscsi_ep, | ||
632 | beiscsi_ep->ep_cid, 1, | 699 | beiscsi_ep->ep_cid, 1, |
633 | savecfg_flag); | 700 | savecfg_flag); |
634 | if (status != MGMT_STATUS_SUCCESS) { | 701 | if (!tag) { |
635 | SE_DEBUG(DBG_LVL_1, | 702 | SE_DEBUG(DBG_LVL_1, |
636 | "mgmt_invalidate_connection Failed for cid=%d \n", | 703 | "mgmt_invalidate_connection Failed for cid=%d \n", |
637 | beiscsi_ep->ep_cid); | 704 | beiscsi_ep->ep_cid); |
705 | } else { | ||
706 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
707 | phba->ctrl.mcc_numtag[tag]); | ||
708 | free_mcc_tag(&phba->ctrl, tag); | ||
638 | } | 709 | } |
710 | beiscsi_close_conn(beiscsi_ep, CONNECTION_UPLOAD_GRACEFUL); | ||
711 | beiscsi_free_ep(beiscsi_ep); | ||
712 | iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); | ||
639 | beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); | 713 | beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); |
640 | iscsi_conn_stop(cls_conn, flag); | 714 | iscsi_conn_stop(cls_conn, flag); |
641 | } | 715 | } |