aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/be2iscsi/be_iscsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/be2iscsi/be_iscsi.c')
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c136
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(&params, 0, sizeof(struct beiscsi_offload_params)); 414 memset(&params, 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 */
462static void beiscsi_free_ep(struct iscsi_endpoint *ep) 530static 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
521free_ep: 587free_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 */
549static int beiscsi_close_conn(struct iscsi_endpoint *ep, int flag) 615static 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}