Skip to content

Commit 7cf210d

Browse files
committed
Merge branch 'qlcnic-fixes'
Manish Chopra says: ==================== qlcnic: bug fixes This series fixes a data structure corruption bug in VF's async mailbox commands handling and an issue realted to napi poll budget in the driver. Please consider applying this series to "net" ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents cfaa218 + b8b2372 commit 7cf210d

File tree

4 files changed

+62
-48
lines changed

4 files changed

+62
-48
lines changed

drivers/net/ethernet/qlogic/qlcnic/qlcnic.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@
3737

3838
#define _QLCNIC_LINUX_MAJOR 5
3939
#define _QLCNIC_LINUX_MINOR 3
40-
#define _QLCNIC_LINUX_SUBVERSION 64
41-
#define QLCNIC_LINUX_VERSIONID "5.3.64"
40+
#define _QLCNIC_LINUX_SUBVERSION 65
41+
#define QLCNIC_LINUX_VERSIONID "5.3.65"
4242
#define QLCNIC_DRV_IDC_VER 0x01
4343
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
4444
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))

drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@
102102
#define QLCNIC_RESPONSE_DESC 0x05
103103
#define QLCNIC_LRO_DESC 0x12
104104

105-
#define QLCNIC_TX_POLL_BUDGET 128
106105
#define QLCNIC_TCP_HDR_SIZE 20
107106
#define QLCNIC_TCP_TS_OPTION_SIZE 12
108107
#define QLCNIC_FETCH_RING_ID(handle) ((handle) >> 63)
@@ -2008,7 +2007,6 @@ static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget)
20082007
struct qlcnic_host_tx_ring *tx_ring;
20092008
struct qlcnic_adapter *adapter;
20102009

2011-
budget = QLCNIC_TX_POLL_BUDGET;
20122010
tx_ring = container_of(napi, struct qlcnic_host_tx_ring, napi);
20132011
adapter = tx_ring->adapter;
20142012
work_done = qlcnic_process_cmd_ring(adapter, tx_ring, budget);

drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,8 @@ struct qlcnic_vf_info {
156156
spinlock_t vlan_list_lock; /* Lock for VLAN list */
157157
};
158158

159-
struct qlcnic_async_work_list {
159+
struct qlcnic_async_cmd {
160160
struct list_head list;
161-
struct work_struct work;
162-
void *ptr;
163161
struct qlcnic_cmd_args *cmd;
164162
};
165163

@@ -168,7 +166,10 @@ struct qlcnic_back_channel {
168166
struct workqueue_struct *bc_trans_wq;
169167
struct workqueue_struct *bc_async_wq;
170168
struct workqueue_struct *bc_flr_wq;
171-
struct list_head async_list;
169+
struct qlcnic_adapter *adapter;
170+
struct list_head async_cmd_list;
171+
struct work_struct vf_async_work;
172+
spinlock_t queue_lock; /* async_cmd_list queue lock */
172173
};
173174

174175
struct qlcnic_sriov {

drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c

Lines changed: 55 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#define QLC_83XX_VF_RESET_FAIL_THRESH 8
3030
#define QLC_BC_CMD_MAX_RETRY_CNT 5
3131

32+
static void qlcnic_sriov_handle_async_issue_cmd(struct work_struct *work);
3233
static void qlcnic_sriov_vf_free_mac_list(struct qlcnic_adapter *);
3334
static int qlcnic_sriov_alloc_bc_mbx_args(struct qlcnic_cmd_args *, u32);
3435
static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *);
@@ -177,7 +178,10 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
177178
}
178179

179180
bc->bc_async_wq = wq;
180-
INIT_LIST_HEAD(&bc->async_list);
181+
INIT_LIST_HEAD(&bc->async_cmd_list);
182+
INIT_WORK(&bc->vf_async_work, qlcnic_sriov_handle_async_issue_cmd);
183+
spin_lock_init(&bc->queue_lock);
184+
bc->adapter = adapter;
181185

182186
for (i = 0; i < num_vfs; i++) {
183187
vf = &sriov->vf_info[i];
@@ -1517,17 +1521,21 @@ static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac,
15171521

15181522
void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc)
15191523
{
1520-
struct list_head *head = &bc->async_list;
1521-
struct qlcnic_async_work_list *entry;
1524+
struct list_head *head = &bc->async_cmd_list;
1525+
struct qlcnic_async_cmd *entry;
15221526

15231527
flush_workqueue(bc->bc_async_wq);
1528+
cancel_work_sync(&bc->vf_async_work);
1529+
1530+
spin_lock(&bc->queue_lock);
15241531
while (!list_empty(head)) {
1525-
entry = list_entry(head->next, struct qlcnic_async_work_list,
1532+
entry = list_entry(head->next, struct qlcnic_async_cmd,
15261533
list);
1527-
cancel_work_sync(&entry->work);
15281534
list_del(&entry->list);
1535+
kfree(entry->cmd);
15291536
kfree(entry);
15301537
}
1538+
spin_unlock(&bc->queue_lock);
15311539
}
15321540

15331541
void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
@@ -1587,57 +1595,64 @@ void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
15871595

15881596
static void qlcnic_sriov_handle_async_issue_cmd(struct work_struct *work)
15891597
{
1590-
struct qlcnic_async_work_list *entry;
1591-
struct qlcnic_adapter *adapter;
1598+
struct qlcnic_async_cmd *entry, *tmp;
1599+
struct qlcnic_back_channel *bc;
15921600
struct qlcnic_cmd_args *cmd;
1601+
struct list_head *head;
1602+
LIST_HEAD(del_list);
1603+
1604+
bc = container_of(work, struct qlcnic_back_channel, vf_async_work);
1605+
head = &bc->async_cmd_list;
1606+
1607+
spin_lock(&bc->queue_lock);
1608+
list_splice_init(head, &del_list);
1609+
spin_unlock(&bc->queue_lock);
1610+
1611+
list_for_each_entry_safe(entry, tmp, &del_list, list) {
1612+
list_del(&entry->list);
1613+
cmd = entry->cmd;
1614+
__qlcnic_sriov_issue_cmd(bc->adapter, cmd);
1615+
kfree(entry);
1616+
}
1617+
1618+
if (!list_empty(head))
1619+
queue_work(bc->bc_async_wq, &bc->vf_async_work);
15931620

1594-
entry = container_of(work, struct qlcnic_async_work_list, work);
1595-
adapter = entry->ptr;
1596-
cmd = entry->cmd;
1597-
__qlcnic_sriov_issue_cmd(adapter, cmd);
15981621
return;
15991622
}
16001623

1601-
static struct qlcnic_async_work_list *
1602-
qlcnic_sriov_get_free_node_async_work(struct qlcnic_back_channel *bc)
1624+
static struct qlcnic_async_cmd *
1625+
qlcnic_sriov_alloc_async_cmd(struct qlcnic_back_channel *bc,
1626+
struct qlcnic_cmd_args *cmd)
16031627
{
1604-
struct list_head *node;
1605-
struct qlcnic_async_work_list *entry = NULL;
1606-
u8 empty = 0;
1628+
struct qlcnic_async_cmd *entry = NULL;
16071629

1608-
list_for_each(node, &bc->async_list) {
1609-
entry = list_entry(node, struct qlcnic_async_work_list, list);
1610-
if (!work_pending(&entry->work)) {
1611-
empty = 1;
1612-
break;
1613-
}
1614-
}
1630+
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
1631+
if (!entry)
1632+
return NULL;
16151633

1616-
if (!empty) {
1617-
entry = kzalloc(sizeof(struct qlcnic_async_work_list),
1618-
GFP_ATOMIC);
1619-
if (entry == NULL)
1620-
return NULL;
1621-
list_add_tail(&entry->list, &bc->async_list);
1622-
}
1634+
entry->cmd = cmd;
1635+
1636+
spin_lock(&bc->queue_lock);
1637+
list_add_tail(&entry->list, &bc->async_cmd_list);
1638+
spin_unlock(&bc->queue_lock);
16231639

16241640
return entry;
16251641
}
16261642

16271643
static void qlcnic_sriov_schedule_async_cmd(struct qlcnic_back_channel *bc,
1628-
work_func_t func, void *data,
16291644
struct qlcnic_cmd_args *cmd)
16301645
{
1631-
struct qlcnic_async_work_list *entry = NULL;
1646+
struct qlcnic_async_cmd *entry = NULL;
16321647

1633-
entry = qlcnic_sriov_get_free_node_async_work(bc);
1634-
if (!entry)
1648+
entry = qlcnic_sriov_alloc_async_cmd(bc, cmd);
1649+
if (!entry) {
1650+
qlcnic_free_mbx_args(cmd);
1651+
kfree(cmd);
16351652
return;
1653+
}
16361654

1637-
entry->ptr = data;
1638-
entry->cmd = cmd;
1639-
INIT_WORK(&entry->work, func);
1640-
queue_work(bc->bc_async_wq, &entry->work);
1655+
queue_work(bc->bc_async_wq, &bc->vf_async_work);
16411656
}
16421657

16431658
static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *adapter,
@@ -1649,8 +1664,8 @@ static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *adapter,
16491664
if (adapter->need_fw_reset)
16501665
return -EIO;
16511666

1652-
qlcnic_sriov_schedule_async_cmd(bc, qlcnic_sriov_handle_async_issue_cmd,
1653-
adapter, cmd);
1667+
qlcnic_sriov_schedule_async_cmd(bc, cmd);
1668+
16541669
return 0;
16551670
}
16561671

0 commit comments

Comments
 (0)