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.c493
1 files changed, 457 insertions, 36 deletions
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index 33c8f09c7ac1..43f35034585d 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -23,6 +23,8 @@
23#include <scsi/scsi_cmnd.h> 23#include <scsi/scsi_cmnd.h>
24#include <scsi/scsi_device.h> 24#include <scsi/scsi_device.h>
25#include <scsi/scsi_host.h> 25#include <scsi/scsi_host.h>
26#include <scsi/scsi_netlink.h>
27#include <net/netlink.h>
26#include <scsi/scsi.h> 28#include <scsi/scsi.h>
27 29
28#include "be_iscsi.h" 30#include "be_iscsi.h"
@@ -207,6 +209,301 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
207 return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid); 209 return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid);
208} 210}
209 211
212static int beiscsi_create_ipv4_iface(struct beiscsi_hba *phba)
213{
214 if (phba->ipv4_iface)
215 return 0;
216
217 phba->ipv4_iface = iscsi_create_iface(phba->shost,
218 &beiscsi_iscsi_transport,
219 ISCSI_IFACE_TYPE_IPV4,
220 0, 0);
221 if (!phba->ipv4_iface) {
222 shost_printk(KERN_ERR, phba->shost, "Could not "
223 "create default IPv4 address.\n");
224 return -ENODEV;
225 }
226
227 return 0;
228}
229
230static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba)
231{
232 if (phba->ipv6_iface)
233 return 0;
234
235 phba->ipv6_iface = iscsi_create_iface(phba->shost,
236 &beiscsi_iscsi_transport,
237 ISCSI_IFACE_TYPE_IPV6,
238 0, 0);
239 if (!phba->ipv6_iface) {
240 shost_printk(KERN_ERR, phba->shost, "Could not "
241 "create default IPv6 address.\n");
242 return -ENODEV;
243 }
244
245 return 0;
246}
247
248void beiscsi_create_def_ifaces(struct beiscsi_hba *phba)
249{
250 struct be_cmd_get_if_info_resp if_info;
251
252 if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info))
253 beiscsi_create_ipv4_iface(phba);
254
255 if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info))
256 beiscsi_create_ipv6_iface(phba);
257}
258
259void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba)
260{
261 if (phba->ipv6_iface)
262 iscsi_destroy_iface(phba->ipv6_iface);
263 if (phba->ipv4_iface)
264 iscsi_destroy_iface(phba->ipv4_iface);
265}
266
267static int
268beiscsi_set_static_ip(struct Scsi_Host *shost,
269 struct iscsi_iface_param_info *iface_param,
270 void *data, uint32_t dt_len)
271{
272 struct beiscsi_hba *phba = iscsi_host_priv(shost);
273 struct iscsi_iface_param_info *iface_ip = NULL;
274 struct iscsi_iface_param_info *iface_subnet = NULL;
275 struct nlattr *nla;
276 int ret;
277
278
279 switch (iface_param->param) {
280 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
281 nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
282 if (nla)
283 iface_ip = nla_data(nla);
284
285 nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
286 if (nla)
287 iface_subnet = nla_data(nla);
288 break;
289 case ISCSI_NET_PARAM_IPV4_ADDR:
290 iface_ip = iface_param;
291 nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
292 if (nla)
293 iface_subnet = nla_data(nla);
294 break;
295 case ISCSI_NET_PARAM_IPV4_SUBNET:
296 iface_subnet = iface_param;
297 nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
298 if (nla)
299 iface_ip = nla_data(nla);
300 break;
301 default:
302 shost_printk(KERN_ERR, shost, "Unsupported param %d\n",
303 iface_param->param);
304 }
305
306 if (!iface_ip || !iface_subnet) {
307 shost_printk(KERN_ERR, shost, "IP and Subnet Mask required\n");
308 return -EINVAL;
309 }
310
311 ret = mgmt_set_ip(phba, iface_ip, iface_subnet,
312 ISCSI_BOOTPROTO_STATIC);
313
314 return ret;
315}
316
317static int
318beiscsi_set_ipv4(struct Scsi_Host *shost,
319 struct iscsi_iface_param_info *iface_param,
320 void *data, uint32_t dt_len)
321{
322 struct beiscsi_hba *phba = iscsi_host_priv(shost);
323 int ret = 0;
324
325 /* Check the param */
326 switch (iface_param->param) {
327 case ISCSI_NET_PARAM_IPV4_GW:
328 ret = mgmt_set_gateway(phba, iface_param);
329 break;
330 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
331 if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)
332 ret = mgmt_set_ip(phba, iface_param,
333 NULL, ISCSI_BOOTPROTO_DHCP);
334 else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)
335 ret = beiscsi_set_static_ip(shost, iface_param,
336 data, dt_len);
337 else
338 shost_printk(KERN_ERR, shost, "Invalid BOOTPROTO: %d\n",
339 iface_param->value[0]);
340 break;
341 case ISCSI_NET_PARAM_IFACE_ENABLE:
342 if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
343 ret = beiscsi_create_ipv4_iface(phba);
344 else
345 iscsi_destroy_iface(phba->ipv4_iface);
346 break;
347 case ISCSI_NET_PARAM_IPV4_SUBNET:
348 case ISCSI_NET_PARAM_IPV4_ADDR:
349 ret = beiscsi_set_static_ip(shost, iface_param,
350 data, dt_len);
351 break;
352 default:
353 shost_printk(KERN_ERR, shost, "Param %d not supported\n",
354 iface_param->param);
355 }
356
357 return ret;
358}
359
360static int
361beiscsi_set_ipv6(struct Scsi_Host *shost,
362 struct iscsi_iface_param_info *iface_param,
363 void *data, uint32_t dt_len)
364{
365 struct beiscsi_hba *phba = iscsi_host_priv(shost);
366 int ret = 0;
367
368 switch (iface_param->param) {
369 case ISCSI_NET_PARAM_IFACE_ENABLE:
370 if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
371 ret = beiscsi_create_ipv6_iface(phba);
372 else {
373 iscsi_destroy_iface(phba->ipv6_iface);
374 ret = 0;
375 }
376 break;
377 case ISCSI_NET_PARAM_IPV6_ADDR:
378 ret = mgmt_set_ip(phba, iface_param, NULL,
379 ISCSI_BOOTPROTO_STATIC);
380 break;
381 default:
382 shost_printk(KERN_ERR, shost, "Param %d not supported\n",
383 iface_param->param);
384 }
385
386 return ret;
387}
388
389int be2iscsi_iface_set_param(struct Scsi_Host *shost,
390 void *data, uint32_t dt_len)
391{
392 struct iscsi_iface_param_info *iface_param = NULL;
393 struct nlattr *attrib;
394 uint32_t rm_len = dt_len;
395 int ret = 0 ;
396
397 nla_for_each_attr(attrib, data, dt_len, rm_len) {
398 iface_param = nla_data(attrib);
399
400 if (iface_param->param_type != ISCSI_NET_PARAM)
401 continue;
402
403 /*
404 * BE2ISCSI only supports 1 interface
405 */
406 if (iface_param->iface_num) {
407 shost_printk(KERN_ERR, shost, "Invalid iface_num %d."
408 "Only iface_num 0 is supported.\n",
409 iface_param->iface_num);
410 return -EINVAL;
411 }
412
413 switch (iface_param->iface_type) {
414 case ISCSI_IFACE_TYPE_IPV4:
415 ret = beiscsi_set_ipv4(shost, iface_param,
416 data, dt_len);
417 break;
418 case ISCSI_IFACE_TYPE_IPV6:
419 ret = beiscsi_set_ipv6(shost, iface_param,
420 data, dt_len);
421 break;
422 default:
423 shost_printk(KERN_ERR, shost,
424 "Invalid iface type :%d passed\n",
425 iface_param->iface_type);
426 break;
427 }
428
429 if (ret)
430 return ret;
431 }
432
433 return ret;
434}
435
436static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
437 struct iscsi_iface *iface, int param,
438 char *buf)
439{
440 struct be_cmd_get_if_info_resp if_info;
441 int len, ip_type = BE2_IPV4;
442
443 memset(&if_info, 0, sizeof(if_info));
444
445 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
446 ip_type = BE2_IPV6;
447
448 len = mgmt_get_if_info(phba, ip_type, &if_info);
449 if (len)
450 return len;
451
452 switch (param) {
453 case ISCSI_NET_PARAM_IPV4_ADDR:
454 len = sprintf(buf, "%pI4\n", &if_info.ip_addr.addr);
455 break;
456 case ISCSI_NET_PARAM_IPV6_ADDR:
457 len = sprintf(buf, "%pI6\n", &if_info.ip_addr.addr);
458 break;
459 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
460 if (!if_info.dhcp_state)
461 len = sprintf(buf, "static");
462 else
463 len = sprintf(buf, "dhcp");
464 break;
465 case ISCSI_NET_PARAM_IPV4_SUBNET:
466 len = sprintf(buf, "%pI4\n", &if_info.ip_addr.subnet_mask);
467 break;
468 default:
469 WARN_ON(1);
470 }
471
472 return len;
473}
474
475int be2iscsi_iface_get_param(struct iscsi_iface *iface,
476 enum iscsi_param_type param_type,
477 int param, char *buf)
478{
479 struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
480 struct beiscsi_hba *phba = iscsi_host_priv(shost);
481 struct be_cmd_get_def_gateway_resp gateway;
482 int len = -ENOSYS;
483
484 switch (param) {
485 case ISCSI_NET_PARAM_IPV4_ADDR:
486 case ISCSI_NET_PARAM_IPV4_SUBNET:
487 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
488 case ISCSI_NET_PARAM_IPV6_ADDR:
489 len = be2iscsi_get_if_param(phba, iface, param, buf);
490 break;
491 case ISCSI_NET_PARAM_IFACE_ENABLE:
492 len = sprintf(buf, "enabled");
493 break;
494 case ISCSI_NET_PARAM_IPV4_GW:
495 memset(&gateway, 0, sizeof(gateway));
496 len = mgmt_get_gateway(phba, BE2_IPV4, &gateway);
497 if (!len)
498 len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr);
499 break;
500 default:
501 len = -ENOSYS;
502 }
503
504 return len;
505}
506
210/** 507/**
211 * beiscsi_ep_get_param - get the iscsi parameter 508 * beiscsi_ep_get_param - get the iscsi parameter
212 * @ep: pointer to iscsi ep 509 * @ep: pointer to iscsi ep
@@ -221,7 +518,7 @@ int beiscsi_ep_get_param(struct iscsi_endpoint *ep,
221 struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; 518 struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
222 int len = 0; 519 int len = 0;
223 520
224 SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_param, param= %d\n", param); 521 SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_get_param, param= %d\n", param);
225 522
226 switch (param) { 523 switch (param) {
227 case ISCSI_PARAM_CONN_PORT: 524 case ISCSI_PARAM_CONN_PORT:
@@ -279,6 +576,121 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
279} 576}
280 577
281/** 578/**
579 * beiscsi_get_initname - Read Initiator Name from flash
580 * @buf: buffer bointer
581 * @phba: The device priv structure instance
582 *
583 * returns number of bytes
584 */
585static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
586{
587 int rc;
588 unsigned int tag, wrb_num;
589 unsigned short status, extd_status;
590 struct be_mcc_wrb *wrb;
591 struct be_cmd_hba_name *resp;
592 struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
593
594 tag = be_cmd_get_initname(phba);
595 if (!tag) {
596 SE_DEBUG(DBG_LVL_1, "Getting Initiator Name Failed\n");
597 return -EBUSY;
598 } else
599 wait_event_interruptible(phba->ctrl.mcc_wait[tag],
600 phba->ctrl.mcc_numtag[tag]);
601
602 wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
603 extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
604 status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
605
606 if (status || extd_status) {
607 SE_DEBUG(DBG_LVL_1, "MailBox Command Failed with "
608 "status = %d extd_status = %d\n",
609 status, extd_status);
610 free_mcc_tag(&phba->ctrl, tag);
611 return -EAGAIN;
612 }
613 wrb = queue_get_wrb(mccq, wrb_num);
614 free_mcc_tag(&phba->ctrl, tag);
615 resp = embedded_payload(wrb);
616 rc = sprintf(buf, "%s\n", resp->initiator_name);
617 return rc;
618}
619
620/**
621 * beiscsi_get_port_state - Get the Port State
622 * @shost : pointer to scsi_host structure
623 *
624 * returns number of bytes
625 */
626static void beiscsi_get_port_state(struct Scsi_Host *shost)
627{
628 struct beiscsi_hba *phba = iscsi_host_priv(shost);
629 struct iscsi_cls_host *ihost = shost->shost_data;
630
631 ihost->port_state = (phba->state == BE_ADAPTER_UP) ?
632 ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN;
633}
634
635/**
636 * beiscsi_get_port_speed - Get the Port Speed from Adapter
637 * @shost : pointer to scsi_host structure
638 *
639 * returns Success/Failure
640 */
641static int beiscsi_get_port_speed(struct Scsi_Host *shost)
642{
643 unsigned int tag, wrb_num;
644 unsigned short status, extd_status;
645 struct be_mcc_wrb *wrb;
646 struct be_cmd_ntwk_link_status_resp *resp;
647 struct beiscsi_hba *phba = iscsi_host_priv(shost);
648 struct iscsi_cls_host *ihost = shost->shost_data;
649 struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
650
651 tag = be_cmd_get_port_speed(phba);
652 if (!tag) {
653 SE_DEBUG(DBG_LVL_1, "Getting Port Speed Failed\n");
654 return -EBUSY;
655 } else
656 wait_event_interruptible(phba->ctrl.mcc_wait[tag],
657 phba->ctrl.mcc_numtag[tag]);
658
659 wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
660 extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
661 status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
662
663 if (status || extd_status) {
664 SE_DEBUG(DBG_LVL_1, "MailBox Command Failed with "
665 "status = %d extd_status = %d\n",
666 status, extd_status);
667 free_mcc_tag(&phba->ctrl, tag);
668 return -EAGAIN;
669 }
670 wrb = queue_get_wrb(mccq, wrb_num);
671 free_mcc_tag(&phba->ctrl, tag);
672 resp = embedded_payload(wrb);
673
674 switch (resp->mac_speed) {
675 case BE2ISCSI_LINK_SPEED_10MBPS:
676 ihost->port_speed = ISCSI_PORT_SPEED_10MBPS;
677 break;
678 case BE2ISCSI_LINK_SPEED_100MBPS:
679 ihost->port_speed = BE2ISCSI_LINK_SPEED_100MBPS;
680 break;
681 case BE2ISCSI_LINK_SPEED_1GBPS:
682 ihost->port_speed = ISCSI_PORT_SPEED_1GBPS;
683 break;
684 case BE2ISCSI_LINK_SPEED_10GBPS:
685 ihost->port_speed = ISCSI_PORT_SPEED_10GBPS;
686 break;
687 default:
688 ihost->port_speed = ISCSI_PORT_SPEED_UNKNOWN;
689 }
690 return 0;
691}
692
693/**
282 * beiscsi_get_host_param - get the iscsi parameter 694 * beiscsi_get_host_param - get the iscsi parameter
283 * @shost: pointer to scsi_host structure 695 * @shost: pointer to scsi_host structure
284 * @param: parameter type identifier 696 * @param: parameter type identifier
@@ -301,6 +713,27 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
301 return status; 713 return status;
302 } 714 }
303 break; 715 break;
716 case ISCSI_HOST_PARAM_INITIATOR_NAME:
717 status = beiscsi_get_initname(buf, phba);
718 if (status < 0) {
719 SE_DEBUG(DBG_LVL_1,
720 "Retreiving Initiator Name Failed\n");
721 return status;
722 }
723 break;
724 case ISCSI_HOST_PARAM_PORT_STATE:
725 beiscsi_get_port_state(shost);
726 status = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost));
727 break;
728 case ISCSI_HOST_PARAM_PORT_SPEED:
729 status = beiscsi_get_port_speed(shost);
730 if (status) {
731 SE_DEBUG(DBG_LVL_1,
732 "Retreiving Port Speed Failed\n");
733 return status;
734 }
735 status = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost));
736 break;
304 default: 737 default:
305 return iscsi_host_get_param(shost, param, buf); 738 return iscsi_host_get_param(shost, param, buf);
306 } 739 }
@@ -309,46 +742,21 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
309 742
310int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) 743int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba)
311{ 744{
312 struct be_cmd_resp_get_mac_addr *resp; 745 struct be_cmd_get_nic_conf_resp resp;
313 struct be_mcc_wrb *wrb;
314 unsigned int tag, wrb_num;
315 unsigned short status, extd_status;
316 struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
317 int rc; 746 int rc;
318 747
319 if (phba->read_mac_address) 748 if (strlen(phba->mac_address))
320 return sysfs_format_mac(buf, phba->mac_address, 749 return strlcpy(buf, phba->mac_address, PAGE_SIZE);
321 ETH_ALEN);
322 750
323 tag = be_cmd_get_mac_addr(phba); 751 memset(&resp, 0, sizeof(resp));
324 if (!tag) { 752 rc = mgmt_get_nic_conf(phba, &resp);
325 SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); 753 if (rc)
326 return -EBUSY; 754 return rc;
327 } else
328 wait_event_interruptible(phba->ctrl.mcc_wait[tag],
329 phba->ctrl.mcc_numtag[tag]);
330 755
331 wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; 756 memcpy(phba->mac_address, resp.mac_address, ETH_ALEN);
332 extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; 757 return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
333 status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
334 if (status || extd_status) {
335 SE_DEBUG(DBG_LVL_1, "Failed to get be_cmd_get_mac_addr"
336 " status = %d extd_status = %d\n",
337 status, extd_status);
338 free_mcc_tag(&phba->ctrl, tag);
339 return -EAGAIN;
340 }
341 wrb = queue_get_wrb(mccq, wrb_num);
342 free_mcc_tag(&phba->ctrl, tag);
343 resp = embedded_payload(wrb);
344 memcpy(phba->mac_address, resp->mac_address, ETH_ALEN);
345 rc = sysfs_format_mac(buf, phba->mac_address,
346 ETH_ALEN);
347 phba->read_mac_address = 1;
348 return rc;
349} 758}
350 759
351
352/** 760/**
353 * beiscsi_conn_get_stats - get the iscsi stats 761 * beiscsi_conn_get_stats - get the iscsi stats
354 * @cls_conn: pointer to iscsi cls conn 762 * @cls_conn: pointer to iscsi cls conn
@@ -736,11 +1144,24 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
736umode_t be2iscsi_attr_is_visible(int param_type, int param) 1144umode_t be2iscsi_attr_is_visible(int param_type, int param)
737{ 1145{
738 switch (param_type) { 1146 switch (param_type) {
1147 case ISCSI_NET_PARAM:
1148 switch (param) {
1149 case ISCSI_NET_PARAM_IFACE_ENABLE:
1150 case ISCSI_NET_PARAM_IPV4_ADDR:
1151 case ISCSI_NET_PARAM_IPV4_SUBNET:
1152 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
1153 case ISCSI_NET_PARAM_IPV4_GW:
1154 case ISCSI_NET_PARAM_IPV6_ADDR:
1155 return S_IRUGO;
1156 default:
1157 return 0;
1158 }
739 case ISCSI_HOST_PARAM: 1159 case ISCSI_HOST_PARAM:
740 switch (param) { 1160 switch (param) {
741 case ISCSI_HOST_PARAM_HWADDRESS: 1161 case ISCSI_HOST_PARAM_HWADDRESS:
742 case ISCSI_HOST_PARAM_IPADDRESS:
743 case ISCSI_HOST_PARAM_INITIATOR_NAME: 1162 case ISCSI_HOST_PARAM_INITIATOR_NAME:
1163 case ISCSI_HOST_PARAM_PORT_STATE:
1164 case ISCSI_HOST_PARAM_PORT_SPEED:
744 return S_IRUGO; 1165 return S_IRUGO;
745 default: 1166 default:
746 return 0; 1167 return 0;