mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-19 05:04:20 +00:00
Merge branch 'ionic-locking-and-filter-fixes'
Shannon Nelson says: ==================== ionic: locking and filter fixes These patches address an ethtool show regs problem, some locking sightings, and issues with RSS hash and filter_id tracking after a managed FW update. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4932893924
5 changed files with 60 additions and 40 deletions
|
@ -103,15 +103,18 @@ static void ionic_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
|
||||||
void *p)
|
void *p)
|
||||||
{
|
{
|
||||||
struct ionic_lif *lif = netdev_priv(netdev);
|
struct ionic_lif *lif = netdev_priv(netdev);
|
||||||
|
unsigned int offset;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
|
||||||
regs->version = IONIC_DEV_CMD_REG_VERSION;
|
regs->version = IONIC_DEV_CMD_REG_VERSION;
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
size = IONIC_DEV_INFO_REG_COUNT * sizeof(u32);
|
size = IONIC_DEV_INFO_REG_COUNT * sizeof(u32);
|
||||||
memcpy_fromio(p, lif->ionic->idev.dev_info_regs->words, size);
|
memcpy_fromio(p + offset, lif->ionic->idev.dev_info_regs->words, size);
|
||||||
|
|
||||||
|
offset += size;
|
||||||
size = IONIC_DEV_CMD_REG_COUNT * sizeof(u32);
|
size = IONIC_DEV_CMD_REG_COUNT * sizeof(u32);
|
||||||
memcpy_fromio(p, lif->ionic->idev.dev_cmd_regs->words, size);
|
memcpy_fromio(p + offset, lif->ionic->idev.dev_cmd_regs->words, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ionic_get_link_ksettings(struct net_device *netdev,
|
static int ionic_get_link_ksettings(struct net_device *netdev,
|
||||||
|
|
|
@ -96,8 +96,7 @@ static void ionic_link_status_check(struct ionic_lif *lif)
|
||||||
u16 link_status;
|
u16 link_status;
|
||||||
bool link_up;
|
bool link_up;
|
||||||
|
|
||||||
if (!test_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state) ||
|
if (!test_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state))
|
||||||
test_bit(IONIC_LIF_F_QUEUE_RESET, lif->state))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
link_status = le16_to_cpu(lif->info->status.link_status);
|
link_status = le16_to_cpu(lif->info->status.link_status);
|
||||||
|
@ -114,16 +113,22 @@ static void ionic_link_status_check(struct ionic_lif *lif)
|
||||||
netif_carrier_on(netdev);
|
netif_carrier_on(netdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev))
|
if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) {
|
||||||
|
mutex_lock(&lif->queue_lock);
|
||||||
ionic_start_queues(lif);
|
ionic_start_queues(lif);
|
||||||
|
mutex_unlock(&lif->queue_lock);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (netif_carrier_ok(netdev)) {
|
if (netif_carrier_ok(netdev)) {
|
||||||
netdev_info(netdev, "Link down\n");
|
netdev_info(netdev, "Link down\n");
|
||||||
netif_carrier_off(netdev);
|
netif_carrier_off(netdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev))
|
if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) {
|
||||||
|
mutex_lock(&lif->queue_lock);
|
||||||
ionic_stop_queues(lif);
|
ionic_stop_queues(lif);
|
||||||
|
mutex_unlock(&lif->queue_lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state);
|
clear_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state);
|
||||||
|
@ -863,8 +868,7 @@ static int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr)
|
||||||
if (f)
|
if (f)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
netdev_dbg(lif->netdev, "rx_filter add ADDR %pM (id %d)\n", addr,
|
netdev_dbg(lif->netdev, "rx_filter add ADDR %pM\n", addr);
|
||||||
ctx.comp.rx_filter_add.filter_id);
|
|
||||||
|
|
||||||
memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, ETH_ALEN);
|
memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, ETH_ALEN);
|
||||||
err = ionic_adminq_post_wait(lif, &ctx);
|
err = ionic_adminq_post_wait(lif, &ctx);
|
||||||
|
@ -893,6 +897,9 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n",
|
||||||
|
addr, f->filter_id);
|
||||||
|
|
||||||
ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
|
ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
|
||||||
ionic_rx_filter_free(lif, f);
|
ionic_rx_filter_free(lif, f);
|
||||||
spin_unlock_bh(&lif->rx_filters.lock);
|
spin_unlock_bh(&lif->rx_filters.lock);
|
||||||
|
@ -901,9 +908,6 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr)
|
||||||
if (err && err != -EEXIST)
|
if (err && err != -EEXIST)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n", addr,
|
|
||||||
ctx.cmd.rx_filter_del.filter_id);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1351,13 +1355,11 @@ static int ionic_vlan_rx_add_vid(struct net_device *netdev, __be16 proto,
|
||||||
};
|
};
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
netdev_dbg(netdev, "rx_filter add VLAN %d\n", vid);
|
||||||
err = ionic_adminq_post_wait(lif, &ctx);
|
err = ionic_adminq_post_wait(lif, &ctx);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
netdev_dbg(netdev, "rx_filter add VLAN %d (id %d)\n", vid,
|
|
||||||
ctx.comp.rx_filter_add.filter_id);
|
|
||||||
|
|
||||||
return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx);
|
return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1382,8 +1384,8 @@ static int ionic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto,
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n", vid,
|
netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n",
|
||||||
le32_to_cpu(ctx.cmd.rx_filter_del.filter_id));
|
vid, f->filter_id);
|
||||||
|
|
||||||
ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
|
ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
|
||||||
ionic_rx_filter_free(lif, f);
|
ionic_rx_filter_free(lif, f);
|
||||||
|
@ -1993,16 +1995,13 @@ int ionic_reset_queues(struct ionic_lif *lif, ionic_reset_cb cb, void *arg)
|
||||||
bool running;
|
bool running;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
err = ionic_wait_for_bit(lif, IONIC_LIF_F_QUEUE_RESET);
|
mutex_lock(&lif->queue_lock);
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
running = netif_running(lif->netdev);
|
running = netif_running(lif->netdev);
|
||||||
if (running) {
|
if (running) {
|
||||||
netif_device_detach(lif->netdev);
|
netif_device_detach(lif->netdev);
|
||||||
err = ionic_stop(lif->netdev);
|
err = ionic_stop(lif->netdev);
|
||||||
if (err)
|
if (err)
|
||||||
goto reset_out;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cb)
|
if (cb)
|
||||||
|
@ -2012,9 +2011,7 @@ int ionic_reset_queues(struct ionic_lif *lif, ionic_reset_cb cb, void *arg)
|
||||||
err = ionic_open(lif->netdev);
|
err = ionic_open(lif->netdev);
|
||||||
netif_device_attach(lif->netdev);
|
netif_device_attach(lif->netdev);
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&lif->queue_lock);
|
||||||
reset_out:
|
|
||||||
clear_bit(IONIC_LIF_F_QUEUE_RESET, lif->state);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -2161,7 +2158,9 @@ static void ionic_lif_handle_fw_down(struct ionic_lif *lif)
|
||||||
|
|
||||||
if (test_bit(IONIC_LIF_F_UP, lif->state)) {
|
if (test_bit(IONIC_LIF_F_UP, lif->state)) {
|
||||||
dev_info(ionic->dev, "Surprise FW stop, stopping queues\n");
|
dev_info(ionic->dev, "Surprise FW stop, stopping queues\n");
|
||||||
|
mutex_lock(&lif->queue_lock);
|
||||||
ionic_stop_queues(lif);
|
ionic_stop_queues(lif);
|
||||||
|
mutex_unlock(&lif->queue_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (netif_running(lif->netdev)) {
|
if (netif_running(lif->netdev)) {
|
||||||
|
@ -2280,15 +2279,15 @@ static void ionic_lif_deinit(struct ionic_lif *lif)
|
||||||
cancel_work_sync(&lif->deferred.work);
|
cancel_work_sync(&lif->deferred.work);
|
||||||
cancel_work_sync(&lif->tx_timeout_work);
|
cancel_work_sync(&lif->tx_timeout_work);
|
||||||
ionic_rx_filters_deinit(lif);
|
ionic_rx_filters_deinit(lif);
|
||||||
|
if (lif->netdev->features & NETIF_F_RXHASH)
|
||||||
|
ionic_lif_rss_deinit(lif);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lif->netdev->features & NETIF_F_RXHASH)
|
|
||||||
ionic_lif_rss_deinit(lif);
|
|
||||||
|
|
||||||
napi_disable(&lif->adminqcq->napi);
|
napi_disable(&lif->adminqcq->napi);
|
||||||
ionic_lif_qcq_deinit(lif, lif->notifyqcq);
|
ionic_lif_qcq_deinit(lif, lif->notifyqcq);
|
||||||
ionic_lif_qcq_deinit(lif, lif->adminqcq);
|
ionic_lif_qcq_deinit(lif, lif->adminqcq);
|
||||||
|
|
||||||
|
mutex_destroy(&lif->queue_lock);
|
||||||
ionic_lif_reset(lif);
|
ionic_lif_reset(lif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2465,6 +2464,7 @@ static int ionic_lif_init(struct ionic_lif *lif)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
lif->hw_index = le16_to_cpu(comp.hw_index);
|
lif->hw_index = le16_to_cpu(comp.hw_index);
|
||||||
|
mutex_init(&lif->queue_lock);
|
||||||
|
|
||||||
/* now that we have the hw_index we can figure out our doorbell page */
|
/* now that we have the hw_index we can figure out our doorbell page */
|
||||||
lif->dbid_count = le32_to_cpu(lif->ionic->ident.dev.ndbpgs_per_lif);
|
lif->dbid_count = le32_to_cpu(lif->ionic->ident.dev.ndbpgs_per_lif);
|
||||||
|
|
|
@ -135,7 +135,6 @@ enum ionic_lif_state_flags {
|
||||||
IONIC_LIF_F_SW_DEBUG_STATS,
|
IONIC_LIF_F_SW_DEBUG_STATS,
|
||||||
IONIC_LIF_F_UP,
|
IONIC_LIF_F_UP,
|
||||||
IONIC_LIF_F_LINK_CHECK_REQUESTED,
|
IONIC_LIF_F_LINK_CHECK_REQUESTED,
|
||||||
IONIC_LIF_F_QUEUE_RESET,
|
|
||||||
IONIC_LIF_F_FW_RESET,
|
IONIC_LIF_F_FW_RESET,
|
||||||
|
|
||||||
/* leave this as last */
|
/* leave this as last */
|
||||||
|
@ -165,6 +164,7 @@ struct ionic_lif {
|
||||||
unsigned int hw_index;
|
unsigned int hw_index;
|
||||||
unsigned int kern_pid;
|
unsigned int kern_pid;
|
||||||
u64 __iomem *kern_dbpage;
|
u64 __iomem *kern_dbpage;
|
||||||
|
struct mutex queue_lock; /* lock for queue structures */
|
||||||
spinlock_t adminq_lock; /* lock for AdminQ operations */
|
spinlock_t adminq_lock; /* lock for AdminQ operations */
|
||||||
struct ionic_qcq *adminqcq;
|
struct ionic_qcq *adminqcq;
|
||||||
struct ionic_qcq *notifyqcq;
|
struct ionic_qcq *notifyqcq;
|
||||||
|
@ -213,12 +213,6 @@ struct ionic_lif {
|
||||||
#define lif_to_txq(lif, i) (&lif_to_txqcq((lif), i)->q)
|
#define lif_to_txq(lif, i) (&lif_to_txqcq((lif), i)->q)
|
||||||
#define lif_to_rxq(lif, i) (&lif_to_txqcq((lif), i)->q)
|
#define lif_to_rxq(lif, i) (&lif_to_txqcq((lif), i)->q)
|
||||||
|
|
||||||
/* return 0 if successfully set the bit, else non-zero */
|
|
||||||
static inline int ionic_wait_for_bit(struct ionic_lif *lif, int bitname)
|
|
||||||
{
|
|
||||||
return wait_on_bit_lock(lif->state, bitname, TASK_INTERRUPTIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline u32 ionic_coal_usec_to_hw(struct ionic *ionic, u32 usecs)
|
static inline u32 ionic_coal_usec_to_hw(struct ionic *ionic, u32 usecs)
|
||||||
{
|
{
|
||||||
u32 mult = le32_to_cpu(ionic->ident.dev.intr_coal_mult);
|
u32 mult = le32_to_cpu(ionic->ident.dev.intr_coal_mult);
|
||||||
|
|
|
@ -21,13 +21,16 @@ void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f)
|
||||||
void ionic_rx_filter_replay(struct ionic_lif *lif)
|
void ionic_rx_filter_replay(struct ionic_lif *lif)
|
||||||
{
|
{
|
||||||
struct ionic_rx_filter_add_cmd *ac;
|
struct ionic_rx_filter_add_cmd *ac;
|
||||||
|
struct hlist_head new_id_list;
|
||||||
struct ionic_admin_ctx ctx;
|
struct ionic_admin_ctx ctx;
|
||||||
struct ionic_rx_filter *f;
|
struct ionic_rx_filter *f;
|
||||||
struct hlist_head *head;
|
struct hlist_head *head;
|
||||||
struct hlist_node *tmp;
|
struct hlist_node *tmp;
|
||||||
|
unsigned int key;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
INIT_HLIST_HEAD(&new_id_list);
|
||||||
ac = &ctx.cmd.rx_filter_add;
|
ac = &ctx.cmd.rx_filter_add;
|
||||||
|
|
||||||
for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
|
for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
|
||||||
|
@ -58,9 +61,30 @@ void ionic_rx_filter_replay(struct ionic_lif *lif)
|
||||||
ac->mac.addr);
|
ac->mac.addr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
spin_lock_bh(&lif->rx_filters.lock);
|
||||||
|
ionic_rx_filter_free(lif, f);
|
||||||
|
spin_unlock_bh(&lif->rx_filters.lock);
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* remove from old id list, save new id in tmp list */
|
||||||
|
spin_lock_bh(&lif->rx_filters.lock);
|
||||||
|
hlist_del(&f->by_id);
|
||||||
|
spin_unlock_bh(&lif->rx_filters.lock);
|
||||||
|
f->filter_id = le32_to_cpu(ctx.comp.rx_filter_add.filter_id);
|
||||||
|
hlist_add_head(&f->by_id, &new_id_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* rebuild the by_id hash lists with the new filter ids */
|
||||||
|
spin_lock_bh(&lif->rx_filters.lock);
|
||||||
|
hlist_for_each_entry_safe(f, tmp, &new_id_list, by_id) {
|
||||||
|
key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
|
||||||
|
head = &lif->rx_filters.by_id[key];
|
||||||
|
hlist_add_head(&f->by_id, head);
|
||||||
|
}
|
||||||
|
spin_unlock_bh(&lif->rx_filters.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ionic_rx_filters_init(struct ionic_lif *lif)
|
int ionic_rx_filters_init(struct ionic_lif *lif)
|
||||||
|
@ -69,10 +93,12 @@ int ionic_rx_filters_init(struct ionic_lif *lif)
|
||||||
|
|
||||||
spin_lock_init(&lif->rx_filters.lock);
|
spin_lock_init(&lif->rx_filters.lock);
|
||||||
|
|
||||||
|
spin_lock_bh(&lif->rx_filters.lock);
|
||||||
for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
|
for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
|
||||||
INIT_HLIST_HEAD(&lif->rx_filters.by_hash[i]);
|
INIT_HLIST_HEAD(&lif->rx_filters.by_hash[i]);
|
||||||
INIT_HLIST_HEAD(&lif->rx_filters.by_id[i]);
|
INIT_HLIST_HEAD(&lif->rx_filters.by_id[i]);
|
||||||
}
|
}
|
||||||
|
spin_unlock_bh(&lif->rx_filters.lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -84,11 +110,13 @@ void ionic_rx_filters_deinit(struct ionic_lif *lif)
|
||||||
struct hlist_node *tmp;
|
struct hlist_node *tmp;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
spin_lock_bh(&lif->rx_filters.lock);
|
||||||
for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
|
for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
|
||||||
head = &lif->rx_filters.by_id[i];
|
head = &lif->rx_filters.by_id[i];
|
||||||
hlist_for_each_entry_safe(f, tmp, head, by_id)
|
hlist_for_each_entry_safe(f, tmp, head, by_id)
|
||||||
ionic_rx_filter_free(lif, f);
|
ionic_rx_filter_free(lif, f);
|
||||||
}
|
}
|
||||||
|
spin_unlock_bh(&lif->rx_filters.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
|
int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
|
||||||
|
@ -124,6 +152,7 @@ int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
|
||||||
f->filter_id = le32_to_cpu(ctx->comp.rx_filter_add.filter_id);
|
f->filter_id = le32_to_cpu(ctx->comp.rx_filter_add.filter_id);
|
||||||
f->rxq_index = rxq_index;
|
f->rxq_index = rxq_index;
|
||||||
memcpy(&f->cmd, ac, sizeof(f->cmd));
|
memcpy(&f->cmd, ac, sizeof(f->cmd));
|
||||||
|
netdev_dbg(lif->netdev, "rx_filter add filter_id %d\n", f->filter_id);
|
||||||
|
|
||||||
INIT_HLIST_NODE(&f->by_hash);
|
INIT_HLIST_NODE(&f->by_hash);
|
||||||
INIT_HLIST_NODE(&f->by_id);
|
INIT_HLIST_NODE(&f->by_id);
|
||||||
|
|
|
@ -161,12 +161,6 @@ static void ionic_rx_clean(struct ionic_queue *q,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no packet processing while resetting */
|
|
||||||
if (unlikely(test_bit(IONIC_LIF_F_QUEUE_RESET, q->lif->state))) {
|
|
||||||
stats->dropped++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stats->pkts++;
|
stats->pkts++;
|
||||||
stats->bytes += le16_to_cpu(comp->len);
|
stats->bytes += le16_to_cpu(comp->len);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue