Skip to content

Commit

Permalink
qlcnic: release device resources during interface down
Browse files Browse the repository at this point in the history
Previously we were allocating device resources during probe and
release them during remove.
Now alloc during interface up and release in interface down.
This helps in device performance, as it doesn't need to keep
track of inactive resources.

Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Amit Kumar Salecha authored and David S. Miller committed Jun 23, 2010
1 parent 42f65cb commit 8a15ad1
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 37 deletions.
4 changes: 4 additions & 0 deletions drivers/net/qlcnic/qlcnic.h
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,10 @@ void __iomem *qlcnic_get_ioaddr(struct qlcnic_adapter *, u32);
int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter);
void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter);

int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter);
void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter);

void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter);
void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter);
void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter);

Expand Down
50 changes: 35 additions & 15 deletions drivers/net/qlcnic/qlcnic_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
for (i = 0; i < nrds_rings; i++) {

rds_ring = &recv_ctx->rds_rings[i];
rds_ring->producer = 0;

prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr);
prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc);
Expand All @@ -193,6 +194,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
for (i = 0; i < nsds_rings; i++) {

sds_ring = &recv_ctx->sds_rings[i];
sds_ring->consumer = 0;
memset(sds_ring->desc_head, 0, STATUS_DESC_RINGSIZE(sds_ring));

prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr);
prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc);
Expand Down Expand Up @@ -293,6 +296,11 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
dma_addr_t rq_phys_addr, rsp_phys_addr;
struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;

/* reset host resources */
tx_ring->producer = 0;
tx_ring->sw_consumer = 0;
*(tx_ring->hw_consumer) = 0;

rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
rq_addr = pci_alloc_consistent(adapter->pdev,
rq_size, &rq_phys_addr);
Expand Down Expand Up @@ -476,38 +484,50 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
sds_ring->desc_head = (struct status_desc *)addr;
}


err = qlcnic_fw_cmd_create_rx_ctx(adapter);
if (err)
goto err_out_free;
err = qlcnic_fw_cmd_create_tx_ctx(adapter);
if (err)
goto err_out_free;

set_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
return 0;

err_out_free:
qlcnic_free_hw_resources(adapter);
return err;
}

void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)

int qlcnic_fw_create_ctx(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;
int ring;
int err;

err = qlcnic_fw_cmd_create_rx_ctx(adapter);
if (err)
return err;

err = qlcnic_fw_cmd_create_tx_ctx(adapter);
if (err) {
qlcnic_fw_cmd_destroy_rx_ctx(adapter);
return err;
}

set_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
return 0;
}

void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
{
if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
qlcnic_fw_cmd_destroy_rx_ctx(adapter);
qlcnic_fw_cmd_destroy_tx_ctx(adapter);

/* Allow dma queues to drain after context reset */
msleep(20);
}
}

void qlcnic_free_hw_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;
int ring;

recv_ctx = &adapter->recv_ctx;

Expand Down
7 changes: 5 additions & 2 deletions drivers/net/qlcnic/qlcnic_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
for (i = 0; diag_registers[i] != -1; i++)
regs_buff[i] = QLCRD32(adapter, diag_registers[i]);

if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
return;

regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/
Expand Down Expand Up @@ -833,6 +833,9 @@ static int qlcnic_blink_led(struct net_device *dev, u32 val)
struct qlcnic_adapter *adapter = netdev_priv(dev);
int ret;

if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
return -EIO;

