Commit b2608311 authored by David S. Miller's avatar David S. Miller

Merge branch 'qed-Enhance-storage-APIs'

Yuval Mintz says:

====================
qed: Enhance storage APIs

This series is intended to add additional information and features
to the API between qed and its storage protocol drivers [qedi, qedf].

Patch #2 adds some information stored on device such as wwpn & wwnn
to allow qedf utilize it; #1 fixes an issue with the reading of those
values [which were unused until now].

Patch #3 would allow the protocol drivers access to images on persistent
storage which is a prerequirement for adding boot from SAN support.

Patch #4 adds infrastrucutre to a future feature for qedi.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3a5f8997 dc4528e9
...@@ -2071,16 +2071,22 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn) ...@@ -2071,16 +2071,22 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
QED_VF_L2_QUE)); QED_VF_L2_QUE));
} }
if (p_hwfn->hw_info.personality == QED_PCI_FCOE)
feat_num[QED_FCOE_CQ] = min_t(u32, sb_cnt.cnt,
RESC_NUM(p_hwfn,
QED_CMDQS_CQS));
if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) if (p_hwfn->hw_info.personality == QED_PCI_ISCSI)
feat_num[QED_ISCSI_CQ] = min_t(u32, sb_cnt.cnt, feat_num[QED_ISCSI_CQ] = min_t(u32, sb_cnt.cnt,
RESC_NUM(p_hwfn, RESC_NUM(p_hwfn,
QED_CMDQS_CQS)); QED_CMDQS_CQS));
DP_VERBOSE(p_hwfn, DP_VERBOSE(p_hwfn,
NETIF_MSG_PROBE, NETIF_MSG_PROBE,
"#PF_L2_QUEUES=%d VF_L2_QUEUES=%d #ROCE_CNQ=%d ISCSI_CQ=%d #SBS=%d\n", "#PF_L2_QUEUES=%d VF_L2_QUEUES=%d #ROCE_CNQ=%d FCOE_CQ=%d ISCSI_CQ=%d #SBS=%d\n",
(int)FEAT_NUM(p_hwfn, QED_PF_L2_QUE), (int)FEAT_NUM(p_hwfn, QED_PF_L2_QUE),
(int)FEAT_NUM(p_hwfn, QED_VF_L2_QUE), (int)FEAT_NUM(p_hwfn, QED_VF_L2_QUE),
(int)FEAT_NUM(p_hwfn, QED_RDMA_CNQ), (int)FEAT_NUM(p_hwfn, QED_RDMA_CNQ),
(int)FEAT_NUM(p_hwfn, QED_FCOE_CQ),
(int)FEAT_NUM(p_hwfn, QED_ISCSI_CQ), (int)FEAT_NUM(p_hwfn, QED_ISCSI_CQ),
(int)sb_cnt.cnt); (int)sb_cnt.cnt);
} }
......
...@@ -141,6 +141,15 @@ qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn, ...@@ -141,6 +141,15 @@ qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn,
p_data = &p_ramrod->init_ramrod_data; p_data = &p_ramrod->init_ramrod_data;
fcoe_pf_params = &p_hwfn->pf_params.fcoe_pf_params; fcoe_pf_params = &p_hwfn->pf_params.fcoe_pf_params;
/* Sanity */
if (fcoe_pf_params->num_cqs > p_hwfn->hw_info.feat_num[QED_FCOE_CQ]) {
DP_ERR(p_hwfn,
"Cannot satisfy CQ amount. CQs requested %d, CQs available %d. Aborting function start\n",
fcoe_pf_params->num_cqs,
p_hwfn->hw_info.feat_num[QED_FCOE_CQ]);
return -EINVAL;
}
p_data->mtu = cpu_to_le16(fcoe_pf_params->mtu); p_data->mtu = cpu_to_le16(fcoe_pf_params->mtu);
tmp = cpu_to_le16(fcoe_pf_params->sq_num_pbl_pages); tmp = cpu_to_le16(fcoe_pf_params->sq_num_pbl_pages);
p_data->sq_num_pages_in_pbl = tmp; p_data->sq_num_pages_in_pbl = tmp;
...@@ -739,6 +748,11 @@ static int qed_fill_fcoe_dev_info(struct qed_dev *cdev, ...@@ -739,6 +748,11 @@ static int qed_fill_fcoe_dev_info(struct qed_dev *cdev,
info->secondary_bdq_rq_addr = info->secondary_bdq_rq_addr =
qed_fcoe_get_secondary_bdq_prod(hwfn, BDQ_ID_RQ); qed_fcoe_get_secondary_bdq_prod(hwfn, BDQ_ID_RQ);
info->wwpn = hwfn->mcp_info->func_info.wwn_port;
info->wwnn = hwfn->mcp_info->func_info.wwn_node;
info->num_cqs = FEAT_NUM(hwfn, QED_FCOE_CQ);
return rc; return rc;
} }
......
...@@ -488,6 +488,54 @@ static int qed_sp_iscsi_conn_update(struct qed_hwfn *p_hwfn, ...@@ -488,6 +488,54 @@ static int qed_sp_iscsi_conn_update(struct qed_hwfn *p_hwfn,
return qed_spq_post(p_hwfn, p_ent, NULL); return qed_spq_post(p_hwfn, p_ent, NULL);
} }
static int
qed_sp_iscsi_mac_update(struct qed_hwfn *p_hwfn,
struct qed_iscsi_conn *p_conn,
enum spq_mode comp_mode,
struct qed_spq_comp_cb *p_comp_addr)
{
struct iscsi_spe_conn_mac_update *p_ramrod = NULL;
struct qed_spq_entry *p_ent = NULL;
struct qed_sp_init_data init_data;
int rc = -EINVAL;
u8 ucval;
/* Get SPQ entry */
memset(&init_data, 0, sizeof(init_data));
init_data.cid = p_conn->icid;
init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
init_data.comp_mode = comp_mode;
init_data.p_comp_data = p_comp_addr;
rc = qed_sp_init_request(p_hwfn, &p_ent,
ISCSI_RAMROD_CMD_ID_MAC_UPDATE,
PROTOCOLID_ISCSI, &init_data);
if (rc)
return rc;
p_ramrod = &p_ent->ramrod.iscsi_conn_mac_update;
p_ramrod->hdr.op_code = ISCSI_RAMROD_CMD_ID_MAC_UPDATE;
SET_FIELD(p_ramrod->hdr.flags,
ISCSI_SLOW_PATH_HDR_LAYER_CODE, p_conn->layer_code);
p_ramrod->conn_id = cpu_to_le16(p_conn->conn_id);
p_ramrod->fw_cid = cpu_to_le32(p_conn->icid);
ucval = p_conn->remote_mac[1];
((u8 *)(&p_ramrod->remote_mac_addr_hi))[0] = ucval;
ucval = p_conn->remote_mac[0];
((u8 *)(&p_ramrod->remote_mac_addr_hi))[1] = ucval;
ucval = p_conn->remote_mac[3];
((u8 *)(&p_ramrod->remote_mac_addr_mid))[0] = ucval;
ucval = p_conn->remote_mac[2];
((u8 *)(&p_ramrod->remote_mac_addr_mid))[1] = ucval;
ucval = p_conn->remote_mac[5];
((u8 *)(&p_ramrod->remote_mac_addr_lo))[0] = ucval;
ucval = p_conn->remote_mac[4];
((u8 *)(&p_ramrod->remote_mac_addr_lo))[1] = ucval;
return qed_spq_post(p_hwfn, p_ent, NULL);
}
static int qed_sp_iscsi_conn_terminate(struct qed_hwfn *p_hwfn, static int qed_sp_iscsi_conn_terminate(struct qed_hwfn *p_hwfn,
struct qed_iscsi_conn *p_conn, struct qed_iscsi_conn *p_conn,
enum spq_mode comp_mode, enum spq_mode comp_mode,
...@@ -1324,6 +1372,23 @@ static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats) ...@@ -1324,6 +1372,23 @@ static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats)
return qed_iscsi_get_stats(QED_LEADING_HWFN(cdev), stats); return qed_iscsi_get_stats(QED_LEADING_HWFN(cdev), stats);
} }
static int qed_iscsi_change_mac(struct qed_dev *cdev,
u32 handle, const u8 *mac)
{
struct qed_hash_iscsi_con *hash_con;
hash_con = qed_iscsi_get_hash(cdev, handle);
if (!hash_con) {
DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
handle);
return -EINVAL;
}
return qed_sp_iscsi_mac_update(QED_LEADING_HWFN(cdev),
hash_con->con,
QED_SPQ_MODE_EBLOCK, NULL);
}
void qed_get_protocol_stats_iscsi(struct qed_dev *cdev, void qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
struct qed_mcp_iscsi_stats *stats) struct qed_mcp_iscsi_stats *stats)
{ {
...@@ -1358,6 +1423,7 @@ static const struct qed_iscsi_ops qed_iscsi_ops_pass = { ...@@ -1358,6 +1423,7 @@ static const struct qed_iscsi_ops qed_iscsi_ops_pass = {
.destroy_conn = &qed_iscsi_destroy_conn, .destroy_conn = &qed_iscsi_destroy_conn,
.clear_sq = &qed_iscsi_clear_conn_sq, .clear_sq = &qed_iscsi_clear_conn_sq,
.get_stats = &qed_iscsi_stats, .get_stats = &qed_iscsi_stats,
.change_mac = &qed_iscsi_change_mac,
}; };
const struct qed_iscsi_ops *qed_get_iscsi_ops(void) const struct qed_iscsi_ops *qed_get_iscsi_ops(void)
......
...@@ -269,6 +269,8 @@ int qed_fill_dev_info(struct qed_dev *cdev, ...@@ -269,6 +269,8 @@ int qed_fill_dev_info(struct qed_dev *cdev,
if (QED_LEADING_HWFN(cdev)->hw_info.b_wol_support == if (QED_LEADING_HWFN(cdev)->hw_info.b_wol_support ==
QED_WOL_SUPPORT_PME) QED_WOL_SUPPORT_PME)
dev_info->wol_support = true; dev_info->wol_support = true;
dev_info->abs_pf_id = QED_LEADING_HWFN(cdev)->abs_pf_id;
} else { } else {
qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major, qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major,
&dev_info->fw_minor, &dev_info->fw_rev, &dev_info->fw_minor, &dev_info->fw_rev,
...@@ -1533,6 +1535,21 @@ static int qed_drain(struct qed_dev *cdev) ...@@ -1533,6 +1535,21 @@ static int qed_drain(struct qed_dev *cdev)
return 0; return 0;
} }
static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type,
u8 *buf, u16 len)
{
struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
struct qed_ptt *ptt = qed_ptt_acquire(hwfn);
int rc;
if (!ptt)
return -EAGAIN;
rc = qed_mcp_get_nvm_image(hwfn, ptt, type, buf, len);
qed_ptt_release(hwfn, ptt);
return rc;
}
static void qed_get_coalesce(struct qed_dev *cdev, u16 *rx_coal, u16 *tx_coal) static void qed_get_coalesce(struct qed_dev *cdev, u16 *rx_coal, u16 *tx_coal)
{ {
*rx_coal = cdev->rx_coalesce_usecs; *rx_coal = cdev->rx_coalesce_usecs;
...@@ -1710,6 +1727,7 @@ const struct qed_common_ops qed_common_ops_pass = { ...@@ -1710,6 +1727,7 @@ const struct qed_common_ops qed_common_ops_pass = {
.dbg_all_data_size = &qed_dbg_all_data_size, .dbg_all_data_size = &qed_dbg_all_data_size,
.chain_alloc = &qed_chain_alloc, .chain_alloc = &qed_chain_alloc,
.chain_free = &qed_chain_free, .chain_free = &qed_chain_free,
.nvm_get_image = &qed_nvm_get_image,
.get_coalesce = &qed_get_coalesce, .get_coalesce = &qed_get_coalesce,
.set_coalesce = &qed_set_coalesce, .set_coalesce = &qed_set_coalesce,
.set_led = &qed_set_led, .set_led = &qed_set_led,
......
...@@ -1736,10 +1736,10 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn, ...@@ -1736,10 +1736,10 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn,
DP_NOTICE(p_hwfn, "MAC is 0 in shmem\n"); DP_NOTICE(p_hwfn, "MAC is 0 in shmem\n");
} }
info->wwn_port = (u64)shmem_info.fcoe_wwn_port_name_upper | info->wwn_port = (u64)shmem_info.fcoe_wwn_port_name_lower |
(((u64)shmem_info.fcoe_wwn_port_name_lower) << 32); (((u64)shmem_info.fcoe_wwn_port_name_upper) << 32);
info->wwn_node = (u64)shmem_info.fcoe_wwn_node_name_upper | info->wwn_node = (u64)shmem_info.fcoe_wwn_node_name_lower |
(((u64)shmem_info.fcoe_wwn_node_name_lower) << 32); (((u64)shmem_info.fcoe_wwn_node_name_upper) << 32);
info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK); info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK);
...@@ -2310,6 +2310,95 @@ int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn, ...@@ -2310,6 +2310,95 @@ int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
return rc; return rc;
} }
static int
qed_mcp_get_nvm_image_att(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
enum qed_nvm_images image_id,
struct qed_nvm_image_att *p_image_att)
{
struct bist_nvm_image_att mfw_image_att;
enum nvm_image_type type;
u32 num_images, i;
int rc;
/* Translate image_id into MFW definitions */
switch (image_id) {
case QED_NVM_IMAGE_ISCSI_CFG:
type = NVM_TYPE_ISCSI_CFG;
break;
case QED_NVM_IMAGE_FCOE_CFG:
type = NVM_TYPE_FCOE_CFG;
break;
default:
DP_NOTICE(p_hwfn, "Unknown request of image_id %08x\n",
image_id);
return -EINVAL;
}
/* Learn number of images, then traverse and see if one fits */
rc = qed_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
if (rc || !num_images)
return -EINVAL;
for (i = 0; i < num_images; i++) {
rc = qed_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
&mfw_image_att, i);
if (rc)
return rc;
if (type == mfw_image_att.image_type)
break;
}
if (i == num_images) {
DP_VERBOSE(p_hwfn, QED_MSG_STORAGE,
"Failed to find nvram image of type %08x\n",
image_id);
return -EINVAL;
}
p_image_att->start_addr = mfw_image_att.nvm_start_addr;
p_image_att->length = mfw_image_att.len;
return 0;
}
int qed_mcp_get_nvm_image(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
enum qed_nvm_images image_id,
u8 *p_buffer, u32 buffer_len)
{
struct qed_nvm_image_att image_att;
int rc;
memset(p_buffer, 0, buffer_len);
rc = qed_mcp_get_nvm_image_att(p_hwfn, p_ptt, image_id, &image_att);
if (rc)
return rc;
/* Validate sizes - both the image's and the supplied buffer's */
if (image_att.length <= 4) {
DP_VERBOSE(p_hwfn, QED_MSG_STORAGE,
"Image [%d] is too small - only %d bytes\n",
image_id, image_att.length);
return -EINVAL;
}
/* Each NVM image is suffixed by CRC; Upper-layer has no need for it */
image_att.length -= 4;
if (image_att.length > buffer_len) {
DP_VERBOSE(p_hwfn,
QED_MSG_STORAGE,
"Image [%d] is too big - %08x bytes where only %08x are available\n",
image_id, image_att.length, buffer_len);
return -ENOMEM;
}
return qed_mcp_nvm_read(p_hwfn->cdev, image_att.start_addr,
p_buffer, image_att.length);
}
static enum resource_id_enum qed_mcp_get_mfw_res_id(enum qed_resources res_id) static enum resource_id_enum qed_mcp_get_mfw_res_id(enum qed_resources res_id)
{ {
enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID; enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID;
......
...@@ -430,6 +430,27 @@ int qed_mcp_set_led(struct qed_hwfn *p_hwfn, ...@@ -430,6 +430,27 @@ int qed_mcp_set_led(struct qed_hwfn *p_hwfn,
*/ */
int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len); int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len);
struct qed_nvm_image_att {
u32 start_addr;
u32 length;
};
/**
* @brief Allows reading a whole nvram image
*
* @param p_hwfn
* @param p_ptt
* @param image_id - image requested for reading
* @param p_buffer - allocated buffer into which to fill data
* @param buffer_len - length of the allocated buffer.
*
* @return 0 iff p_buffer now contains the nvram image.
*/
int qed_mcp_get_nvm_image(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
enum qed_nvm_images image_id,
u8 *p_buffer, u32 buffer_len);
/** /**
* @brief Bist register test * @brief Bist register test
* *
......
...@@ -120,6 +120,7 @@ union ramrod_data { ...@@ -120,6 +120,7 @@ union ramrod_data {
struct iscsi_spe_func_dstry iscsi_destroy; struct iscsi_spe_func_dstry iscsi_destroy;
struct iscsi_spe_conn_offload iscsi_conn_offload; struct iscsi_spe_conn_offload iscsi_conn_offload;
struct iscsi_conn_update_ramrod_params iscsi_conn_update; struct iscsi_conn_update_ramrod_params iscsi_conn_update;
struct iscsi_spe_conn_mac_update iscsi_conn_mac_update;
struct iscsi_spe_conn_termination iscsi_conn_terminate; struct iscsi_spe_conn_termination iscsi_conn_terminate;
struct vf_start_ramrod_data vf_start; struct vf_start_ramrod_data vf_start;
......
...@@ -24,6 +24,11 @@ struct qed_dev_fcoe_info { ...@@ -24,6 +24,11 @@ struct qed_dev_fcoe_info {
void __iomem *primary_dbq_rq_addr; void __iomem *primary_dbq_rq_addr;
void __iomem *secondary_bdq_rq_addr; void __iomem *secondary_bdq_rq_addr;
u64 wwpn;
u64 wwnn;
u8 num_cqs;
}; };
struct qed_fcoe_params_offload { struct qed_fcoe_params_offload {
......
...@@ -156,6 +156,11 @@ struct qed_dcbx_get { ...@@ -156,6 +156,11 @@ struct qed_dcbx_get {
struct qed_dcbx_admin_params local; struct qed_dcbx_admin_params local;
}; };
enum qed_nvm_images {
QED_NVM_IMAGE_ISCSI_CFG,
QED_NVM_IMAGE_FCOE_CFG,
};
enum qed_led_mode { enum qed_led_mode {
QED_LED_MODE_OFF, QED_LED_MODE_OFF,
QED_LED_MODE_ON, QED_LED_MODE_ON,
...@@ -360,6 +365,8 @@ struct qed_dev_info { ...@@ -360,6 +365,8 @@ struct qed_dev_info {
bool vxlan_enable; bool vxlan_enable;
bool gre_enable; bool gre_enable;
bool geneve_enable; bool geneve_enable;
u8 abs_pf_id;
}; };
enum qed_sb_type { enum qed_sb_type {
...@@ -628,6 +635,19 @@ struct qed_common_ops { ...@@ -628,6 +635,19 @@ struct qed_common_ops {
void (*chain_free)(struct qed_dev *cdev, void (*chain_free)(struct qed_dev *cdev,
struct qed_chain *p_chain); struct qed_chain *p_chain);
/**
* @brief nvm_get_image - reads an entire image from nvram
*
* @param cdev
* @param type - type of the request nvram image
* @param buf - preallocated buffer to fill with the image
* @param len - length of the allocated buffer
*
* @return 0 on success, error otherwise
*/
int (*nvm_get_image)(struct qed_dev *cdev,
enum qed_nvm_images type, u8 *buf, u16 len);
/** /**
* @brief get_coalesce - Get coalesce parameters in usec * @brief get_coalesce - Get coalesce parameters in usec
* *
......
...@@ -210,6 +210,11 @@ struct qed_iscsi_cb_ops { ...@@ -210,6 +210,11 @@ struct qed_iscsi_cb_ops {
* @param stats - pointer to struck that would be filled * @param stats - pointer to struck that would be filled
* we stats * we stats
* @return 0 on success, error otherwise. * @return 0 on success, error otherwise.
* @change_mac Change MAC of interface
* @param cdev
* @param handle - the connection handle.
* @param mac - new MAC to configure.
* @return 0 on success, otherwise error value.
*/ */
struct qed_iscsi_ops { struct qed_iscsi_ops {
const struct qed_common_ops *common; const struct qed_common_ops *common;
...@@ -248,6 +253,8 @@ struct qed_iscsi_ops { ...@@ -248,6 +253,8 @@ struct qed_iscsi_ops {
int (*get_stats)(struct qed_dev *cdev, int (*get_stats)(struct qed_dev *cdev,
struct qed_iscsi_stats *stats); struct qed_iscsi_stats *stats);
int (*change_mac)(struct qed_dev *cdev, u32 handle, const u8 *mac);
}; };
const struct qed_iscsi_ops *qed_get_iscsi_ops(void); const struct qed_iscsi_ops *qed_get_iscsi_ops(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment