Commit 1d6cff4f authored by Yuval Mintz's avatar Yuval Mintz Committed by David S. Miller

qed: Add iSCSI out of order packet handling.

This patch adds out of order packet handling for hardware offloaded
iSCSI. Out of order packet handling requires driver buffer allocation
and assistance.
Signed-off-by: default avatarArun Easi <arun.easi@cavium.com>
Signed-off-by: default avatarYuval Mintz <yuval.mintz@cavium.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fc831825
......@@ -6,4 +6,4 @@ qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \
qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
qed-$(CONFIG_QED_LL2) += qed_ll2.o
qed-$(CONFIG_QED_RDMA) += qed_roce.o
qed-$(CONFIG_QED_ISCSI) += qed_iscsi.o
qed-$(CONFIG_QED_ISCSI) += qed_iscsi.o qed_ooo.o
......@@ -383,6 +383,7 @@ struct qed_hwfn {
/* Protocol related */
bool using_ll2;
struct qed_ll2_info *p_ll2_info;
struct qed_ooo_info *p_ooo_info;
struct qed_rdma_info *p_rdma_info;
struct qed_iscsi_info *p_iscsi_info;
struct qed_pf_params pf_params;
......
......@@ -32,6 +32,7 @@
#include "qed_iscsi.h"
#include "qed_ll2.h"
#include "qed_mcp.h"
#include "qed_ooo.h"
#include "qed_reg_addr.h"
#include "qed_sp.h"
#include "qed_sriov.h"
......@@ -147,8 +148,10 @@ void qed_resc_free(struct qed_dev *cdev)
#ifdef CONFIG_QED_LL2
qed_ll2_free(p_hwfn, p_hwfn->p_ll2_info);
#endif
if (p_hwfn->hw_info.personality == QED_PCI_ISCSI)
if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
qed_iscsi_free(p_hwfn, p_hwfn->p_iscsi_info);
qed_ooo_free(p_hwfn, p_hwfn->p_ooo_info);
}
qed_iov_free(p_hwfn);
qed_dmae_info_free(p_hwfn);
qed_dcbx_info_free(p_hwfn, p_hwfn->p_dcbx_info);
......@@ -406,6 +409,7 @@ int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
int qed_resc_alloc(struct qed_dev *cdev)
{
struct qed_iscsi_info *p_iscsi_info;
struct qed_ooo_info *p_ooo_info;
#ifdef CONFIG_QED_LL2
struct qed_ll2_info *p_ll2_info;
#endif
......@@ -516,6 +520,10 @@ int qed_resc_alloc(struct qed_dev *cdev)
if (!p_iscsi_info)
goto alloc_no_mem;
p_hwfn->p_iscsi_info = p_iscsi_info;
p_ooo_info = qed_ooo_alloc(p_hwfn);
if (!p_ooo_info)
goto alloc_no_mem;
p_hwfn->p_ooo_info = p_ooo_info;
}
/* DMA info initialization */
......@@ -570,8 +578,10 @@ void qed_resc_setup(struct qed_dev *cdev)
if (p_hwfn->using_ll2)
qed_ll2_setup(p_hwfn, p_hwfn->p_ll2_info);
#endif
if (p_hwfn->hw_info.personality == QED_PCI_ISCSI)
if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
qed_iscsi_setup(p_hwfn, p_hwfn->p_iscsi_info);
qed_ooo_setup(p_hwfn, p_hwfn->p_ooo_info);
}
}
}
......
This diff is collapsed.
......@@ -41,6 +41,12 @@ enum qed_ll2_conn_type {
MAX_QED_LL2_RX_CONN_TYPE
};
enum qed_ll2_tx_dest {
QED_LL2_TX_DEST_NW, /* Light L2 TX Destination to the Network */
QED_LL2_TX_DEST_LB, /* Light L2 TX Destination to the Loopback */
QED_LL2_TX_DEST_MAX
};
struct qed_ll2_rx_packet {
struct list_head list_entry;
struct core_rx_bd_with_buff_len *rxq_bd;
......@@ -192,6 +198,8 @@ int qed_ll2_post_rx_buffer(struct qed_hwfn *p_hwfn,
* @param l4_hdr_offset_w L4 Header Offset from start of packet
* (in words). This is needed if both l4_csum
* and ipv6_ext are set
* @param e_tx_dest indicates if the packet is to be transmitted via
* loopback or to the network
* @param first_frag
* @param first_frag_len
* @param cookie
......@@ -206,6 +214,7 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
u16 vlan,
u8 bd_flags,
u16 l4_hdr_offset_w,
enum qed_ll2_tx_dest e_tx_dest,
enum qed_ll2_roce_flavor_type qed_roce_flavor,
dma_addr_t first_frag,
u16 first_frag_len, void *cookie, u8 notify_fw);
......
This diff is collapsed.
/* QLogic qed NIC Driver
* Copyright (c) 2015 QLogic Corporation
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
* this source tree.
*/
#ifndef _QED_OOO_H
#define _QED_OOO_H
#include <linux/types.h>
#include <linux/list.h>
#include <linux/slab.h>
#include "qed.h"
#define QED_MAX_NUM_ISLES 256
#define QED_MAX_NUM_OOO_HISTORY_ENTRIES 512
#define QED_OOO_LEFT_BUF 0
#define QED_OOO_RIGHT_BUF 1
struct qed_ooo_buffer {
struct list_head list_entry;
void *rx_buffer_virt_addr;
dma_addr_t rx_buffer_phys_addr;
u32 rx_buffer_size;
u16 packet_length;
u16 parse_flags;
u16 vlan;
u8 placement_offset;
};
struct qed_ooo_isle {
struct list_head list_entry;
struct list_head buffers_list;
};
struct qed_ooo_archipelago {
struct list_head list_entry;
struct list_head isles_list;
u32 cid;
};
struct qed_ooo_history {
struct ooo_opaque *p_cqes;
u32 head_idx;
u32 num_of_cqes;
};
struct qed_ooo_info {
struct list_head free_buffers_list;
struct list_head ready_buffers_list;
struct list_head free_isles_list;
struct list_head free_archipelagos_list;
struct list_head archipelagos_list;
struct qed_ooo_archipelago *p_archipelagos_mem;
struct qed_ooo_isle *p_isles_mem;
struct qed_ooo_history ooo_history;
u32 cur_isles_number;
u32 max_isles_number;
u32 gen_isles_number;
};
#if IS_ENABLED(CONFIG_QED_ISCSI)
void qed_ooo_save_history_entry(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
struct ooo_opaque *p_cqe);
struct qed_ooo_info *qed_ooo_alloc(struct qed_hwfn *p_hwfn);
void qed_ooo_release_connection_isles(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
u32 cid);
void qed_ooo_release_all_isles(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info);
void qed_ooo_setup(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info);
void qed_ooo_free(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info);
void qed_ooo_put_free_buffer(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
struct qed_ooo_buffer *p_buffer);
struct qed_ooo_buffer *
qed_ooo_get_free_buffer(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info);
void qed_ooo_put_ready_buffer(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
struct qed_ooo_buffer *p_buffer, u8 on_tail);
struct qed_ooo_buffer *
qed_ooo_get_ready_buffer(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info);
void qed_ooo_delete_isles(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
u32 cid, u8 drop_isle, u8 drop_size);
void qed_ooo_add_new_isle(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
u32 cid,
u8 ooo_isle, struct qed_ooo_buffer *p_buffer);
void qed_ooo_add_new_buffer(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
u32 cid,
u8 ooo_isle,
struct qed_ooo_buffer *p_buffer, u8 buffer_side);
void qed_ooo_join_isles(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info, u32 cid,
u8 left_isle);
#else /* IS_ENABLED(CONFIG_QED_ISCSI) */
static inline void qed_ooo_save_history_entry(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
struct ooo_opaque *p_cqe) {}
static inline struct qed_ooo_info *qed_ooo_alloc(
struct qed_hwfn *p_hwfn) { return NULL; }
static inline void
qed_ooo_release_connection_isles(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
u32 cid) {}
static inline void qed_ooo_release_all_isles(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info)
{}
static inline void qed_ooo_setup(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info) {}
static inline void qed_ooo_free(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info) {}
static inline void qed_ooo_put_free_buffer(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
struct qed_ooo_buffer *p_buffer) {}
static inline struct qed_ooo_buffer *
qed_ooo_get_free_buffer(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info) { return NULL; }
static inline void qed_ooo_put_ready_buffer(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
struct qed_ooo_buffer *p_buffer,
u8 on_tail) {}
static inline struct qed_ooo_buffer *
qed_ooo_get_ready_buffer(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info) { return NULL; }
static inline void qed_ooo_delete_isles(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
u32 cid, u8 drop_isle, u8 drop_size) {}
static inline void qed_ooo_add_new_isle(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
u32 cid, u8 ooo_isle,
struct qed_ooo_buffer *p_buffer) {}
static inline void qed_ooo_add_new_buffer(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info,
u32 cid, u8 ooo_isle,
struct qed_ooo_buffer *p_buffer,
u8 buffer_side) {}
static inline void qed_ooo_join_isles(struct qed_hwfn *p_hwfn,
struct qed_ooo_info *p_ooo_info, u32 cid,
u8 left_isle) {}
#endif /* IS_ENABLED(CONFIG_QED_ISCSI) */
#endif
......@@ -2771,6 +2771,7 @@ static int qed_roce_ll2_tx(struct qed_dev *cdev,
/* Tx header */
rc = qed_ll2_prepare_tx_packet(QED_LEADING_HWFN(cdev), roce_ll2->handle,
1 + pkt->n_seg, 0, flags, 0,
QED_LL2_TX_DEST_NW,
qed_roce_flavor, pkt->header.baddr,
pkt->header.len, pkt, 1);
if (rc) {
......
......@@ -26,6 +26,7 @@
#include "qed_int.h"
#include "qed_iscsi.h"
#include "qed_mcp.h"
#include "qed_ooo.h"
#include "qed_reg_addr.h"
#include "qed_sp.h"
#include "qed_sriov.h"
......@@ -281,6 +282,14 @@ qed_async_event_completion(struct qed_hwfn *p_hwfn,
case PROTOCOLID_ISCSI:
if (!IS_ENABLED(CONFIG_QED_ISCSI))
return -EINVAL;
if (p_eqe->opcode == ISCSI_EVENT_TYPE_ASYN_DELETE_OOO_ISLES) {
u32 cid = le32_to_cpu(p_eqe->data.iscsi_info.cid);
qed_ooo_release_connection_isles(p_hwfn,
p_hwfn->p_ooo_info,
cid);
return 0;
}
if (p_hwfn->p_iscsi_info->event_cb) {
struct qed_iscsi_info *p_iscsi = p_hwfn->p_iscsi_info;
......
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