Loading drivers/scsi/qedi/qedi.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading drivers/scsi/qedi/qedi_iscsi.h +6 −0 Original line number Diff line number Diff line Loading @@ -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) Loading drivers/scsi/qedi/qedi_main.c +182 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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 Loading
drivers/scsi/qedi/qedi.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
drivers/scsi/qedi/qedi_iscsi.h +6 −0 Original line number Diff line number Diff line Loading @@ -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) Loading
drivers/scsi/qedi/qedi_main.c +182 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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