qedi: Add support for populating ethernet TLVs.
This patch adds callbacks for providing the ethernet protocol driver TLVs. Signed-off-by: Manish Rangankar <manish.rangankar@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8673daf4f5
commit
534bbdf883
|
@ -353,6 +353,9 @@ struct qedi_ctx {
|
|||
#define IPV6_LEN 41
|
||||
#define IPV4_LEN 17
|
||||
struct iscsi_boot_kset *boot_kset;
|
||||
|
||||
/* Used for iscsi statistics */
|
||||
struct mutex stats_lock;
|
||||
};
|
||||
|
||||
struct qedi_work {
|
||||
|
|
|
@ -223,6 +223,12 @@ struct qedi_work_map {
|
|||
struct work_struct *ptr_tmf_work;
|
||||
};
|
||||
|
||||
struct qedi_boot_target {
|
||||
char ip_addr[64];
|
||||
char iscsi_name[255];
|
||||
u32 ipv6_en;
|
||||
};
|
||||
|
||||
#define qedi_set_itt(task_id, itt) ((u32)(((task_id) & 0xffff) | ((itt) << 16)))
|
||||
#define qedi_get_itt(cqe) (cqe.iscsi_hdr.cmd.itt >> 16)
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ static void qedi_free_global_queues(struct qedi_ctx *qedi);
|
|||
static struct qedi_cmd *qedi_get_cmd_from_tid(struct qedi_ctx *qedi, u32 tid);
|
||||
static void qedi_reset_uio_rings(struct qedi_uio_dev *udev);
|
||||
static void qedi_ll2_free_skbs(struct qedi_ctx *qedi);
|
||||
static struct nvm_iscsi_block *qedi_get_nvram_block(struct qedi_ctx *qedi);
|
||||
|
||||
static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle)
|
||||
{
|
||||
|
@ -879,6 +880,186 @@ static void qedi_free_iscsi_pf_param(struct qedi_ctx *qedi)
|
|||
kfree(qedi->global_queues);
|
||||
}
|
||||
|
||||
static void qedi_get_boot_tgt_info(struct nvm_iscsi_block *block,
|
||||
struct qedi_boot_target *tgt, u8 index)
|
||||
{
|
||||
u32 ipv6_en;
|
||||
|
||||
ipv6_en = !!(block->generic.ctrl_flags &
|
||||
NVM_ISCSI_CFG_GEN_IPV6_ENABLED);
|
||||
|
||||
snprintf(tgt->iscsi_name, NVM_ISCSI_CFG_ISCSI_NAME_MAX_LEN, "%s\n",
|
||||
block->target[index].target_name.byte);
|
||||
|
||||
tgt->ipv6_en = ipv6_en;
|
||||
|
||||
if (ipv6_en)
|
||||
snprintf(tgt->ip_addr, IPV6_LEN, "%pI6\n",
|
||||
block->target[index].ipv6_addr.byte);
|
||||
else
|
||||
snprintf(tgt->ip_addr, IPV4_LEN, "%pI4\n",
|
||||
block->target[index].ipv4_addr.byte);
|
||||
}
|
||||
|
||||
static int qedi_find_boot_info(struct qedi_ctx *qedi,
|
||||
struct qed_mfw_tlv_iscsi *iscsi,
|
||||
struct nvm_iscsi_block *block)
|
||||
{
|
||||
struct qedi_boot_target *pri_tgt = NULL, *sec_tgt = NULL;
|
||||
u32 pri_ctrl_flags = 0, sec_ctrl_flags = 0, found = 0;
|
||||
struct iscsi_cls_session *cls_sess;
|
||||
struct iscsi_cls_conn *cls_conn;
|
||||
struct qedi_conn *qedi_conn;
|
||||
struct iscsi_session *sess;
|
||||
struct iscsi_conn *conn;
|
||||
char ep_ip_addr[64];
|
||||
int i, ret = 0;
|
||||
|
||||
pri_ctrl_flags = !!(block->target[0].ctrl_flags &
|
||||
NVM_ISCSI_CFG_TARGET_ENABLED);
|
||||
if (pri_ctrl_flags) {
|
||||
pri_tgt = kzalloc(sizeof(*pri_tgt), GFP_KERNEL);
|
||||
if (!pri_tgt)
|
||||
return -1;
|
||||
qedi_get_boot_tgt_info(block, pri_tgt, 0);
|
||||
}
|
||||
|
||||
sec_ctrl_flags = !!(block->target[1].ctrl_flags &
|
||||
NVM_ISCSI_CFG_TARGET_ENABLED);
|
||||
if (sec_ctrl_flags) {
|
||||
sec_tgt = kzalloc(sizeof(*sec_tgt), GFP_KERNEL);
|
||||
if (!sec_tgt) {
|
||||
ret = -1;
|
||||
goto free_tgt;
|
||||
}
|
||||
qedi_get_boot_tgt_info(block, sec_tgt, 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < qedi->max_active_conns; i++) {
|
||||
qedi_conn = qedi_get_conn_from_id(qedi, i);
|
||||
if (!qedi_conn)
|
||||
continue;
|
||||
|
||||
if (qedi_conn->ep->ip_type == TCP_IPV4)
|
||||
snprintf(ep_ip_addr, IPV4_LEN, "%pI4\n",
|
||||
qedi_conn->ep->dst_addr);
|
||||
else
|
||||
snprintf(ep_ip_addr, IPV6_LEN, "%pI6\n",
|
||||
qedi_conn->ep->dst_addr);
|
||||
|
||||
cls_conn = qedi_conn->cls_conn;
|
||||
conn = cls_conn->dd_data;
|
||||
cls_sess = iscsi_conn_to_session(cls_conn);
|
||||
sess = cls_sess->dd_data;
|
||||
|
||||
if (pri_ctrl_flags) {
|
||||
if (!strcmp(pri_tgt->iscsi_name, sess->targetname) &&
|
||||
!strcmp(pri_tgt->ip_addr, ep_ip_addr)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sec_ctrl_flags) {
|
||||
if (!strcmp(sec_tgt->iscsi_name, sess->targetname) &&
|
||||
!strcmp(sec_tgt->ip_addr, ep_ip_addr)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (conn->hdrdgst_en) {
|
||||
iscsi->header_digest_set = true;
|
||||
iscsi->header_digest = 1;
|
||||
}
|
||||
|
||||
if (conn->datadgst_en) {
|
||||
iscsi->data_digest_set = true;
|
||||
iscsi->data_digest = 1;
|
||||
}
|
||||
iscsi->boot_taget_portal_set = true;
|
||||
iscsi->boot_taget_portal = sess->tpgt;
|
||||
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (sec_ctrl_flags)
|
||||
kfree(sec_tgt);
|
||||
free_tgt:
|
||||
if (pri_ctrl_flags)
|
||||
kfree(pri_tgt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Protocol TLV handler
|
||||
*/
|
||||
static void qedi_get_protocol_tlv_data(void *dev, void *data)
|
||||
{
|
||||
struct qed_mfw_tlv_iscsi *iscsi = data;
|
||||
struct qed_iscsi_stats *fw_iscsi_stats;
|
||||
struct nvm_iscsi_block *block = NULL;
|
||||
u32 chap_en = 0, mchap_en = 0;
|
||||
struct qedi_ctx *qedi = dev;
|
||||
int rval = 0;
|
||||
|
||||
fw_iscsi_stats = kmalloc(sizeof(*fw_iscsi_stats), GFP_KERNEL);
|
||||
if (!fw_iscsi_stats) {
|
||||
QEDI_ERR(&qedi->dbg_ctx,
|
||||
"Could not allocate memory for fw_iscsi_stats.\n");
|
||||
goto exit_get_data;
|
||||
}
|
||||
|
||||
mutex_lock(&qedi->stats_lock);
|
||||
/* Query firmware for offload stats */
|
||||
qedi_ops->get_stats(qedi->cdev, fw_iscsi_stats);
|
||||
mutex_unlock(&qedi->stats_lock);
|
||||
|
||||
iscsi->rx_frames_set = true;
|
||||
iscsi->rx_frames = fw_iscsi_stats->iscsi_rx_packet_cnt;
|
||||
iscsi->rx_bytes_set = true;
|
||||
iscsi->rx_bytes = fw_iscsi_stats->iscsi_rx_bytes_cnt;
|
||||
iscsi->tx_frames_set = true;
|
||||
iscsi->tx_frames = fw_iscsi_stats->iscsi_tx_packet_cnt;
|
||||
iscsi->tx_bytes_set = true;
|
||||
iscsi->tx_bytes = fw_iscsi_stats->iscsi_tx_bytes_cnt;
|
||||
iscsi->frame_size_set = true;
|
||||
iscsi->frame_size = qedi->ll2_mtu;
|
||||
block = qedi_get_nvram_block(qedi);
|
||||
if (block) {
|
||||
chap_en = !!(block->generic.ctrl_flags &
|
||||
NVM_ISCSI_CFG_GEN_CHAP_ENABLED);
|
||||
mchap_en = !!(block->generic.ctrl_flags &
|
||||
NVM_ISCSI_CFG_GEN_CHAP_MUTUAL_ENABLED);
|
||||
|
||||
iscsi->auth_method_set = (chap_en || mchap_en) ? true : false;
|
||||
iscsi->auth_method = 1;
|
||||
if (chap_en)
|
||||
iscsi->auth_method = 2;
|
||||
if (mchap_en)
|
||||
iscsi->auth_method = 3;
|
||||
|
||||
iscsi->tx_desc_size_set = true;
|
||||
iscsi->tx_desc_size = QEDI_SQ_SIZE;
|
||||
iscsi->rx_desc_size_set = true;
|
||||
iscsi->rx_desc_size = QEDI_CQ_SIZE;
|
||||
|
||||
/* tpgt, hdr digest, data digest */
|
||||
rval = qedi_find_boot_info(qedi, iscsi, block);
|
||||
if (rval)
|
||||
QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
|
||||
"Boot target not set");
|
||||
}
|
||||
|
||||
kfree(fw_iscsi_stats);
|
||||
exit_get_data:
|
||||
return;
|
||||
}
|
||||
|
||||
static void qedi_link_update(void *dev, struct qed_link_output *link)
|
||||
{
|
||||
struct qedi_ctx *qedi = (struct qedi_ctx *)dev;
|
||||
|
@ -896,6 +1077,7 @@ static void qedi_link_update(void *dev, struct qed_link_output *link)
|
|||
static struct qed_iscsi_cb_ops qedi_cb_ops = {
|
||||
{
|
||||
.link_update = qedi_link_update,
|
||||
.get_protocol_tlv_data = qedi_get_protocol_tlv_data,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue