Commit 012ec812 authored by Himanshu Madhani's avatar Himanshu Madhani Committed by David S. Miller

qlcnic: Multi Tx queue support for 82xx Series adapter.

o  82xx firmware allows support for multiple Tx queues. This
   patch will enable multi Tx queue support for 82xx series
   adapter. Max number of Tx queues supported will be 8.
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 954c3967
...@@ -97,6 +97,9 @@ ...@@ -97,6 +97,9 @@
#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \ #define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
+ MGMT_CMD_DESC_RESV) + MGMT_CMD_DESC_RESV)
#define QLCNIC_MAX_TX_TIMEOUTS 2 #define QLCNIC_MAX_TX_TIMEOUTS 2
#define QLCNIC_MAX_TX_RINGS 8
#define QLCNIC_MAX_SDS_RINGS 8
/* /*
* Following are the states of the Phantom. Phantom will set them and * Following are the states of the Phantom. Phantom will set them and
* Host will read to check if the fields are correct. * Host will read to check if the fields are correct.
...@@ -515,6 +518,7 @@ struct qlcnic_host_sds_ring { ...@@ -515,6 +518,7 @@ struct qlcnic_host_sds_ring {
u32 num_desc; u32 num_desc;
void __iomem *crb_sts_consumer; void __iomem *crb_sts_consumer;
struct qlcnic_host_tx_ring *tx_ring;
struct status_desc *desc_head; struct status_desc *desc_head;
struct qlcnic_adapter *adapter; struct qlcnic_adapter *adapter;
struct napi_struct napi; struct napi_struct napi;
...@@ -532,9 +536,17 @@ struct qlcnic_host_tx_ring { ...@@ -532,9 +536,17 @@ struct qlcnic_host_tx_ring {
void __iomem *crb_intr_mask; void __iomem *crb_intr_mask;
char name[IFNAMSIZ + 12]; char name[IFNAMSIZ + 12];
u16 ctx_id; u16 ctx_id;
u32 state;
u32 producer; u32 producer;
u32 sw_consumer; u32 sw_consumer;
u32 num_desc; u32 num_desc;
u64 xmit_on;
u64 xmit_off;
u64 xmit_called;
u64 xmit_finished;
void __iomem *crb_cmd_producer; void __iomem *crb_cmd_producer;
struct cmd_desc_type0 *desc_head; struct cmd_desc_type0 *desc_head;
struct qlcnic_adapter *adapter; struct qlcnic_adapter *adapter;
...@@ -559,7 +571,6 @@ struct qlcnic_recv_context { ...@@ -559,7 +571,6 @@ struct qlcnic_recv_context {
u32 state; u32 state;
u16 context_id; u16 context_id;
u16 virt_port; u16 virt_port;
}; };
/* HW context creation */ /* HW context creation */
...@@ -604,6 +615,7 @@ struct qlcnic_recv_context { ...@@ -604,6 +615,7 @@ struct qlcnic_recv_context {
#define QLCNIC_CAP0_LRO_CONTIGUOUS (1 << 8) #define QLCNIC_CAP0_LRO_CONTIGUOUS (1 << 8)
#define QLCNIC_CAP0_VALIDOFF (1 << 11) #define QLCNIC_CAP0_VALIDOFF (1 << 11)
#define QLCNIC_CAP0_LRO_MSS (1 << 21) #define QLCNIC_CAP0_LRO_MSS (1 << 21)
#define QLCNIC_CAP0_TX_MULTI (1 << 22)
/* /*
* Context state * Context state
...@@ -814,6 +826,7 @@ struct qlcnic_mac_list_s { ...@@ -814,6 +826,7 @@ struct qlcnic_mac_list_s {
#define QLCNIC_FW_CAPABILITY_BDG BIT_8 #define QLCNIC_FW_CAPABILITY_BDG BIT_8
#define QLCNIC_FW_CAPABILITY_FVLANTX BIT_9 #define QLCNIC_FW_CAPABILITY_FVLANTX BIT_9
#define QLCNIC_FW_CAPABILITY_HW_LRO BIT_10 #define QLCNIC_FW_CAPABILITY_HW_LRO BIT_10
#define QLCNIC_FW_CAPABILITY_2_MULTI_TX BIT_4
#define QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK BIT_27 #define QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK BIT_27
#define QLCNIC_FW_CAPABILITY_MORE_CAPS BIT_31 #define QLCNIC_FW_CAPABILITY_MORE_CAPS BIT_31
...@@ -922,6 +935,7 @@ struct qlcnic_ipaddr { ...@@ -922,6 +935,7 @@ struct qlcnic_ipaddr {
#define QLCNIC_BEACON_DISABLE 0xD #define QLCNIC_BEACON_DISABLE 0xD
#define QLCNIC_DEF_NUM_STS_DESC_RINGS 4 #define QLCNIC_DEF_NUM_STS_DESC_RINGS 4
#define QLCNIC_DEF_NUM_TX_RINGS 4
#define QLCNIC_MSIX_TBL_SPACE 8192 #define QLCNIC_MSIX_TBL_SPACE 8192
#define QLCNIC_PCI_REG_MSIX_TBL 0x44 #define QLCNIC_PCI_REG_MSIX_TBL 0x44
#define QLCNIC_MSIX_TBL_PGSIZE 4096 #define QLCNIC_MSIX_TBL_PGSIZE 4096
...@@ -937,6 +951,7 @@ struct qlcnic_ipaddr { ...@@ -937,6 +951,7 @@ struct qlcnic_ipaddr {
#define __QLCNIC_DIAG_RES_ALLOC 6 #define __QLCNIC_DIAG_RES_ALLOC 6
#define __QLCNIC_LED_ENABLE 7 #define __QLCNIC_LED_ENABLE 7
#define __QLCNIC_ELB_INPROGRESS 8 #define __QLCNIC_ELB_INPROGRESS 8
#define __QLCNIC_MULTI_TX_UNIQUE 9
#define __QLCNIC_SRIOV_ENABLE 10 #define __QLCNIC_SRIOV_ENABLE 10
#define __QLCNIC_SRIOV_CAPABLE 11 #define __QLCNIC_SRIOV_CAPABLE 11
#define __QLCNIC_MBX_POLL_ENABLE 12 #define __QLCNIC_MBX_POLL_ENABLE 12
...@@ -1482,7 +1497,8 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter); ...@@ -1482,7 +1497,8 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter);
void qlcnic_reset_rx_buffers_list(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_rx_buffers(struct qlcnic_adapter *adapter);
void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter); void qlcnic_release_tx_buffers(struct qlcnic_adapter *,
struct qlcnic_host_tx_ring *);
int qlcnic_check_fw_status(struct qlcnic_adapter *adapter); int qlcnic_check_fw_status(struct qlcnic_adapter *adapter);
void qlcnic_watchdog_task(struct work_struct *work); void qlcnic_watchdog_task(struct work_struct *work);
...@@ -1543,6 +1559,7 @@ void qlcnic_free_sds_rings(struct qlcnic_recv_context *); ...@@ -1543,6 +1559,7 @@ void qlcnic_free_sds_rings(struct qlcnic_recv_context *);
void qlcnic_advert_link_change(struct qlcnic_adapter *, int); void qlcnic_advert_link_change(struct qlcnic_adapter *, int);
void qlcnic_free_tx_rings(struct qlcnic_adapter *); void qlcnic_free_tx_rings(struct qlcnic_adapter *);
int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *); int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *);
void qlcnic_dump_mbx(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter); void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter); void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
...@@ -1605,6 +1622,26 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring) ...@@ -1605,6 +1622,26 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
tx_ring->producer; tx_ring->producer;
} }
static inline int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter,
struct net_device *netdev)
{
int err, tx_q;
tx_q = adapter->max_drv_tx_rings;
netdev->num_tx_queues = tx_q;
netdev->real_num_tx_queues = tx_q;
err = netif_set_real_num_tx_queues(netdev, tx_q);
if (err)
dev_err(&adapter->pdev->dev, "failed to set %d Tx queues\n",
tx_q);
else
dev_info(&adapter->pdev->dev, "set %d Tx queues\n", tx_q);
return err;
}
struct qlcnic_nic_template { struct qlcnic_nic_template {
int (*config_bridged_mode) (struct qlcnic_adapter *, u32); int (*config_bridged_mode) (struct qlcnic_adapter *, u32);
int (*config_led) (struct qlcnic_adapter *, u32, u32); int (*config_led) (struct qlcnic_adapter *, u32, u32);
...@@ -1932,15 +1969,42 @@ static inline void qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, ...@@ -1932,15 +1969,42 @@ static inline void qlcnic_config_ipaddr(struct qlcnic_adapter *adapter,
adapter->nic_ops->config_ipaddr(adapter, ip, cmd); adapter->nic_ops->config_ipaddr(adapter, ip, cmd);
} }
static inline bool qlcnic_check_multi_tx(struct qlcnic_adapter *adapter)
{
return test_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state);
}
static inline void qlcnic_disable_multi_tx(struct qlcnic_adapter *adapter)
{
test_and_clear_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state);
adapter->max_drv_tx_rings = 1;
}
/* When operating in a muti tx mode, driver needs to write 0x1
* to src register, instead of 0x0 to disable receiving interrupt.
*/
static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring) static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
{ {
struct qlcnic_adapter *adapter = sds_ring->adapter;
if (qlcnic_check_multi_tx(adapter) &&
(adapter->flags & QLCNIC_MSIX_ENABLED))
writel(0x1, sds_ring->crb_intr_mask);
else
writel(0, sds_ring->crb_intr_mask); writel(0, sds_ring->crb_intr_mask);
} }
/* When operating in a muti tx mode, driver needs to write 0x0
* to src register, instead of 0x1 to enable receiving interrupts.
*/
static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring) static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
{ {
struct qlcnic_adapter *adapter = sds_ring->adapter; struct qlcnic_adapter *adapter = sds_ring->adapter;
if (qlcnic_check_multi_tx(adapter) &&
(adapter->flags & QLCNIC_MSIX_ENABLED))
writel(0, sds_ring->crb_intr_mask);
else
writel(0x1, sds_ring->crb_intr_mask); writel(0x1, sds_ring->crb_intr_mask);
if (!QLCNIC_IS_MSI_FAMILY(adapter)) if (!QLCNIC_IS_MSI_FAMILY(adapter))
......
...@@ -695,7 +695,7 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter, ...@@ -695,7 +695,7 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter, static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
u32 data[]); u32 data[]);
static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter, void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *cmd) struct qlcnic_cmd_args *cmd)
{ {
int i; int i;
...@@ -1691,7 +1691,7 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) ...@@ -1691,7 +1691,7 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
/* Make sure carrier is off and queue is stopped during loopback */ /* Make sure carrier is off and queue is stopped during loopback */
if (netif_running(netdev)) { if (netif_running(netdev)) {
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_stop_queue(netdev); netif_tx_stop_all_queues(netdev);
} }
ret = qlcnic_do_lb_test(adapter, mode); ret = qlcnic_do_lb_test(adapter, mode);
......
...@@ -387,7 +387,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, ...@@ -387,7 +387,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
return -EIO; return -EIO;
tx_ring = adapter->tx_ring; tx_ring = &adapter->tx_ring[0];
__netif_tx_lock_bh(tx_ring->txq); __netif_tx_lock_bh(tx_ring->txq);
producer = tx_ring->producer; producer = tx_ring->producer;
......
...@@ -87,6 +87,7 @@ enum qlcnic_regs { ...@@ -87,6 +87,7 @@ enum qlcnic_regs {
#define QLCNIC_CMD_CONFIG_VPORT 0x32 #define QLCNIC_CMD_CONFIG_VPORT 0x32
#define QLCNIC_CMD_GET_MAC_STATS 0x37 #define QLCNIC_CMD_GET_MAC_STATS 0x37
#define QLCNIC_CMD_82XX_SET_DRV_VER 0x38 #define QLCNIC_CMD_82XX_SET_DRV_VER 0x38
#define QLCNIC_CMD_MQ_TX_CONFIG_INTR 0x39
#define QLCNIC_CMD_GET_LED_STATUS 0x3C #define QLCNIC_CMD_GET_LED_STATUS 0x3C
#define QLCNIC_CMD_CONFIGURE_RSS 0x41 #define QLCNIC_CMD_CONFIGURE_RSS 0x41
#define QLCNIC_CMD_CONFIG_INTR_COAL 0x43 #define QLCNIC_CMD_CONFIG_INTR_COAL 0x43
...@@ -177,6 +178,8 @@ int qlcnic_82xx_setup_intr(struct qlcnic_adapter *, u8); ...@@ -177,6 +178,8 @@ int qlcnic_82xx_setup_intr(struct qlcnic_adapter *, u8);
irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *); irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *);
int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter, int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *); struct qlcnic_cmd_args *);
int qlcnic_82xx_mq_intrpt(struct qlcnic_adapter *, int);
int qlcnic_82xx_config_intrpt(struct qlcnic_adapter *, u8);
int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *); int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *);
int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *, int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *,
struct qlcnic_host_tx_ring *tx_ring, int); struct qlcnic_host_tx_ring *tx_ring, int);
......
...@@ -127,12 +127,12 @@ void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter) ...@@ -127,12 +127,12 @@ void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter)
} }
} }
void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter) void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
struct qlcnic_host_tx_ring *tx_ring)
{ {
struct qlcnic_cmd_buffer *cmd_buf; struct qlcnic_cmd_buffer *cmd_buf;
struct qlcnic_skb_frag *buffrag; struct qlcnic_skb_frag *buffrag;
int i, j; int i, j;
struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
cmd_buf = tx_ring->cmd_buf_arr; cmd_buf = tx_ring->cmd_buf_arr;
for (i = 0; i < tx_ring->num_desc; i++) { for (i = 0; i < tx_ring->num_desc; i++) {
...@@ -241,7 +241,12 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) ...@@ -241,7 +241,12 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
sds_ring->irq = adapter->msix_entries[ring].vector; sds_ring->irq = adapter->msix_entries[ring].vector;
sds_ring->adapter = adapter; sds_ring->adapter = adapter;
sds_ring->num_desc = adapter->num_rxd; sds_ring->num_desc = adapter->num_rxd;
if (qlcnic_82xx_check(adapter)) {
if (qlcnic_check_multi_tx(adapter))
sds_ring->tx_ring = &adapter->tx_ring[ring];
else
sds_ring->tx_ring = &adapter->tx_ring[0];
}
for (i = 0; i < NUM_RCV_DESC_RINGS; i++) for (i = 0; i < NUM_RCV_DESC_RINGS; i++)
INIT_LIST_HEAD(&sds_ring->free_list[i]); INIT_LIST_HEAD(&sds_ring->free_list[i]);
} }
......
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