[SCSI] be2iscsi: Add support for iscsi boot
This patch contains changes for adding support for iscsi_boot. Have modified to make read of mac address from chip as a function. The mac_address is being cached after teh first call as it is not expected to change Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: Jayamohan Kallickal <jayamohank@serverengines.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
f3506b755f
commit
c7acc5b8f9
|
@ -162,6 +162,13 @@ struct be_mcc_mailbox {
|
|||
#define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES 2
|
||||
#define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3
|
||||
#define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7
|
||||
#define OPCODE_COMMON_ISCSI_NTWK_SET_VLAN 14
|
||||
#define OPCODE_COMMON_ISCSI_NTWK_CONFIGURE_STATELESS_IP_ADDR 17
|
||||
#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR 21
|
||||
#define OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY 22
|
||||
#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY 23
|
||||
#define OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID 24
|
||||
#define OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO 25
|
||||
#define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61
|
||||
#define OPCODE_COMMON_ISCSI_DEFQ_CREATE 64
|
||||
#define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65
|
||||
|
@ -237,11 +244,109 @@ struct be_cmd_resp_eq_create {
|
|||
u16 rsvd0; /* sword */
|
||||
} __packed;
|
||||
|
||||
struct mgmt_chap_format {
|
||||
u32 flags;
|
||||
u8 intr_chap_name[256];
|
||||
u8 intr_secret[16];
|
||||
u8 target_chap_name[256];
|
||||
u8 target_secret[16];
|
||||
u16 intr_chap_name_length;
|
||||
u16 intr_secret_length;
|
||||
u16 target_chap_name_length;
|
||||
u16 target_secret_length;
|
||||
} __packed;
|
||||
|
||||
struct mgmt_auth_method_format {
|
||||
u8 auth_method_type;
|
||||
u8 padding[3];
|
||||
struct mgmt_chap_format chap;
|
||||
} __packed;
|
||||
|
||||
struct mgmt_conn_login_options {
|
||||
u8 flags;
|
||||
u8 header_digest;
|
||||
u8 data_digest;
|
||||
u8 rsvd0;
|
||||
u32 max_recv_datasegment_len_ini;
|
||||
u32 max_recv_datasegment_len_tgt;
|
||||
u32 tcp_mss;
|
||||
u32 tcp_window_size;
|
||||
struct mgmt_auth_method_format auth_data;
|
||||
} __packed;
|
||||
|
||||
struct ip_address_format {
|
||||
u16 size_of_structure;
|
||||
u8 reserved;
|
||||
u8 ip_type;
|
||||
u8 ip_address[16];
|
||||
u32 rsvd0;
|
||||
} __packed;
|
||||
|
||||
struct mgmt_conn_info {
|
||||
u32 connection_handle;
|
||||
u32 connection_status;
|
||||
u16 src_port;
|
||||
u16 dest_port;
|
||||
u16 dest_port_redirected;
|
||||
u16 cid;
|
||||
u32 estimated_throughput;
|
||||
struct ip_address_format src_ipaddr;
|
||||
struct ip_address_format dest_ipaddr;
|
||||
struct ip_address_format dest_ipaddr_redirected;
|
||||
struct mgmt_conn_login_options negotiated_login_options;
|
||||
} __packed;
|
||||
|
||||
struct mgmt_session_login_options {
|
||||
u8 flags;
|
||||
u8 error_recovery_level;
|
||||
u16 rsvd0;
|
||||
u32 first_burst_length;
|
||||
u32 max_burst_length;
|
||||
u16 max_connections;
|
||||
u16 max_outstanding_r2t;
|
||||
u16 default_time2wait;
|
||||
u16 default_time2retain;
|
||||
} __packed;
|
||||
|
||||
struct mgmt_session_info {
|
||||
u32 session_handle;
|
||||
u32 status;
|
||||
u8 isid[6];
|
||||
u16 tsih;
|
||||
u32 session_flags;
|
||||
u16 conn_count;
|
||||
u16 pad;
|
||||
u8 target_name[224];
|
||||
u8 initiator_iscsiname[224];
|
||||
struct mgmt_session_login_options negotiated_login_options;
|
||||
struct mgmt_conn_info conn_list[1];
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_req_get_session {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u32 session_handle;
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_resp_get_session {
|
||||
struct be_cmd_resp_hdr hdr;
|
||||
struct mgmt_session_info session_info;
|
||||
} __packed;
|
||||
|
||||
struct mac_addr {
|
||||
u16 size_of_struct;
|
||||
u8 addr[ETH_ALEN];
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_req_get_boot_target {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
} __packed;
|
||||
|
||||
struct be_cmd_resp_get_boot_target {
|
||||
struct be_cmd_resp_hdr hdr;
|
||||
u32 boot_session_count;
|
||||
int boot_session_handle;
|
||||
};
|
||||
|
||||
struct be_cmd_req_mac_query {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u8 type;
|
||||
|
@ -426,6 +531,11 @@ int be_poll_mcc(struct be_ctrl_info *ctrl);
|
|||
int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
|
||||
struct beiscsi_hba *phba);
|
||||
unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba);
|
||||
unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba);
|
||||
unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba,
|
||||
u32 boot_session_handle,
|
||||
struct be_dma_mem *nonemb_cmd);
|
||||
|
||||
void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag);
|
||||
/*ISCSI Functuions */
|
||||
int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
|
||||
|
@ -601,14 +711,6 @@ struct be_eq_delay_params_in {
|
|||
struct eq_delay delay[8];
|
||||
} __packed;
|
||||
|
||||
struct ip_address_format {
|
||||
u16 size_of_structure;
|
||||
u8 reserved;
|
||||
u8 ip_type;
|
||||
u8 ip_address[16];
|
||||
u32 rsvd0;
|
||||
} __packed;
|
||||
|
||||
struct tcp_connect_and_offload_in {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
struct ip_address_format ip_address;
|
||||
|
@ -688,18 +790,29 @@ struct be_fw_cfg {
|
|||
u32 function_caps;
|
||||
} __packed;
|
||||
|
||||
#define CMD_ISCSI_COMMAND_INVALIDATE 1
|
||||
#define ISCSI_OPCODE_SCSI_DATA_OUT 5
|
||||
struct be_all_if_id {
|
||||
struct be_cmd_req_hdr hdr;
|
||||
u32 if_count;
|
||||
u32 if_hndl_list[1];
|
||||
} __packed;
|
||||
|
||||
#define ISCSI_OPCODE_SCSI_DATA_OUT 5
|
||||
#define OPCODE_COMMON_MODIFY_EQ_DELAY 41
|
||||
#define OPCODE_COMMON_ISCSI_CLEANUP 59
|
||||
#define OPCODE_COMMON_TCP_UPLOAD 56
|
||||
#define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70
|
||||
#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
|
||||
#define OPCODE_COMMON_MODIFY_EQ_DELAY 41
|
||||
#define OPCODE_COMMON_ISCSI_CLEANUP 59
|
||||
#define OPCODE_COMMON_TCP_UPLOAD 56
|
||||
#define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1
|
||||
/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
|
||||
#define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001
|
||||
#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002
|
||||
#define OPCODE_ISCSI_INI_CFG_GET_HBA_NAME 6
|
||||
#define OPCODE_ISCSI_INI_CFG_SET_HBA_NAME 7
|
||||
#define OPCODE_ISCSI_INI_SESSION_GET_A_SESSION 14
|
||||
#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41
|
||||
#define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42
|
||||
#define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52
|
||||
|
||||
/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */
|
||||
#define CMD_ISCSI_COMMAND_INVALIDATE 1
|
||||
#define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001
|
||||
#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002
|
||||
|
||||
#define INI_WR_CMD 1 /* Initiator write command */
|
||||
#define INI_TMF_CMD 2 /* Initiator TMF command */
|
||||
|
|
|
@ -300,40 +300,16 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
|
|||
enum iscsi_host_param param, char *buf)
|
||||
{
|
||||
struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
|
||||
struct be_cmd_resp_get_mac_addr *resp;
|
||||
struct be_mcc_wrb *wrb;
|
||||
unsigned int tag, wrb_num;
|
||||
int len = 0;
|
||||
unsigned short status, extd_status;
|
||||
struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
|
||||
int status;
|
||||
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param);
|
||||
switch (param) {
|
||||
case ISCSI_HOST_PARAM_HWADDRESS:
|
||||
tag = be_cmd_get_mac_addr(phba);
|
||||
if (!tag) {
|
||||
SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n");
|
||||
return -EAGAIN;
|
||||
} else
|
||||
wait_event_interruptible(phba->ctrl.mcc_wait[tag],
|
||||
phba->ctrl.mcc_numtag[tag]);
|
||||
|
||||
wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
|
||||
extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
|
||||
status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
|
||||
if (status || extd_status) {
|
||||
SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed"
|
||||
" status = %d extd_status = %d\n",
|
||||
status, extd_status);
|
||||
free_mcc_tag(&phba->ctrl, tag);
|
||||
return -EAGAIN;
|
||||
} else {
|
||||
wrb = queue_get_wrb(mccq, wrb_num);
|
||||
free_mcc_tag(&phba->ctrl, tag);
|
||||
resp = embedded_payload(wrb);
|
||||
memcpy(phba->mac_address, resp->mac_address, ETH_ALEN);
|
||||
len = sysfs_format_mac(buf, phba->mac_address,
|
||||
ETH_ALEN);
|
||||
status = beiscsi_get_macaddr(buf, phba);
|
||||
if (status < 0) {
|
||||
SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n");
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -342,6 +318,48 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
|
|||
return len;
|
||||
}
|
||||
|
||||
int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba)
|
||||
{
|
||||
struct be_cmd_resp_get_mac_addr *resp;
|
||||
struct be_mcc_wrb *wrb;
|
||||
unsigned int tag, wrb_num;
|
||||
unsigned short status, extd_status;
|
||||
struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
|
||||
int rc;
|
||||
|
||||
if (phba->read_mac_address)
|
||||
return sysfs_format_mac(buf, phba->mac_address,
|
||||
ETH_ALEN);
|
||||
|
||||
tag = be_cmd_get_mac_addr(phba);
|
||||
if (!tag) {
|
||||
SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n");
|
||||
return -EBUSY;
|
||||
} else
|
||||
wait_event_interruptible(phba->ctrl.mcc_wait[tag],
|
||||
phba->ctrl.mcc_numtag[tag]);
|
||||
|
||||
wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
|
||||
extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
|
||||
status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
|
||||
if (status || extd_status) {
|
||||
SE_DEBUG(DBG_LVL_1, "Failed to get be_cmd_get_mac_addr"
|
||||
" status = %d extd_status = %d\n",
|
||||
status, extd_status);
|
||||
free_mcc_tag(&phba->ctrl, tag);
|
||||
return -EAGAIN;
|
||||
}
|
||||
wrb = queue_get_wrb(mccq, wrb_num);
|
||||
free_mcc_tag(&phba->ctrl, tag);
|
||||
resp = embedded_payload(wrb);
|
||||
memcpy(phba->mac_address, resp->mac_address, ETH_ALEN);
|
||||
rc = sysfs_format_mac(buf, phba->mac_address,
|
||||
ETH_ALEN);
|
||||
phba->read_mac_address = 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* beiscsi_conn_get_stats - get the iscsi stats
|
||||
* @cls_conn: pointer to iscsi cls conn
|
||||
|
|
|
@ -54,6 +54,8 @@ int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
|
|||
int beiscsi_get_host_param(struct Scsi_Host *shost,
|
||||
enum iscsi_host_param param, char *buf);
|
||||
|
||||
int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba);
|
||||
|
||||
int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
|
||||
enum iscsi_param param, char *buf, int buflen);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/iscsi_boot_sysfs.h>
|
||||
|
||||
#include <scsi/libiscsi.h>
|
||||
#include <scsi/scsi_transport_iscsi.h>
|
||||
|
@ -211,6 +212,218 @@ unlock:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
|
||||
{
|
||||
struct beiscsi_hba *phba = data;
|
||||
char *str = buf;
|
||||
int rc;
|
||||
|
||||
switch (type) {
|
||||
case ISCSI_BOOT_TGT_NAME:
|
||||
rc = sprintf(buf, "%.*s\n",
|
||||
(int)strlen(phba->boot_sess.target_name),
|
||||
(char *)&phba->boot_sess.target_name);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_IP_ADDR:
|
||||
if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1)
|
||||
rc = sprintf(buf, "%pI4\n",
|
||||
(char *)&phba->boot_sess.conn_list[0].
|
||||
dest_ipaddr.ip_address);
|
||||
else
|
||||
rc = sprintf(str, "%pI6\n",
|
||||
(char *)&phba->boot_sess.conn_list[0].
|
||||
dest_ipaddr.ip_address);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_PORT:
|
||||
rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0].
|
||||
dest_port);
|
||||
break;
|
||||
|
||||
case ISCSI_BOOT_TGT_CHAP_NAME:
|
||||
rc = sprintf(str, "%.*s\n",
|
||||
phba->boot_sess.conn_list[0].
|
||||
negotiated_login_options.auth_data.chap.
|
||||
target_chap_name_length,
|
||||
(char *)&phba->boot_sess.conn_list[0].
|
||||
negotiated_login_options.auth_data.chap.
|
||||
target_chap_name);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_CHAP_SECRET:
|
||||
rc = sprintf(str, "%.*s\n",
|
||||
phba->boot_sess.conn_list[0].
|
||||
negotiated_login_options.auth_data.chap.
|
||||
target_secret_length,
|
||||
(char *)&phba->boot_sess.conn_list[0].
|
||||
negotiated_login_options.auth_data.chap.
|
||||
target_secret);
|
||||
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_REV_CHAP_NAME:
|
||||
rc = sprintf(str, "%.*s\n",
|
||||
phba->boot_sess.conn_list[0].
|
||||
negotiated_login_options.auth_data.chap.
|
||||
intr_chap_name_length,
|
||||
(char *)&phba->boot_sess.conn_list[0].
|
||||
negotiated_login_options.auth_data.chap.
|
||||
intr_chap_name);
|
||||
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
|
||||
rc = sprintf(str, "%.*s\n",
|
||||
phba->boot_sess.conn_list[0].
|
||||
negotiated_login_options.auth_data.chap.
|
||||
intr_secret_length,
|
||||
(char *)&phba->boot_sess.conn_list[0].
|
||||
negotiated_login_options.auth_data.chap.
|
||||
intr_secret);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_FLAGS:
|
||||
rc = sprintf(str, "2\n");
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_NIC_ASSOC:
|
||||
rc = sprintf(str, "0\n");
|
||||
break;
|
||||
default:
|
||||
rc = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf)
|
||||
{
|
||||
struct beiscsi_hba *phba = data;
|
||||
char *str = buf;
|
||||
int rc;
|
||||
|
||||
switch (type) {
|
||||
case ISCSI_BOOT_INI_INITIATOR_NAME:
|
||||
rc = sprintf(str, "%s\n", phba->boot_sess.initiator_iscsiname);
|
||||
break;
|
||||
default:
|
||||
rc = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)
|
||||
{
|
||||
struct beiscsi_hba *phba = data;
|
||||
char *str = buf;
|
||||
int rc;
|
||||
|
||||
switch (type) {
|
||||
case ISCSI_BOOT_ETH_FLAGS:
|
||||
rc = sprintf(str, "2\n");
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_INDEX:
|
||||
rc = sprintf(str, "0\n");
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_MAC:
|
||||
rc = beiscsi_get_macaddr(buf, phba);
|
||||
if (rc < 0) {
|
||||
SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n");
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rc = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static mode_t beiscsi_tgt_get_attr_visibility(void *data, int type)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch (type) {
|
||||
case ISCSI_BOOT_TGT_NAME:
|
||||
case ISCSI_BOOT_TGT_IP_ADDR:
|
||||
case ISCSI_BOOT_TGT_PORT:
|
||||
case ISCSI_BOOT_TGT_CHAP_NAME:
|
||||
case ISCSI_BOOT_TGT_CHAP_SECRET:
|
||||
case ISCSI_BOOT_TGT_REV_CHAP_NAME:
|
||||
case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
|
||||
case ISCSI_BOOT_TGT_NIC_ASSOC:
|
||||
case ISCSI_BOOT_TGT_FLAGS:
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
default:
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static mode_t beiscsi_ini_get_attr_visibility(void *data, int type)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch (type) {
|
||||
case ISCSI_BOOT_INI_INITIATOR_NAME:
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
default:
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static mode_t beiscsi_eth_get_attr_visibility(void *data, int type)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch (type) {
|
||||
case ISCSI_BOOT_ETH_FLAGS:
|
||||
case ISCSI_BOOT_ETH_MAC:
|
||||
case ISCSI_BOOT_ETH_INDEX:
|
||||
rc = S_IRUGO;
|
||||
break;
|
||||
default:
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
|
||||
{
|
||||
struct iscsi_boot_kobj *boot_kobj;
|
||||
|
||||
phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no);
|
||||
if (!phba->boot_kset)
|
||||
return -ENOMEM;
|
||||
|
||||
/* get boot info using mgmt cmd */
|
||||
boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba,
|
||||
beiscsi_show_boot_tgt_info,
|
||||
beiscsi_tgt_get_attr_visibility);
|
||||
if (!boot_kobj)
|
||||
goto free_kset;
|
||||
|
||||
boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba,
|
||||
beiscsi_show_boot_ini_info,
|
||||
beiscsi_ini_get_attr_visibility);
|
||||
if (!boot_kobj)
|
||||
goto free_kset;
|
||||
|
||||
boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba,
|
||||
beiscsi_show_boot_eth_info,
|
||||
beiscsi_eth_get_attr_visibility);
|
||||
if (!boot_kobj)
|
||||
goto free_kset;
|
||||
return 0;
|
||||
|
||||
free_kset:
|
||||
iscsi_boot_destroy_kset(phba->boot_kset);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*------------------- PCI Driver operations and data ----------------- */
|
||||
static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
|
||||
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
|
||||
|
@ -268,6 +481,15 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
|
|||
|
||||
if (iscsi_host_add(shost, &phba->pcidev->dev))
|
||||
goto free_devices;
|
||||
|
||||
if (beiscsi_setup_boot_info(phba))
|
||||
/*
|
||||
* log error but continue, because we may not be using
|
||||
* iscsi boot.
|
||||
*/
|
||||
shost_printk(KERN_ERR, phba->shost, "Could not set up "
|
||||
"iSCSI boot info.");
|
||||
|
||||
return phba;
|
||||
|
||||
free_devices:
|
||||
|
@ -3279,6 +3501,89 @@ static void hwi_disable_intr(struct beiscsi_hba *phba)
|
|||
"In hwi_disable_intr, Already Disabled\n");
|
||||
}
|
||||
|
||||
static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
|
||||
{
|
||||
struct be_cmd_resp_get_boot_target *boot_resp;
|
||||
struct be_cmd_resp_get_session *session_resp;
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_dma_mem nonemb_cmd;
|
||||
unsigned int tag, wrb_num;
|
||||
unsigned short status, extd_status;
|
||||
struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
|
||||
|
||||
tag = beiscsi_get_boot_target(phba);
|
||||
if (!tag) {
|
||||
SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n");
|
||||
return -EAGAIN;
|
||||
} else
|
||||
wait_event_interruptible(phba->ctrl.mcc_wait[tag],
|
||||
phba->ctrl.mcc_numtag[tag]);
|
||||
|
||||
wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
|
||||
extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
|
||||
status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
|
||||
if (status || extd_status) {
|
||||
SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed"
|
||||
" status = %d extd_status = %d\n",
|
||||
status, extd_status);
|
||||
free_mcc_tag(&phba->ctrl, tag);
|
||||
return -EBUSY;
|
||||
}
|
||||
wrb = queue_get_wrb(mccq, wrb_num);
|
||||
free_mcc_tag(&phba->ctrl, tag);
|
||||
boot_resp = embedded_payload(wrb);
|
||||
|
||||
if (boot_resp->boot_session_handle < 0) {
|
||||
printk(KERN_ERR "No Boot Session for this pci_func,"
|
||||
"session Hndl = %d\n", boot_resp->boot_session_handle);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
|
||||
sizeof(*session_resp),
|
||||
&nonemb_cmd.dma);
|
||||
if (nonemb_cmd.va == NULL) {
|
||||
SE_DEBUG(DBG_LVL_1,
|
||||
"Failed to allocate memory for"
|
||||
"beiscsi_get_session_info\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(nonemb_cmd.va, 0, sizeof(*session_resp));
|
||||
tag = beiscsi_get_session_info(phba,
|
||||
boot_resp->boot_session_handle, &nonemb_cmd);
|
||||
if (!tag) {
|
||||
SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info"
|
||||
" Failed\n");
|
||||
goto boot_freemem;
|
||||
} else
|
||||
wait_event_interruptible(phba->ctrl.mcc_wait[tag],
|
||||
phba->ctrl.mcc_numtag[tag]);
|
||||
|
||||
wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
|
||||
extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
|
||||
status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
|
||||
if (status || extd_status) {
|
||||
SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info Failed"
|
||||
" status = %d extd_status = %d\n",
|
||||
status, extd_status);
|
||||
free_mcc_tag(&phba->ctrl, tag);
|
||||
goto boot_freemem;
|
||||
}
|
||||
wrb = queue_get_wrb(mccq, wrb_num);
|
||||
free_mcc_tag(&phba->ctrl, tag);
|
||||
session_resp = nonemb_cmd.va ;
|
||||
memcpy(&phba->boot_sess, &session_resp->session_info,
|
||||
sizeof(struct mgmt_session_info));
|
||||
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
|
||||
nonemb_cmd.va, nonemb_cmd.dma);
|
||||
return 0;
|
||||
boot_freemem:
|
||||
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
|
||||
nonemb_cmd.va, nonemb_cmd.dma);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int beiscsi_init_port(struct beiscsi_hba *phba)
|
||||
{
|
||||
int ret;
|
||||
|
@ -3841,6 +4146,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
|
|||
iscsi_host_remove(phba->shost);
|
||||
pci_dev_put(phba->pcidev);
|
||||
iscsi_host_free(phba->shost);
|
||||
iscsi_boot_destroy_kset(phba->boot_kset);
|
||||
}
|
||||
|
||||
static void beiscsi_msix_enable(struct beiscsi_hba *phba)
|
||||
|
@ -3996,6 +4302,11 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
|
|||
goto free_blkenbld;
|
||||
}
|
||||
hwi_enable_intr(phba);
|
||||
ret = beiscsi_get_boot_info(phba);
|
||||
if (ret < 0) {
|
||||
shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
|
||||
"No Boot Devices !!!!!\n");
|
||||
}
|
||||
SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n");
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -312,6 +312,7 @@ struct beiscsi_hba {
|
|||
struct list_head hba_queue;
|
||||
unsigned short *cid_array;
|
||||
struct iscsi_endpoint **ep_array;
|
||||
struct iscsi_boot_kset *boot_kset;
|
||||
struct Scsi_Host *shost;
|
||||
struct {
|
||||
/**
|
||||
|
@ -342,6 +343,8 @@ struct beiscsi_hba {
|
|||
struct work_struct work_cqs; /* The work being queued */
|
||||
struct be_ctrl_info ctrl;
|
||||
unsigned int generation;
|
||||
unsigned int read_mac_address;
|
||||
struct mgmt_session_info boot_sess;
|
||||
struct invalidate_command_table inv_tbl[128];
|
||||
|
||||
};
|
||||
|
|
|
@ -20,6 +20,77 @@
|
|||
|
||||
#include "be_mgmt.h"
|
||||
#include "be_iscsi.h"
|
||||
#include <scsi/scsi_transport_iscsi.h>
|
||||
|
||||
unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba)
|
||||
{
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_req_get_mac_addr *req;
|
||||
unsigned int tag = 0;
|
||||
|
||||
SE_DEBUG(DBG_LVL_8, "In bescsi_get_boot_target\n");
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
tag = alloc_mcc_tag(phba);
|
||||
if (!tag) {
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return tag;
|
||||
}
|
||||
|
||||
wrb = wrb_from_mccq(phba);
|
||||
req = embedded_payload(wrb);
|
||||
wrb->tag0 |= tag;
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
|
||||
OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET,
|
||||
sizeof(*req));
|
||||
|
||||
be_mcc_notify(phba);
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return tag;
|
||||
}
|
||||
|
||||
unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba,
|
||||
u32 boot_session_handle,
|
||||
struct be_dma_mem *nonemb_cmd)
|
||||
{
|
||||
struct be_ctrl_info *ctrl = &phba->ctrl;
|
||||
struct be_mcc_wrb *wrb;
|
||||
unsigned int tag = 0;
|
||||
struct be_cmd_req_get_session *req;
|
||||
struct be_cmd_resp_get_session *resp;
|
||||
struct be_sge *sge;
|
||||
|
||||
SE_DEBUG(DBG_LVL_8, "In beiscsi_get_session_info\n");
|
||||
spin_lock(&ctrl->mbox_lock);
|
||||
tag = alloc_mcc_tag(phba);
|
||||
if (!tag) {
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return tag;
|
||||
}
|
||||
|
||||
nonemb_cmd->size = sizeof(*resp);
|
||||
req = nonemb_cmd->va;
|
||||
memset(req, 0, sizeof(*req));
|
||||
wrb = wrb_from_mccq(phba);
|
||||
sge = nonembedded_sgl(wrb);
|
||||
wrb->tag0 |= tag;
|
||||
|
||||
|
||||
wrb->tag0 |= tag;
|
||||
be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
|
||||
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
|
||||
OPCODE_ISCSI_INI_SESSION_GET_A_SESSION,
|
||||
sizeof(*resp));
|
||||
req->session_handle = boot_session_handle;
|
||||
sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
|
||||
sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
|
||||
sge->len = cpu_to_le32(nonemb_cmd->size);
|
||||
|
||||
be_mcc_notify(phba);
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return tag;
|
||||
}
|
||||
|
||||
int mgmt_get_fw_config(struct be_ctrl_info *ctrl,
|
||||
struct beiscsi_hba *phba)
|
||||
|
|
Loading…
Reference in a new issue