ret = adapter->nic_ops->config_led(adapter, 1, 0xf);
if (ret) {
dev_err(&adapter->pdev->dev,
Expand Down Expand Up @@ -904,7 +907,7 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);

if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
return -EINVAL;

/*
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/qlcnic/qlcnic_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,

i = 0;

if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
return -EIO;

tx_ring = adapter->tx_ring;
Expand Down Expand Up @@ -431,7 +431,7 @@ void qlcnic_set_multi(struct net_device *netdev)
u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
u32 mode = VPORT_MISS_MODE_DROP;

if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
return;

qlcnic_nic_add_mac(adapter, adapter->mac_addr);
Expand Down
26 changes: 26 additions & 0 deletions drivers/net/qlcnic/qlcnic_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,32 @@ void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter)
}
}

void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter)
{
struct qlcnic_recv_context *recv_ctx;
struct qlcnic_host_rds_ring *rds_ring;
struct qlcnic_rx_buffer *rx_buf;
int i, ring;

recv_ctx = &adapter->recv_ctx;
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &recv_ctx->rds_rings[ring];

spin_lock(&rds_ring->lock);

INIT_LIST_HEAD(&rds_ring->free_list);

rx_buf = rds_ring->rx_buf_arr;
for (i = 0; i < rds_ring->num_desc; i++) {
list_add_tail(&rx_buf->list,
&rds_ring->free_list);
rx_buf++;
}

spin_unlock(&rds_ring->lock);
}
}

void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter)
{
struct qlcnic_cmd_buffer *cmd_buf;
Expand Down
60 changes: 42 additions & 18 deletions drivers/net/qlcnic/qlcnic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EINVAL;

if (netif_running(netdev)) {
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
netif_device_detach(netdev);
qlcnic_napi_disable(adapter);
}
Expand All @@ -355,7 +355,7 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
qlcnic_set_multi(adapter->netdev);

if (netif_running(netdev)) {
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
netif_device_attach(netdev);
qlcnic_napi_enable(adapter);
}
Expand Down Expand Up @@ -877,9 +877,23 @@ qlcnic_init_coalesce_defaults(struct qlcnic_adapter *adapter)
static int
__qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
{
int ring;
struct qlcnic_host_rds_ring *rds_ring;

if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
return -EIO;

if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
return 0;

if (qlcnic_fw_create_ctx(adapter))
return -EIO;

for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &adapter->recv_ctx.rds_rings[ring];
qlcnic_post_rx_buffers(adapter, ring, rds_ring);
}

qlcnic_set_multi(netdev);
qlcnic_fw_cmd_set_mtu(adapter, netdev->mtu);

Expand Down Expand Up @@ -936,6 +950,9 @@ __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)

qlcnic_napi_disable(adapter);

qlcnic_fw_destroy_ctx(adapter);

qlcnic_reset_rx_buffers_list(adapter);
qlcnic_release_tx_buffers(adapter);
spin_unlock(&adapter->tx_clean_lock);
}
Expand All @@ -957,21 +974,19 @@ qlcnic_attach(struct qlcnic_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
int err, ring;
struct qlcnic_host_rds_ring *rds_ring;
int err;

if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC)
return 0;


err = qlcnic_napi_add(adapter, netdev);
if (err)
return err;

err = qlcnic_alloc_sw_resources(adapter);
if (err) {
dev_err(&pdev->dev, "Error in setting sw resources\n");
return err;
goto err_out_napi_del;
}

err = qlcnic_alloc_hw_resources(adapter);
Expand All @@ -980,16 +995,10 @@ qlcnic_attach(struct qlcnic_adapter *adapter)
goto err_out_free_sw;
}


for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &adapter->recv_ctx.rds_rings[ring];
qlcnic_post_rx_buffers(adapter, ring, rds_ring);
}

err = qlcnic_request_irq(adapter);
if (err) {
dev_err(&pdev->dev, "failed to setup interrupt\n");
goto err_out_free_rxbuf;
goto err_out_free_hw;
}

qlcnic_init_coalesce_defaults(adapter);
Expand All @@ -999,11 +1008,12 @@ qlcnic_attach(struct qlcnic_adapter *adapter)
adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC;
return 0;

err_out_free_rxbuf:
qlcnic_release_rx_buffers(adapter);
err_out_free_hw:
qlcnic_free_hw_resources(adapter);
err_out_free_sw:
qlcnic_free_sw_resources(adapter);
err_out_napi_del:
qlcnic_napi_del(adapter);
return err;
}

Expand Down Expand Up @@ -1038,6 +1048,8 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
}
}

qlcnic_fw_destroy_ctx(adapter);

qlcnic_detach(adapter);

adapter->diag_test = 0;
Expand All @@ -1056,6 +1068,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_host_sds_ring *sds_ring;
struct qlcnic_host_rds_ring *rds_ring;
int ring;
int ret;

Expand All @@ -1075,6 +1088,17 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
return ret;
}

ret = qlcnic_fw_create_ctx(adapter);
if (ret) {
qlcnic_detach(adapter);
return ret;
}

for (ring = 0; ring < adapter->max_rds_rings; ring++) {
rds_ring = &adapter->recv_ctx.rds_rings[ring];
qlcnic_post_rx_buffers(adapter, ring, rds_ring);
}

if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &adapter->recv_ctx.sds_rings[ring];
Expand Down Expand Up @@ -2636,7 +2660,7 @@ qlcnic_store_bridged_mode(struct device *dev,
if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG))
goto err_out;

if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
goto err_out;

if (strict_strtoul(buf, 2, &new))
Expand Down Expand Up @@ -2944,7 +2968,7 @@ static int qlcnic_netdev_event(struct notifier_block *this,
if (!adapter)
goto done;

if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
goto done;

qlcnic_config_indev_addr(dev, event);
Expand Down Expand Up @@ -2980,7 +3004,7 @@ qlcnic_inetaddr_event(struct notifier_block *this,
if (!adapter)
goto done;

if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
goto done;

switch (event) {
Expand Down

0 comments on commit 8a15ad1

Please sign in to comment.