Commit 84b9000a authored by David S. Miller's avatar David S. Miller

Merge branch 'ionic-fixes'

Shannon Nelson says:

====================
ionic fixes

These are a few little fixes and cleanups found while working
on other features and more testing.
====================
parents df291e54 e768929d
......@@ -184,6 +184,10 @@ static int ionic_sriov_configure(struct pci_dev *pdev, int num_vfs)
struct device *dev = ionic->dev;
int ret = 0;
if (ionic->lif &&
test_bit(IONIC_LIF_F_FW_RESET, ionic->lif->state))
return -EBUSY;
if (num_vfs > 0) {
ret = pci_enable_sriov(pdev, num_vfs);
if (ret) {
......
......@@ -14,18 +14,20 @@
static void ionic_watchdog_cb(struct timer_list *t)
{
struct ionic *ionic = from_timer(ionic, t, watchdog_timer);
struct ionic_lif *lif = ionic->lif;
int hb;
mod_timer(&ionic->watchdog_timer,
round_jiffies(jiffies + ionic->watchdog_period));
if (!ionic->lif)
if (!lif)
return;
hb = ionic_heartbeat_check(ionic);
if (hb >= 0)
ionic_link_status_check_request(ionic->lif, CAN_NOT_SLEEP);
if (hb >= 0 &&
!test_bit(IONIC_LIF_F_FW_RESET, lif->state))
ionic_link_status_check_request(lif, CAN_NOT_SLEEP);
}
void ionic_init_devinfo(struct ionic *ionic)
......
......@@ -29,11 +29,9 @@ static void ionic_get_stats_strings(struct ionic_lif *lif, u8 *buf)
static void ionic_get_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *buf)
{
struct ionic_lif *lif;
struct ionic_lif *lif = netdev_priv(netdev);
u32 i;
lif = netdev_priv(netdev);
memset(buf, 0, stats->n_stats * sizeof(*buf));
for (i = 0; i < ionic_num_stats_grps; i++)
ionic_stats_groups[i].get_values(lif, &buf);
......@@ -209,6 +207,14 @@ static int ionic_get_link_ksettings(struct net_device *netdev,
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseER_Full);
break;
case IONIC_XCVR_PID_SFP_10GBASE_T:
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseT_Full);
break;
case IONIC_XCVR_PID_SFP_1000BASE_T:
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseT_Full);
break;
case IONIC_XCVR_PID_UNKNOWN:
/* This means there's no module plugged in */
break;
......@@ -264,12 +270,10 @@ static int ionic_set_link_ksettings(struct net_device *netdev,
const struct ethtool_link_ksettings *ks)
{
struct ionic_lif *lif = netdev_priv(netdev);
struct ionic_dev *idev = &lif->ionic->idev;
struct ionic *ionic = lif->ionic;
struct ionic_dev *idev;
int err = 0;
idev = &lif->ionic->idev;
/* set autoneg */
if (ks->base.autoneg != idev->port_info->config.an_enable) {
mutex_lock(&ionic->dev_cmd_lock);
......
......@@ -320,7 +320,7 @@ struct ionic_lif_identify_comp {
/**
* enum ionic_lif_capability - LIF capabilities
* @IONIC_LIF_CAP_ETH: LIF supports Ethernet
* @IONIC_LIF_CAP_RDMA: LIF support RDMA
* @IONIC_LIF_CAP_RDMA: LIF supports RDMA
*/
enum ionic_lif_capability {
IONIC_LIF_CAP_ETH = BIT(0),
......@@ -404,7 +404,7 @@ union ionic_lif_config {
* @max_ucast_filters: Number of perfect unicast addresses supported
* @max_mcast_filters: Number of perfect multicast addresses supported
* @min_frame_size: Minimum size of frames to be sent
* @max_frame_size: Maximim size of frames to be sent
* @max_frame_size: Maximum size of frames to be sent
* @config: LIF config struct with features, mtu, mac, q counts
*
* @rdma: RDMA identify structure
......@@ -692,7 +692,7 @@ enum ionic_txq_desc_opcode {
* checksums are also updated.
*
* IONIC_TXQ_DESC_OPCODE_TSO:
* Device preforms TCP segmentation offload
* Device performs TCP segmentation offload
* (TSO). @hdr_len is the number of bytes
* to the end of TCP header (the offset to
* the TCP payload). @mss is the desired
......@@ -982,13 +982,13 @@ struct ionic_rxq_comp {
};
enum ionic_pkt_type {
IONIC_PKT_TYPE_NON_IP = 0x000,
IONIC_PKT_TYPE_IPV4 = 0x001,
IONIC_PKT_TYPE_IPV4_TCP = 0x003,
IONIC_PKT_TYPE_IPV4_UDP = 0x005,
IONIC_PKT_TYPE_IPV6 = 0x008,
IONIC_PKT_TYPE_IPV6_TCP = 0x018,
IONIC_PKT_TYPE_IPV6_UDP = 0x028,
IONIC_PKT_TYPE_NON_IP = 0x00,
IONIC_PKT_TYPE_IPV4 = 0x01,
IONIC_PKT_TYPE_IPV4_TCP = 0x03,
IONIC_PKT_TYPE_IPV4_UDP = 0x05,
IONIC_PKT_TYPE_IPV6 = 0x08,
IONIC_PKT_TYPE_IPV6_TCP = 0x18,
IONIC_PKT_TYPE_IPV6_UDP = 0x28,
/* below types are only used if encap offloads are enabled on lif */
IONIC_PKT_TYPE_ENCAP_NON_IP = 0x40,
IONIC_PKT_TYPE_ENCAP_IPV4 = 0x41,
......@@ -1111,6 +1111,8 @@ enum ionic_xcvr_pid {
IONIC_XCVR_PID_QSFP_100G_CWDM4 = 69,
IONIC_XCVR_PID_QSFP_100G_PSM4 = 70,
IONIC_XCVR_PID_SFP_25GBASE_ACC = 71,
IONIC_XCVR_PID_SFP_10GBASE_T = 72,
IONIC_XCVR_PID_SFP_1000BASE_T = 73,
};
/**
......@@ -1331,7 +1333,7 @@ enum ionic_stats_ctl_cmd {
* @IONIC_PORT_ATTR_STATE: Port state attribute
* @IONIC_PORT_ATTR_SPEED: Port speed attribute
* @IONIC_PORT_ATTR_MTU: Port MTU attribute
* @IONIC_PORT_ATTR_AUTONEG: Port autonegotation attribute
* @IONIC_PORT_ATTR_AUTONEG: Port autonegotiation attribute
* @IONIC_PORT_ATTR_FEC: Port FEC attribute
* @IONIC_PORT_ATTR_PAUSE: Port pause attribute
* @IONIC_PORT_ATTR_LOOPBACK: Port loopback attribute
......@@ -1951,8 +1953,8 @@ enum ionic_qos_sched_type {
* @pfc_cos: Priority-Flow Control class of service
* @dwrr_weight: QoS class scheduling weight
* @strict_rlmt: Rate limit for strict priority scheduling
* @rw_dot1q_pcp: Rewrite dot1q pcp to this value (valid iff F_RW_DOT1Q_PCP)
* @rw_ip_dscp: Rewrite ip dscp to this value (valid iff F_RW_IP_DSCP)
* @rw_dot1q_pcp: Rewrite dot1q pcp to value (valid iff F_RW_DOT1Q_PCP)
* @rw_ip_dscp: Rewrite ip dscp to value (valid iff F_RW_IP_DSCP)
* @dot1q_pcp: Dot1q pcp value
* @ndscp: Number of valid dscp values in the ip_dscp field
* @ip_dscp: IP dscp values
......
......@@ -120,23 +120,34 @@ static void ionic_link_status_check(struct ionic_lif *lif)
if (!test_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state))
return;
/* Don't put carrier back up if we're in a broken state */
if (test_bit(IONIC_LIF_F_BROKEN, lif->state)) {
clear_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state);
return;
}
link_status = le16_to_cpu(lif->info->status.link_status);
link_up = link_status == IONIC_PORT_OPER_STATUS_UP;
if (link_up) {
if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) {
int err = 0;
if (netdev->flags & IFF_UP && netif_running(netdev)) {
mutex_lock(&lif->queue_lock);
ionic_start_queues(lif);
err = ionic_start_queues(lif);
if (err) {
netdev_err(lif->netdev,
"Failed to start queues: %d\n", err);
set_bit(IONIC_LIF_F_BROKEN, lif->state);
netif_carrier_off(lif->netdev);
}
mutex_unlock(&lif->queue_lock);
}
if (!netif_carrier_ok(netdev)) {
u32 link_speed;
if (!err && !netif_carrier_ok(netdev)) {
ionic_port_identify(lif->ionic);
link_speed = le32_to_cpu(lif->info->status.link_speed);
netdev_info(netdev, "Link up - %d Gbps\n",
link_speed / 1000);
le32_to_cpu(lif->info->status.link_speed) / 1000);
netif_carrier_on(netdev);
}
} else {
......@@ -145,7 +156,7 @@ static void ionic_link_status_check(struct ionic_lif *lif)
netif_carrier_off(netdev);
}
if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) {
if (netdev->flags & IFF_UP && netif_running(netdev)) {
mutex_lock(&lif->queue_lock);
ionic_stop_queues(lif);
mutex_unlock(&lif->queue_lock);
......@@ -382,6 +393,8 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
static void ionic_qcqs_free(struct ionic_lif *lif)
{
struct device *dev = lif->ionic->dev;
struct ionic_qcq *adminqcq;
unsigned long irqflags;
if (lif->notifyqcq) {
ionic_qcq_free(lif, lif->notifyqcq);
......@@ -390,9 +403,14 @@ static void ionic_qcqs_free(struct ionic_lif *lif)
}
if (lif->adminqcq) {
ionic_qcq_free(lif, lif->adminqcq);
devm_kfree(dev, lif->adminqcq);
spin_lock_irqsave(&lif->adminq_lock, irqflags);
adminqcq = READ_ONCE(lif->adminqcq);
lif->adminqcq = NULL;
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
if (adminqcq) {
ionic_qcq_free(lif, adminqcq);
devm_kfree(dev, adminqcq);
}
}
if (lif->rxqcqs) {
......@@ -718,10 +736,8 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
unsigned int intr_index;
int err;
if (qcq->flags & IONIC_QCQ_F_INTR)
intr_index = qcq->intr.index;
else
intr_index = lif->rxqcqs[q->index]->intr.index;
intr_index = qcq->intr.index;
ctx.cmd.q_init.intr_index = cpu_to_le16(intr_index);
dev_dbg(dev, "txq_init.pid %d\n", ctx.cmd.q_init.pid);
......@@ -839,7 +855,7 @@ static bool ionic_notifyq_service(struct ionic_cq *cq,
switch (le16_to_cpu(comp->event.ecode)) {
case IONIC_EVENT_LINK_CHANGE:
ionic_link_status_check_request(lif, false);
ionic_link_status_check_request(lif, CAN_NOT_SLEEP);
break;
case IONIC_EVENT_RESET:
work = kzalloc(sizeof(*work), GFP_ATOMIC);
......@@ -877,6 +893,7 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget)
struct ionic_intr_info *intr = napi_to_cq(napi)->bound_intr;
struct ionic_lif *lif = napi_to_cq(napi)->lif;
struct ionic_dev *idev = &lif->ionic->idev;
unsigned long irqflags;
unsigned int flags = 0;
int n_work = 0;
int a_work = 0;
......@@ -886,14 +903,16 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget)
n_work = ionic_cq_service(&lif->notifyqcq->cq, budget,
ionic_notifyq_service, NULL, NULL);
spin_lock_irqsave(&lif->adminq_lock, irqflags);
if (lif->adminqcq && lif->adminqcq->flags & IONIC_QCQ_F_INITED)
a_work = ionic_cq_service(&lif->adminqcq->cq, budget,
ionic_adminq_service, NULL, NULL);
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
work_done = max(n_work, a_work);
if (work_done < budget && napi_complete_done(napi, work_done)) {
flags |= IONIC_INTR_CRED_UNMASK;
lif->adminqcq->cq.bound_intr->rearm_count++;
intr->rearm_count++;
}
if (work_done || flags) {
......@@ -1443,7 +1462,7 @@ static int ionic_start_queues_reconfig(struct ionic_lif *lif)
*/
err = ionic_txrx_init(lif);
mutex_unlock(&lif->queue_lock);
ionic_link_status_check_request(lif, true);
ionic_link_status_check_request(lif, CAN_SLEEP);
netif_device_attach(lif->netdev);
return err;
......@@ -1482,7 +1501,8 @@ static void ionic_tx_timeout_work(struct work_struct *ws)
{
struct ionic_lif *lif = container_of(ws, struct ionic_lif, tx_timeout_work);
netdev_info(lif->netdev, "Tx Timeout recovery\n");
if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
return;
/* if we were stopped before this scheduled job was launched,
* don't bother the queues as they are already stopped.
......@@ -1498,6 +1518,7 @@ static void ionic_tx_timeout(struct net_device *netdev, unsigned int txqueue)
{
struct ionic_lif *lif = netdev_priv(netdev);
netdev_info(lif->netdev, "Tx Timeout triggered - txq %d\n", txqueue);
schedule_work(&lif->tx_timeout_work);
}
......@@ -1839,6 +1860,12 @@ static int ionic_start_queues(struct ionic_lif *lif)
{
int err;
if (test_bit(IONIC_LIF_F_BROKEN, lif->state))
return -EIO;
if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
return -EBUSY;
if (test_and_set_bit(IONIC_LIF_F_UP, lif->state))
return 0;
......@@ -1857,13 +1884,17 @@ static int ionic_open(struct net_device *netdev)
struct ionic_lif *lif = netdev_priv(netdev);
int err;
/* If recovering from a broken state, clear the bit and we'll try again */
if (test_and_clear_bit(IONIC_LIF_F_BROKEN, lif->state))
netdev_info(netdev, "clearing broken state\n");
err = ionic_txrx_alloc(lif);
if (err)
return err;
err = ionic_txrx_init(lif);
if (err)
goto err_out;
goto err_txrx_free;
err = netif_set_real_num_tx_queues(netdev, lif->nxqs);
if (err)
......@@ -1884,7 +1915,7 @@ static int ionic_open(struct net_device *netdev)
err_txrx_deinit:
ionic_txrx_deinit(lif);
err_out:
err_txrx_free:
ionic_txrx_free(lif);
return err;
}
......@@ -2356,7 +2387,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif,
swap(lif->nxqs, qparam->nxqs);
err_out_reinit_unlock:
/* re-init the queues, but don't loose an error code */
/* re-init the queues, but don't lose an error code */
if (err)
ionic_start_queues_reconfig(lif);
else
......@@ -2605,7 +2636,7 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
}
clear_bit(IONIC_LIF_F_FW_RESET, lif->state);
ionic_link_status_check_request(lif, true);
ionic_link_status_check_request(lif, CAN_SLEEP);
netif_device_attach(lif->netdev);
dev_info(ionic->dev, "FW Up: LIFs restarted\n");
......@@ -2976,7 +3007,7 @@ int ionic_lif_register(struct ionic_lif *lif)
return err;
}
ionic_link_status_check_request(lif, true);
ionic_link_status_check_request(lif, CAN_SLEEP);
lif->registered = true;
ionic_lif_set_netdev_info(lif);
......
......@@ -139,6 +139,7 @@ enum ionic_lif_state_flags {
IONIC_LIF_F_LINK_CHECK_REQUESTED,
IONIC_LIF_F_FW_RESET,
IONIC_LIF_F_SPLIT_INTR,
IONIC_LIF_F_BROKEN,
IONIC_LIF_F_TX_DIM_INTR,
IONIC_LIF_F_RX_DIM_INTR,
......
......@@ -187,10 +187,17 @@ static const char *ionic_opcode_to_str(enum ionic_cmd_opcode opcode)
static void ionic_adminq_flush(struct ionic_lif *lif)
{
struct ionic_queue *q = &lif->adminqcq->q;
struct ionic_desc_info *desc_info;
unsigned long irqflags;
struct ionic_queue *q;
spin_lock_irqsave(&lif->adminq_lock, irqflags);
if (!lif->adminqcq) {
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
return;
}
spin_lock(&lif->adminq_lock);
q = &lif->adminqcq->q;
while (q->tail_idx != q->head_idx) {
desc_info = &q->info[q->tail_idx];
......@@ -199,7 +206,7 @@ static void ionic_adminq_flush(struct ionic_lif *lif)
desc_info->cb_arg = NULL;
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
}
spin_unlock(&lif->adminq_lock);
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
}
static int ionic_adminq_check_err(struct ionic_lif *lif,
......@@ -252,15 +259,18 @@ static void ionic_adminq_cb(struct ionic_queue *q,
static int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
{
struct ionic_desc_info *desc_info;
unsigned long irqflags;
struct ionic_queue *q;
int err = 0;
if (!lif->adminqcq)
spin_lock_irqsave(&lif->adminq_lock, irqflags);
if (!lif->adminqcq) {
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
return -EIO;
}
q = &lif->adminqcq->q;
spin_lock(&lif->adminq_lock);
if (!ionic_q_has_space(q, 1)) {
err = -ENOSPC;
goto err_out;
......@@ -280,7 +290,7 @@ static int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
ionic_q_post(q, true, ionic_adminq_cb, ctx);
err_out:
spin_unlock(&lif->adminq_lock);
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
return err;
}
......
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