aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/be2iscsi/be_iscsi.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/scsi/be2iscsi/be_iscsi.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/scsi/be2iscsi/be_iscsi.c')
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c155
1 files changed, 116 insertions, 39 deletions
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index 2fd25442cfaf..c3928cb8b042 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
@@ -67,11 +67,11 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
67 cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; 67 cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn;
68 } 68 }
69 69
70 cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, 70 cls_session = iscsi_session_setup(&beiscsi_iscsi_transport,
71 shost, cmds_max, 71 shost, cmds_max,
72 sizeof(*beiscsi_sess), 72 sizeof(*beiscsi_sess),
73 sizeof(*io_task), 73 sizeof(*io_task),
74 initial_cmdsn, ISCSI_MAX_TARGET); 74 initial_cmdsn, ISCSI_MAX_TARGET);
75 if (!cls_session) 75 if (!cls_session)
76 return NULL; 76 return NULL;
77 sess = cls_session->dd_data; 77 sess = cls_session->dd_data;
@@ -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->ctrl, 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);
@@ -377,16 +409,13 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
377 struct beiscsi_conn *beiscsi_conn = conn->dd_data; 409 struct beiscsi_conn *beiscsi_conn = conn->dd_data;
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 struct iscsi_session *session = conn->session;
381 struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
382 struct beiscsi_hba *phba = iscsi_host_priv(shost);
383 412
413 SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_start\n");
384 memset(&params, 0, sizeof(struct beiscsi_offload_params)); 414 memset(&params, 0, sizeof(struct beiscsi_offload_params));
385 beiscsi_ep = beiscsi_conn->ep; 415 beiscsi_ep = beiscsi_conn->ep;
386 if (!beiscsi_ep) 416 if (!beiscsi_ep)
387 SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_start , no beiscsi_ep\n"); 417 SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_start , no beiscsi_ep\n");
388 418
389 free_mgmt_sgl_handle(phba, beiscsi_conn->plogin_sgl_handle);
390 beiscsi_conn->login_in_progress = 0; 419 beiscsi_conn->login_in_progress = 0;
391 beiscsi_set_params_for_offld(beiscsi_conn, &params); 420 beiscsi_set_params_for_offld(beiscsi_conn, &params);
392 beiscsi_offload_connection(beiscsi_conn, &params); 421 beiscsi_offload_connection(beiscsi_conn, &params);
@@ -426,8 +455,14 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
426{ 455{
427 struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; 456 struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
428 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;
429 int ret = -1; 463 int ret = -1;
430 464
465 SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn\n");
431 beiscsi_ep->ep_cid = beiscsi_get_cid(phba); 466 beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
432 if (beiscsi_ep->ep_cid == 0xFFFF) { 467 if (beiscsi_ep->ep_cid == 0xFFFF) {
433 SE_DEBUG(DBG_LVL_1, "No free cid available\n"); 468 SE_DEBUG(DBG_LVL_1, "No free cid available\n");
@@ -435,15 +470,44 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
435 } 470 }
436 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 ",
437 beiscsi_ep->ep_cid); 472 beiscsi_ep->ep_cid);
438 phba->ep_array[beiscsi_ep->ep_cid] = ep; 473 phba->ep_array[beiscsi_ep->ep_cid -
439 if (beiscsi_ep->ep_cid > 474 phba->fw_config.iscsi_cid_start] = ep;
440 (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)) {
441 SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); 477 SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
442 return ret; 478 return ret;
443 } 479 }
444 480
445 beiscsi_ep->cid_vld = 0; 481 beiscsi_ep->cid_vld = 0;
446 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_open_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;
447} 511}
448 512
449/** 513/**
@@ -463,14 +527,12 @@ static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
463 * beiscsi_free_ep - free endpoint 527 * beiscsi_free_ep - free endpoint
464 * @ep: pointer to iscsi endpoint structure 528 * @ep: pointer to iscsi endpoint structure
465 */ 529 */
466static void beiscsi_free_ep(struct iscsi_endpoint *ep) 530static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
467{ 531{
468 struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
469 struct beiscsi_hba *phba = beiscsi_ep->phba; 532 struct beiscsi_hba *phba = beiscsi_ep->phba;
470 533
471 beiscsi_put_cid(phba, beiscsi_ep->ep_cid); 534 beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
472 beiscsi_ep->phba = NULL; 535 beiscsi_ep->phba = NULL;
473 iscsi_destroy_endpoint(ep);
474} 536}
475 537
476/** 538/**
@@ -498,6 +560,13 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
498 SE_DEBUG(DBG_LVL_1, "shost is NULL \n"); 560 SE_DEBUG(DBG_LVL_1, "shost is NULL \n");
499 return ERR_PTR(ret); 561 return ERR_PTR(ret);
500 } 562 }
563
564 if (phba->state != BE_ADAPTER_UP) {
565 ret = -EBUSY;
566 SE_DEBUG(DBG_LVL_1, "The Adapter state is Not UP \n");
567 return ERR_PTR(ret);
568 }
569
501 ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint)); 570 ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint));
502 if (!ep) { 571 if (!ep) {
503 ret = -ENOMEM; 572 ret = -ENOMEM;
@@ -506,9 +575,9 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
506 575
507 beiscsi_ep = ep->dd_data; 576 beiscsi_ep = ep->dd_data;
508 beiscsi_ep->phba = phba; 577 beiscsi_ep->phba = phba;
509 578 beiscsi_ep->openiscsi_ep = ep;
510 if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) { 579 if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) {
511 SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); 580 SE_DEBUG(DBG_LVL_1, "Failed in beiscsi_open_conn \n");
512 ret = -ENOMEM; 581 ret = -ENOMEM;
513 goto free_ep; 582 goto free_ep;
514 } 583 }
@@ -516,7 +585,7 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
516 return ep; 585 return ep;
517 586
518free_ep: 587free_ep:
519 beiscsi_free_ep(ep); 588 beiscsi_free_ep(beiscsi_ep);
520 return ERR_PTR(ret); 589 return ERR_PTR(ret);
521} 590}
522 591
@@ -543,20 +612,22 @@ int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
543 * @ep: The iscsi endpoint 612 * @ep: The iscsi endpoint
544 * @flag: The type of connection closure 613 * @flag: The type of connection closure
545 */ 614 */
546static int beiscsi_close_conn(struct iscsi_endpoint *ep, int flag) 615static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag)
547{ 616{
548 int ret = 0; 617 int ret = 0;
549 struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; 618 unsigned int tag;
550 struct beiscsi_hba *phba = beiscsi_ep->phba; 619 struct beiscsi_hba *phba = beiscsi_ep->phba;
551 620
552 if (MGMT_STATUS_SUCCESS != 621 tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag);
553 mgmt_upload_connection(phba, beiscsi_ep->ep_cid, 622 if (!tag) {
554 CONNECTION_UPLOAD_GRACEFUL)) {
555 SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x", 623 SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x",
556 beiscsi_ep->ep_cid); 624 beiscsi_ep->ep_cid);
557 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);
558 } 630 }
559
560 return ret; 631 return ret;
561} 632}
562 633
@@ -571,19 +642,17 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
571 struct beiscsi_conn *beiscsi_conn; 642 struct beiscsi_conn *beiscsi_conn;
572 struct beiscsi_endpoint *beiscsi_ep; 643 struct beiscsi_endpoint *beiscsi_ep;
573 struct beiscsi_hba *phba; 644 struct beiscsi_hba *phba;
574 int flag = 0;
575 645
576 beiscsi_ep = ep->dd_data; 646 beiscsi_ep = ep->dd_data;
577 phba = beiscsi_ep->phba; 647 phba = beiscsi_ep->phba;
578 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);
579 650
580 if (beiscsi_ep->conn) { 651 if (beiscsi_ep->conn) {
581 beiscsi_conn = beiscsi_ep->conn; 652 beiscsi_conn = beiscsi_ep->conn;
582 iscsi_suspend_queue(beiscsi_conn->conn); 653 iscsi_suspend_queue(beiscsi_conn->conn);
583 beiscsi_close_conn(ep, flag);
584 } 654 }
585 655
586 beiscsi_free_ep(ep);
587} 656}
588 657
589/** 658/**
@@ -616,23 +685,31 @@ void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
616 struct iscsi_session *session = conn->session; 685 struct iscsi_session *session = conn->session;
617 struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session); 686 struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
618 struct beiscsi_hba *phba = iscsi_host_priv(shost); 687 struct beiscsi_hba *phba = iscsi_host_priv(shost);
619 unsigned int status; 688 unsigned int tag;
620 unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; 689 unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
621 690
622 SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop\n");
623 beiscsi_ep = beiscsi_conn->ep; 691 beiscsi_ep = beiscsi_conn->ep;
624 if (!beiscsi_ep) { 692 if (!beiscsi_ep) {
625 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");
626 return; 694 return;
627 } 695 }
628 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,
629 beiscsi_ep->ep_cid, 1, 699 beiscsi_ep->ep_cid, 1,
630 savecfg_flag); 700 savecfg_flag);
631 if (status != MGMT_STATUS_SUCCESS) { 701 if (!tag) {
632 SE_DEBUG(DBG_LVL_1, 702 SE_DEBUG(DBG_LVL_1,
633 "mgmt_invalidate_connection Failed for cid=%d \n", 703 "mgmt_invalidate_connection Failed for cid=%d \n",
634 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);
635 } 709 }
710 beiscsi_close_conn(beiscsi_ep, CONNECTION_UPLOAD_GRACEFUL);
711 beiscsi_free_ep(beiscsi_ep);
712 iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
636 beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); 713 beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
637 iscsi_conn_stop(cls_conn, flag); 714 iscsi_conn_stop(cls_conn, flag);
638} 715}