Commit 4be41e92 authored by Sony Chacko's avatar Sony Chacko Committed by David S. Miller

qlcnic: 83xx data path routines

Add 83xx adapter data path routines
Update few 82xx adapter data path routines
Modify datapath resource allocation routines
Signed-off-by: default avatarAnirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: default avatarSucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: default avatarSritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: default avatarSony Chacko <sony.chacko@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7f966452
......@@ -431,6 +431,7 @@ struct qlcnic_adapter_stats {
u64 rx_dma_map_error;
u64 tx_dma_map_error;
u64 spurious_intr;
u64 mac_filter_limit_overrun;
};
/*
......@@ -469,6 +470,7 @@ struct qlcnic_host_sds_ring {
} ____cacheline_internodealigned_in_smp;
struct qlcnic_host_tx_ring {
int irq;
void __iomem *crb_intr_mask;
char name[IFNAMSIZ+4];
u16 ctx_id;
......@@ -477,6 +479,8 @@ struct qlcnic_host_tx_ring {
u32 num_desc;
void __iomem *crb_cmd_producer;
struct cmd_desc_type0 *desc_head;
struct qlcnic_adapter *adapter;
struct napi_struct napi;
struct qlcnic_cmd_buffer *cmd_buf_arr;
__le32 *hw_consumer;
......@@ -1402,7 +1406,7 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter);
int qlcnic_check_fw_status(struct qlcnic_adapter *adapter);
void qlcnic_watchdog_task(struct work_struct *work);
void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
struct qlcnic_host_rds_ring *rds_ring);
struct qlcnic_host_rds_ring *rds_ring, u8 ring_id);
int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max);
void qlcnic_set_multi(struct net_device *netdev);
void qlcnic_free_mac_list(struct qlcnic_adapter *adapter);
......@@ -1443,7 +1447,6 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *);
void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd);
void qlcnic_napi_del(struct qlcnic_adapter *);
int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int);
void qlcnic_free_sds_rings(struct qlcnic_recv_context *);
......@@ -1495,6 +1498,7 @@ struct qlcnic_nic_template {
void (*request_reset) (struct qlcnic_adapter *, u32);
void (*cancel_idc_work) (struct qlcnic_adapter *);
int (*napi_add)(struct qlcnic_adapter *, struct net_device *);
void (*napi_del)(struct qlcnic_adapter *);
void (*config_ipaddr)(struct qlcnic_adapter *, __be32, int);
irqreturn_t (*clear_legacy_intr)(struct qlcnic_adapter *);
};
......@@ -1670,6 +1674,11 @@ static inline int qlcnic_napi_add(struct qlcnic_adapter *adapter,
return adapter->nic_ops->napi_add(adapter, netdev);
}
static inline void qlcnic_napi_del(struct qlcnic_adapter *adapter)
{
adapter->nic_ops->napi_del(adapter);
}
static inline void qlcnic_napi_enable(struct qlcnic_adapter *adapter)
{
adapter->ahw->hw_ops->napi_enable(adapter);
......
......@@ -242,6 +242,7 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
.get_func_no = qlcnic_83xx_get_func_no,
.api_lock = qlcnic_83xx_cam_lock,
.api_unlock = qlcnic_83xx_cam_unlock,
.process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag,
.create_rx_ctx = qlcnic_83xx_create_rx_ctx,
.create_tx_ctx = qlcnic_83xx_create_tx_ctx,
.setup_link_event = qlcnic_83xx_setup_link_event,
......@@ -249,6 +250,8 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
.get_pci_info = qlcnic_83xx_get_pci_info,
.set_nic_info = qlcnic_83xx_set_nic_info,
.change_macvlan = qlcnic_83xx_sre_macaddr_change,
.napi_enable = qlcnic_83xx_napi_enable,
.napi_disable = qlcnic_83xx_napi_disable,
.config_intr_coal = qlcnic_83xx_config_intr_coal,
.config_rss = qlcnic_83xx_config_rss,
.config_hw_lro = qlcnic_83xx_config_hw_lro,
......@@ -262,6 +265,8 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
static struct qlcnic_nic_template qlcnic_83xx_ops = {
.config_bridged_mode = qlcnic_config_bridged_mode,
.config_led = qlcnic_config_led,
.napi_add = qlcnic_83xx_napi_add,
.napi_del = qlcnic_83xx_napi_del,
.config_ipaddr = qlcnic_83xx_config_ipaddr,
.clear_legacy_intr = qlcnic_83xx_clear_legacy_intr,
};
......
......@@ -193,8 +193,7 @@ void qlcnic_83xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
void qlcnic_83xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *, ulong);
int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *, ulong, u32);
void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *,
struct qlcnic_host_sds_ring *, int, u64 []);
void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *, int, u64 []);
int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *, u32);
int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *, u8);
int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *, u8);
......@@ -206,6 +205,11 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *);
int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *, int);
int qlcnic_83xx_napi_add(struct qlcnic_adapter *, struct net_device *);
void qlcnic_83xx_napi_del(struct qlcnic_adapter *);
void qlcnic_83xx_napi_enable(struct qlcnic_adapter *);
void qlcnic_83xx_napi_disable(struct qlcnic_adapter *);
void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32);
int qlcnic_ind_rd(struct qlcnic_adapter *, u32);
void qlcnic_83xx_get_stats(struct qlcnic_adapter *,
......
......@@ -498,36 +498,42 @@ qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config)
int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
{
void *addr;
int err;
int ring;
int err, ring;
struct qlcnic_recv_context *recv_ctx;
struct qlcnic_host_rds_ring *rds_ring;
struct qlcnic_host_sds_ring *sds_ring;
struct qlcnic_host_tx_ring *tx_ring;
__le32 *ptr;
struct pci_dev *pdev = adapter->pdev;
recv_ctx = adapter->recv_ctx;
tx_ring = adapter->tx_ring;
tx_ring->hw_consumer = (__le32 *) dma_alloc_coherent(&pdev->dev,
sizeof(u32), &tx_ring->hw_cons_phys_addr, GFP_KERNEL);
if (tx_ring->hw_consumer == NULL) {
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
ptr = (__le32 *)dma_alloc_coherent(&pdev->dev, sizeof(u32),
&tx_ring->hw_cons_phys_addr,
GFP_KERNEL);
if (ptr == NULL) {
dev_err(&pdev->dev, "failed to allocate tx consumer\n");
return -ENOMEM;
}
tx_ring->hw_consumer = ptr;
/* cmd desc ring */
addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring),
&tx_ring->phys_addr, GFP_KERNEL);
&tx_ring->phys_addr,
GFP_KERNEL);
if (addr == NULL) {
dev_err(&pdev->dev, "failed to allocate tx desc ring\n");
dev_err(&pdev->dev,
"failed to allocate tx desc ring\n");
err = -ENOMEM;
goto err_out_free;
}
tx_ring->desc_head = addr;
}
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &recv_ctx->rds_rings[ring];
......@@ -624,21 +630,24 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
recv_ctx = adapter->recv_ctx;
tx_ring = adapter->tx_ring;
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
if (tx_ring->hw_consumer != NULL) {
dma_free_coherent(&adapter->pdev->dev,
sizeof(u32),
dma_free_coherent(&adapter->pdev->dev, sizeof(u32),
tx_ring->hw_consumer,
tx_ring->hw_cons_phys_addr);
tx_ring->hw_consumer = NULL;
}
if (tx_ring->desc_head != NULL) {
dma_free_coherent(&adapter->pdev->dev,
TX_DESC_RINGSIZE(tx_ring),
tx_ring->desc_head, tx_ring->phys_addr);
tx_ring->desc_head,
tx_ring->phys_addr);
tx_ring->desc_head = NULL;
}
}
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &recv_ctx->rds_rings[ring];
......
......@@ -163,13 +163,12 @@ void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
{
struct qlcnic_recv_context *recv_ctx;
struct qlcnic_host_rds_ring *rds_ring;
struct qlcnic_host_tx_ring *tx_ring;
int ring;
recv_ctx = adapter->recv_ctx;
if (recv_ctx->rds_rings == NULL)
goto skip_rds;
return;
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &recv_ctx->rds_rings[ring];
......@@ -177,16 +176,6 @@ void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
rds_ring->rx_buf_arr = NULL;
}
kfree(recv_ctx->rds_rings);
skip_rds:
if (adapter->tx_ring == NULL)
return;
tx_ring = adapter->tx_ring;
vfree(tx_ring->cmd_buf_arr);
tx_ring->cmd_buf_arr = NULL;
kfree(adapter->tx_ring);
adapter->tx_ring = NULL;
}
int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
......@@ -194,31 +183,11 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
struct qlcnic_recv_context *recv_ctx;
struct qlcnic_host_rds_ring *rds_ring;
struct qlcnic_host_sds_ring *sds_ring;
struct qlcnic_host_tx_ring *tx_ring;
struct qlcnic_rx_buffer *rx_buf;
int ring, i, size;
struct qlcnic_cmd_buffer *cmd_buf_arr;
struct net_device *netdev = adapter->netdev;
size = sizeof(struct qlcnic_host_tx_ring);
tx_ring = kzalloc(size, GFP_KERNEL);
if (tx_ring == NULL) {
dev_err(&netdev->dev, "failed to allocate tx ring struct\n");
return -ENOMEM;
}
adapter->tx_ring = tx_ring;
tx_ring->num_desc = adapter->num_txd;
tx_ring->txq = netdev_get_tx_queue(netdev, 0);
cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring));
if (cmd_buf_arr == NULL) {
dev_err(&netdev->dev, "failed to allocate cmd buffer ring\n");
goto err_out;
}
tx_ring->cmd_buf_arr = cmd_buf_arr;
recv_ctx = adapter->recv_ctx;
size = adapter->max_rds_rings * sizeof(struct qlcnic_host_rds_ring);
......@@ -253,10 +222,11 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
}
rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring));
if (rds_ring->rx_buf_arr == NULL) {
dev_err(&netdev->dev, "Failed to allocate "
"rx buffer ring %d\n", ring);
dev_err(&netdev->dev,
"Failed to allocate rx buffer ring %d\n", ring);
goto err_out;
}
INIT_LIST_HEAD(&rds_ring->free_list);
/*
* Now go through all of them, set reference handles
......
......@@ -303,6 +303,7 @@ static struct qlcnic_nic_template qlcnic_ops = {
.request_reset = qlcnic_82xx_dev_request_reset,
.cancel_idc_work = qlcnic_82xx_cancel_idc_work,
.napi_add = qlcnic_82xx_napi_add,
.napi_del = qlcnic_82xx_napi_del,
.config_ipaddr = qlcnic_82xx_config_ipaddr,
.clear_legacy_intr = qlcnic_82xx_clear_legacy_intr,
};
......@@ -1201,7 +1202,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &adapter->recv_ctx->rds_rings[ring];
qlcnic_post_rx_buffers(adapter, rds_ring);
qlcnic_post_rx_buffers(adapter, rds_ring, ring);
}
qlcnic_set_multi(netdev);
......@@ -1380,21 +1381,11 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
{
int err = 0;
adapter->ahw = kzalloc(sizeof(struct qlcnic_hardware_context),
GFP_KERNEL);
if (!adapter->ahw) {
dev_err(&adapter->pdev->dev,
"Failed to allocate recv ctx resources for adapter\n");
err = -ENOMEM;
goto err_out;
}
adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context),
GFP_KERNEL);
if (!adapter->recv_ctx) {
dev_err(&adapter->pdev->dev,
"Failed to allocate recv ctx resources for adapter\n");
kfree(adapter->ahw);
adapter->ahw = NULL;
err = -ENOMEM;
goto err_out;
}
......@@ -1402,6 +1393,8 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
/* clear stats */
memset(&adapter->stats, 0, sizeof(adapter->stats));
err_out:
return err;
}
......@@ -1415,8 +1408,8 @@ static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter)
vfree(adapter->ahw->fw_dump.tmpl_hdr);
adapter->ahw->fw_dump.tmpl_hdr = NULL;
}
kfree(adapter->ahw);
adapter->ahw = NULL;
adapter->ahw->fw_dump.tmpl_hdr = NULL;
}
int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
......@@ -1436,6 +1429,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
adapter->max_sds_rings = 1;
adapter->ahw->diag_test = test;
adapter->ahw->linkup = 0;
ret = qlcnic_attach(adapter);
if (ret) {
......@@ -1452,7 +1446,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &adapter->recv_ctx->rds_rings[ring];
qlcnic_post_rx_buffers(adapter, rds_ring);
qlcnic_post_rx_buffers(adapter, rds_ring, ring);
}
if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
......@@ -1601,6 +1595,66 @@ qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count)
return -ENOMEM;
}
void qlcnic_free_tx_rings(struct qlcnic_adapter *adapter)
{
int ring;
struct qlcnic_host_tx_ring *tx_ring;
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
if (tx_ring && tx_ring->cmd_buf_arr != NULL) {
vfree(tx_ring->cmd_buf_arr);
tx_ring->cmd_buf_arr = NULL;
}
}
if (adapter->tx_ring != NULL)
kfree(adapter->tx_ring);
}
int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter,
struct net_device *netdev)
{
int ring, size, vector, index;
struct qlcnic_host_tx_ring *tx_ring;
struct qlcnic_cmd_buffer *cmd_buf_arr;
size = adapter->max_drv_tx_rings * sizeof(struct qlcnic_host_tx_ring);
tx_ring = kzalloc(size, GFP_KERNEL);
if (tx_ring == NULL) {
dev_err(&netdev->dev, "failed to allocate tx rings\n");
return -ENOMEM;
}
adapter->tx_ring = tx_ring;
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
tx_ring->num_desc = adapter->num_txd;
tx_ring->txq = netdev_get_tx_queue(netdev, ring);
cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring));
if (cmd_buf_arr == NULL) {
dev_err(&netdev->dev,
"failed to allocate cmd buffer ring\n");
qlcnic_free_tx_rings(adapter);
return -ENOMEM;
}
memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
tx_ring->cmd_buf_arr = cmd_buf_arr;
}
if (qlcnic_83xx_check(adapter)) {
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
tx_ring->adapter = adapter;
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
index = adapter->max_sds_rings + ring;
vector = adapter->msix_entries[index].vector;
tx_ring->irq = vector;
}
}
}
return 0;
}
static int __devinit
qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
......
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