Loading drivers/net/ethernet/msm/emac/emac.h +42 −7 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ #define EMAC_NUM_CORE_IRQ 4 #define EMAC_WOL_IRQ 4 #define EMAC_SGMII_PHY_IRQ 5 #define EMAC_NUM_IRQ 6 #define EMAC_IRQ_CNT 6 /* mdio/mdc gpios */ #define EMAC_GPIO_CNT 2 Loading Loading @@ -519,19 +519,42 @@ union emac_sw_tpdesc { #define EMAC_TPD_LAST_FRAGMENT 0x80000000 #define EMAC_TPD_TSTAMP_SAVE 0x80000000 struct emac_irq_info { /* emac_irq_per_dev per-device (per-adapter) irq properties. * @idx: index of this irq entry in the adapter irq array. * @irq: irq number. * @mask mask to use over status register. */ struct emac_irq_per_dev { int idx; unsigned int irq; u32 mask; }; /* emac_irq_common irq properties which are common to all devices of this driver * @name name in configuration (devicetree). * @handler ISR. * @status_reg status register offset. * @mask_reg mask register offset. * @init_mask initial value for mask to use over status register. * @irqflags request_irq() flags. */ struct emac_irq_common { char *name; irq_handler_t handler; u32 status_reg; u32 mask_reg; u32 mask; u32 init_mask; struct emac_rx_queue *rxque; struct emac_adapter *adpt; unsigned long irqflags; }; /* emac_irq_cmn_tbl a table of common irq properties to all devices of this * driver. */ extern const struct emac_irq_common emac_irq_cmn_tbl[]; struct emac_clk { struct clk *clk; bool enabled; Loading Loading @@ -600,7 +623,7 @@ struct emac_rx_queue { u8 consume_shft; u32 intr; struct emac_irq_info *irq_info; struct emac_irq_per_dev *irq; }; #define GET_RFD_BUFFER(_rque, _i) (&((_rque)->rfd.rfbuff[(_i)])) Loading Loading @@ -662,7 +685,7 @@ struct emac_tx_queue { struct emac_adapter { struct net_device *netdev; struct emac_irq_info irq_info[EMAC_NUM_IRQ]; struct emac_irq_per_dev irq[EMAC_IRQ_CNT]; unsigned int gpio[EMAC_GPIO_CNT]; struct emac_clk clk[EMAC_CLK_CNT]; Loading Loading @@ -713,6 +736,18 @@ static inline struct emac_adapter *emac_hw_get_adap(struct emac_hw *hw) return container_of(hw, struct emac_adapter, hw); } static inline struct emac_adapter *emac_irq_get_adpt(struct emac_irq_per_dev *irq) { struct emac_irq_per_dev *irq_0 = irq - irq->idx; /* why using __builtin_offsetof() and not container_of() ? * container_of(irq_0, struct emac_adapter, irq) fails to compile * because emac->irq is of array type. */ return (struct emac_adapter *) ((char *)irq_0 - __builtin_offsetof(struct emac_adapter, irq)); } /* default to trying for four seconds */ #define EMAC_TRY_LINK_TIMEOUT (4 * HZ) Loading drivers/net/ethernet/msm/emac/emac_hw.c +18 −19 Original line number Diff line number Diff line Loading @@ -887,21 +887,21 @@ int emac_check_sgmii_autoneg(struct emac_hw *hw, u32 *speed, bool *link_up) void emac_hw_enable_intr(struct emac_hw *hw) { struct emac_adapter *adpt = emac_hw_get_adap(hw); struct emac_irq_info *irq_info; int i; for (i = 0; i < EMAC_NUM_CORE_IRQ; i++) { irq_info = &adpt->irq_info[i]; emac_reg_w32(hw, EMAC, irq_info->status_reg, ~DIS_INT); emac_reg_w32(hw, EMAC, irq_info->mask_reg, irq_info->mask); } struct emac_irq_per_dev *irq = &adpt->irq[i]; const struct emac_irq_common *irq_cmn = &emac_irq_cmn_tbl[i]; if (adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) { irq_info = &adpt->irq_info[EMAC_SGMII_PHY_IRQ]; emac_reg_w32(hw, EMAC_SGMII_PHY, irq_info->mask_reg, irq_info->mask); emac_reg_w32(hw, EMAC, irq_cmn->status_reg, ~DIS_INT); emac_reg_w32(hw, EMAC, irq_cmn->mask_reg, irq->mask); } if (adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) emac_reg_w32(hw, EMAC_SGMII_PHY, emac_irq_cmn_tbl[EMAC_SGMII_PHY_IRQ].mask_reg, adpt->irq[EMAC_SGMII_PHY_IRQ].mask); if (adpt->tstamp_en) emac_reg_w32(hw, EMAC_1588, EMAC_P1588_PTP_EXPANDED_INT_MASK, hw->ptp_intr_mask); Loading @@ -911,23 +911,22 @@ void emac_hw_enable_intr(struct emac_hw *hw) void emac_hw_disable_intr(struct emac_hw *hw) { struct emac_adapter *adpt = emac_hw_get_adap(hw); struct emac_irq_info *irq_info; int i; for (i = 0; i < EMAC_NUM_CORE_IRQ; i++) { irq_info = &adpt->irq_info[i]; emac_reg_w32(hw, EMAC, irq_info->status_reg, DIS_INT); emac_reg_w32(hw, EMAC, irq_info->mask_reg, 0); const struct emac_irq_common *irq_cmn = &emac_irq_cmn_tbl[i]; emac_reg_w32(hw, EMAC, irq_cmn->status_reg, DIS_INT); emac_reg_w32(hw, EMAC, irq_cmn->mask_reg, 0); } if (adpt->tstamp_en) emac_reg_w32(hw, EMAC_1588, EMAC_P1588_PTP_EXPANDED_INT_MASK, 0); emac_reg_w32(hw, EMAC_1588, EMAC_P1588_PTP_EXPANDED_INT_MASK, 0); if (adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) emac_reg_w32(hw, EMAC_SGMII_PHY, emac_irq_cmn_tbl[EMAC_SGMII_PHY_IRQ].mask_reg, 0); if (adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) { irq_info = &adpt->irq_info[EMAC_SGMII_PHY_IRQ]; emac_reg_w32(hw, EMAC_SGMII_PHY, irq_info->mask_reg, 0); } wmb(); } Loading drivers/net/ethernet/msm/emac/emac_main.c +85 −88 Original line number Diff line number Diff line Loading @@ -79,32 +79,31 @@ static int msm_emac_intr_ext; module_param_named(intr_ext, msm_emac_intr_ext, int, S_IRUGO | S_IWUSR | S_IWGRP); static irqreturn_t emac_interrupt(int irq, void *data); static irqreturn_t emac_sgmii_interrupt(int irq, void *data); static irqreturn_t emac_wol_interrupt(int irq, void *data); /* EMAC HW has an issue with interrupt assignment because of which receive queue 1 is disabled and following receive rss queue to interrupt mapping is used. rss-queue intr 0 core0 1 core3 (disabled) 2 core1 3 core2 static irqreturn_t emac_isr(int irq, void *data); static irqreturn_t emac_sgmii_isr(int irq, void *data); static irqreturn_t emac_wol_isr(int irq, void *data); /* EMAC HW has an issue with interrupt assignment because of which receive queue * 1 is disabled and following receive rss queue to interrupt mapping is used: * rss-queue intr * 0 core0 * 1 core3 (disabled) * 2 core1 * 3 core2 */ static struct emac_irq_info emac_irq[EMAC_NUM_IRQ] = { { 0, "emac_core0_irq", emac_interrupt, EMAC_INT_STATUS, EMAC_INT_MASK, RX_PKT_INT0, NULL, NULL }, { 0, "emac_core3_irq", emac_interrupt, EMAC_INT3_STATUS, EMAC_INT3_MASK, 0, NULL, NULL }, { 0, "emac_core1_irq", emac_interrupt, EMAC_INT1_STATUS, EMAC_INT1_MASK, RX_PKT_INT2, NULL, NULL }, { 0, "emac_core2_irq", emac_interrupt, EMAC_INT2_STATUS, EMAC_INT2_MASK, RX_PKT_INT3, NULL, NULL }, { 0, "emac_wol_irq", emac_wol_interrupt, 0, 0, 0, NULL, NULL }, { 0, "emac_sgmii_irq", emac_sgmii_interrupt, 0, EMAC_SGMII_PHY_INTERRUPT_MASK, SGMII_ISR_MASK, NULL, NULL }, const struct emac_irq_common emac_irq_cmn_tbl[EMAC_IRQ_CNT] = { { "emac_core0_irq", emac_isr, EMAC_INT_STATUS, EMAC_INT_MASK, RX_PKT_INT0, 0}, { "emac_core3_irq", emac_isr, EMAC_INT3_STATUS, EMAC_INT3_MASK, 0, 0}, { "emac_core1_irq", emac_isr, EMAC_INT1_STATUS, EMAC_INT1_MASK, RX_PKT_INT2, 0}, { "emac_core2_irq", emac_isr, EMAC_INT2_STATUS, EMAC_INT2_MASK, RX_PKT_INT3, 0}, { "emac_wol_irq" , emac_wol_isr, 0, 0, 0, 0}, { "emac_sgmii_irq", emac_sgmii_isr, 0, EMAC_SGMII_PHY_INTERRUPT_MASK, SGMII_ISR_MASK, IRQF_TRIGGER_RISING}, }; static const char * const emac_gpio_name[] = { Loading Loading @@ -731,7 +730,7 @@ static int emac_napi_rtx(struct napi_struct *napi, int budget) struct emac_rx_queue *rxque = container_of(napi, struct emac_rx_queue, napi); struct emac_adapter *adpt = netdev_priv(rxque->netdev); struct emac_irq_info *irq_info = rxque->irq_info; struct emac_irq_per_dev *irq = rxque->irq; struct emac_hw *hw = &adpt->hw; int work_done = 0; Loading @@ -745,8 +744,9 @@ static int emac_napi_rtx(struct napi_struct *napi, int budget) quit_polling: napi_complete(napi); irq_info->mask |= rxque->intr; emac_reg_w32(hw, EMAC, irq_info->mask_reg, irq_info->mask); irq->mask |= rxque->intr; emac_reg_w32(hw, EMAC, emac_irq_cmn_tbl[irq->idx].mask_reg, irq->mask); wmb(); } Loading Loading @@ -1022,30 +1022,30 @@ static int emac_start_xmit(struct sk_buff *skb, } /* ISR */ static irqreturn_t emac_wol_interrupt(int irq, void *data) static irqreturn_t emac_wol_isr(int irq, void *data) { struct emac_irq_info *irq_info = data; struct emac_adapter *adpt = irq_info->adpt; emac_dbg(adpt, wol, "EMAC wol interrupt received\n"); emac_dbg(emac_irq_get_adpt(data), wol, "EMAC wol interrupt received\n"); return IRQ_HANDLED; } static irqreturn_t emac_interrupt(int irq, void *data) static irqreturn_t emac_isr(int _irq, void *data) { struct emac_irq_info *irq_info = data; struct emac_adapter *adpt = irq_info->adpt; struct emac_irq_per_dev *irq = data; const struct emac_irq_common *irq_cmn = &emac_irq_cmn_tbl[irq->idx]; struct emac_adapter *adpt = emac_irq_get_adpt(data); struct emac_rx_queue *rxque = &adpt->rx_queue[irq->idx]; struct emac_hw *hw = &adpt->hw; int max_ints = 1; u32 isr, status; emac_dbg(emac_irq_get_adpt(data), wol, "EMAC wol interrupt received\n"); /* disable the interrupt */ emac_reg_w32(hw, EMAC, irq_info->mask_reg, 0); emac_reg_w32(hw, EMAC, irq_cmn->mask_reg, 0); wmb(); do { isr = emac_reg_r32(hw, EMAC, irq_info->status_reg); status = isr & irq_info->mask; isr = emac_reg_r32(hw, EMAC, irq_cmn->status_reg); status = isr & irq->mask; if (status == 0) break; Loading @@ -1065,10 +1065,10 @@ static irqreturn_t emac_interrupt(int irq, void *data) /* Schedule the napi for receive queue with interrupt * status bit set */ if ((status & irq_info->rxque->intr)) { if (napi_schedule_prep(&irq_info->rxque->napi)) { irq_info->mask &= ~irq_info->rxque->intr; __napi_schedule(&irq_info->rxque->napi); if ((status & rxque->intr)) { if (napi_schedule_prep(&rxque->napi)) { irq->mask &= ~rxque->intr; __napi_schedule(&rxque->napi); } } Loading Loading @@ -1098,15 +1098,15 @@ static irqreturn_t emac_interrupt(int irq, void *data) } while (--max_ints > 0); /* enable the interrupt */ emac_reg_w32(hw, EMAC, irq_info->mask_reg, irq_info->mask); emac_reg_w32(hw, EMAC, irq_cmn->mask_reg, irq->mask); wmb(); return IRQ_HANDLED; } static irqreturn_t emac_sgmii_interrupt(int irq, void *data) static irqreturn_t emac_sgmii_isr(int _irq, void *data) { struct emac_irq_info *irq_info = data; struct emac_adapter *adpt = irq_info->adpt; struct emac_irq_per_dev *irq = data; struct emac_adapter *adpt = emac_irq_get_adpt(data); struct emac_hw *hw = &adpt->hw; u32 status; Loading @@ -1115,7 +1115,7 @@ static irqreturn_t emac_sgmii_interrupt(int irq, void *data) do { status = emac_reg_r32(hw, EMAC_SGMII_PHY, EMAC_SGMII_PHY_INTERRUPT_STATUS); status &= irq_info->mask; status &= irq->mask; if (!status) break; Loading Loading @@ -1158,10 +1158,10 @@ static inline void emac_disable_intr(struct emac_adapter *adpt) emac_hw_disable_intr(hw); for (i = 0; i < EMAC_NUM_CORE_IRQ; i++) synchronize_irq(adpt->irq_info[i].irq); synchronize_irq(adpt->irq[i].irq); /* SGMII IRQ */ synchronize_irq(adpt->irq_info[EMAC_SGMII_PHY_IRQ].irq); synchronize_irq(adpt->irq[EMAC_SGMII_PHY_IRQ].irq); } /* Configure VLAN tag strip/insert feature */ Loading Loading @@ -1638,22 +1638,24 @@ int emac_up(struct emac_adapter *adpt) } } for (i = 0; i < EMAC_NUM_IRQ; i++) { struct emac_irq_info *irq_info = &adpt->irq_info[i]; u32 flag = (i == EMAC_SGMII_PHY_IRQ) ? IRQF_TRIGGER_RISING : 0; for (i = 0; i < EMAC_IRQ_CNT; i++) { struct emac_irq_per_dev *irq = &adpt->irq[i]; const struct emac_irq_common *irq_cmn = &emac_irq_cmn_tbl[i]; if (irq_info->irq == 0) if (!irq->irq) continue; retval = request_irq(irq_info->irq, irq_info->handler, flag, irq_info->name, irq_info); retval = request_irq(irq->irq, irq_cmn->handler, irq_cmn->irqflags, irq_cmn->name, irq); if (retval) { emac_err(adpt, "Unable to allocate interrupt %d: %d\n", irq_info->irq, retval); emac_err(adpt, "error:%d on request_irq(%d:%s flags:0x%lx)\n", retval, irq->irq, irq_cmn->name, irq_cmn->irqflags); while (--i >= 0) if (adpt->irq_info[i].irq) free_irq(adpt->irq_info[i].irq, &adpt->irq_info[i]); if (adpt->irq[i].irq) free_irq(adpt->irq[i].irq, &adpt->irq[i]); goto err_request_irq; } } Loading Loading @@ -1697,9 +1699,9 @@ void emac_down(struct emac_adapter *adpt, u32 ctrl) emac_disable_intr(adpt); emac_napi_disable_all(adpt); for (i = 0; i < EMAC_NUM_IRQ; i++) if (adpt->irq_info[i].irq) free_irq(adpt->irq_info[i].irq, &adpt->irq_info[i]); for (i = 0; i < EMAC_IRQ_CNT; i++) if (adpt->irq[i].irq) free_irq(adpt->irq[i].irq, &adpt->irq[i]); for (i = 0; (!adpt->no_mdio_gpio) && i < EMAC_GPIO_CNT; i++) gpio_free(adpt->gpio[i]); Loading Loading @@ -2176,8 +2178,8 @@ static void emac_init_rtx_queues(struct platform_device *pdev, adpt->rx_queue[3].consume_mask = RFD3_CONS_IDX_BMSK; adpt->rx_queue[3].consume_shft = RFD3_CONS_IDX_SHFT; adpt->rx_queue[3].irq_info = &adpt->irq_info[3]; adpt->rx_queue[3].intr = adpt->irq_info[3].mask & ISR_RX_PKT; adpt->rx_queue[3].irq = &adpt->irq[3]; adpt->rx_queue[3].intr = adpt->irq[3].mask & ISR_RX_PKT; case 3: adpt->rx_queue[2].produce_reg = EMAC_MAILBOX_6; adpt->rx_queue[2].produce_mask = RFD2_PROD_IDX_BMSK; Loading @@ -2191,8 +2193,8 @@ static void emac_init_rtx_queues(struct platform_device *pdev, adpt->rx_queue[2].consume_mask = RFD2_CONS_IDX_BMSK; adpt->rx_queue[2].consume_shft = RFD2_CONS_IDX_SHFT; adpt->rx_queue[2].irq_info = &adpt->irq_info[2]; adpt->rx_queue[2].intr = adpt->irq_info[2].mask & ISR_RX_PKT; adpt->rx_queue[2].irq = &adpt->irq[2]; adpt->rx_queue[2].intr = adpt->irq[2].mask & ISR_RX_PKT; case 2: adpt->rx_queue[1].produce_reg = EMAC_MAILBOX_5; adpt->rx_queue[1].produce_mask = RFD1_PROD_IDX_BMSK; Loading @@ -2206,8 +2208,8 @@ static void emac_init_rtx_queues(struct platform_device *pdev, adpt->rx_queue[1].consume_mask = RFD1_CONS_IDX_BMSK; adpt->rx_queue[1].consume_shft = RFD1_CONS_IDX_SHFT; adpt->rx_queue[1].irq_info = &adpt->irq_info[1]; adpt->rx_queue[1].intr = adpt->irq_info[1].mask & ISR_RX_PKT; adpt->rx_queue[1].irq = &adpt->irq[1]; adpt->rx_queue[1].intr = adpt->irq[1].mask & ISR_RX_PKT; case 1: adpt->rx_queue[0].produce_reg = EMAC_MAILBOX_0; adpt->rx_queue[0].produce_mask = RFD0_PROD_IDX_BMSK; Loading @@ -2221,8 +2223,8 @@ static void emac_init_rtx_queues(struct platform_device *pdev, adpt->rx_queue[0].consume_mask = RFD0_CONS_IDX_BMSK; adpt->rx_queue[0].consume_shft = RFD0_CONS_IDX_SHFT; adpt->rx_queue[0].irq_info = &adpt->irq_info[0]; adpt->rx_queue[0].intr = adpt->irq_info[0].mask & ISR_RX_PKT; adpt->rx_queue[0].irq = &adpt->irq[0]; adpt->rx_queue[0].intr = adpt->irq[0].mask & ISR_RX_PKT; break; } Loading Loading @@ -2366,7 +2368,7 @@ static int emac_suspend(struct device *device) int retval = 0; /* cannot suspend if WOL is disabled */ if (!adpt->irq_info[EMAC_WOL_IRQ].irq) if (!adpt->irq[EMAC_WOL_IRQ].irq) return -EPERM; netif_device_detach(netdev); Loading Loading @@ -2549,7 +2551,6 @@ static int emac_get_resources(struct platform_device *pdev, u8 i; struct resource *res; struct net_device *netdev = adpt->netdev; struct emac_irq_info *irq_info; struct device_node *node = pdev->dev.of_node; char *res_name[NUM_EMAC_REG_BASES] = {"emac", "emac_csr", "emac_1588", "emac_qserdes", "emac_sgmii_phy"}; Loading Loading @@ -2605,14 +2606,14 @@ static int emac_get_resources(struct platform_device *pdev, memcpy(adpt->hw.mac_perm_addr, maddr, netdev->addr_len); /* get irqs */ for (i = 0; i < EMAC_NUM_IRQ; i++) { for (i = 0; i < EMAC_IRQ_CNT; i++) { /* SGMII_PHY IRQ is only required if phy_mode is "sgmii" */ if ((i == EMAC_SGMII_PHY_IRQ) && (adpt->phy_mode != PHY_INTERFACE_MODE_SGMII)) continue; irq_info = &adpt->irq_info[i]; retval = platform_get_irq_byname(pdev, irq_info->name); retval = platform_get_irq_byname(pdev, emac_irq_cmn_tbl[i].name); if (retval < 0) { /* If WOL IRQ is not specified, WOL is disabled */ if (i == EMAC_WOL_IRQ) Loading @@ -2621,7 +2622,7 @@ static int emac_get_resources(struct platform_device *pdev, return retval; } irq_info->irq = retval; adpt->irq[i].irq = retval; } retval = emac_get_clk(pdev, adpt); Loading Loading @@ -2724,15 +2725,11 @@ static int emac_probe(struct platform_device *pdev) dma_set_max_seg_size(&pdev->dev, 65536); dma_set_seg_boundary(&pdev->dev, 0xffffffff); memcpy(adpt->irq_info, emac_irq, sizeof(adpt->irq_info)); for (i = 0; i < EMAC_NUM_CORE_IRQ; i++) { adpt->irq_info[i].adpt = adpt; adpt->irq_info[i].rxque = &adpt->rx_queue[i]; adpt->irq[i].idx = i; adpt->irq[i].mask = emac_irq_cmn_tbl[i].init_mask; } adpt->irq_info[EMAC_WOL_IRQ].adpt = adpt; adpt->irq_info[EMAC_SGMII_PHY_IRQ].adpt = adpt; adpt->irq_info[0].mask |= (msm_emac_intr_ext ? IMR_EXTENDED_MASK : adpt->irq[0].mask |= (msm_emac_intr_ext ? IMR_EXTENDED_MASK : IMR_NORMAL_MASK); retval = emac_get_resources(pdev, adpt); Loading @@ -2747,7 +2744,7 @@ static int emac_probe(struct platform_device *pdev) hw_ver = emac_reg_r32(hw, EMAC, EMAC_CORE_HW_VERSION); netdev->watchdog_timeo = EMAC_WATCHDOG_TIME; netdev->irq = adpt->irq_info[0].irq; netdev->irq = adpt->irq[0].irq; if (adpt->tstamp_en) adpt->rrdesc_size = EMAC_TS_RRDESC_SIZE; Loading drivers/net/ethernet/msm/emac/emac_ptp.c +2 −2 Original line number Diff line number Diff line Loading @@ -416,7 +416,7 @@ int emac_ptp_config(struct emac_hw *hw) getnstimeofday(&ts); rtc_settime(hw, &ts); emac_hw_get_adap(hw)->irq_info[0].mask |= PTP_INT; emac_hw_get_adap(hw)->irq[0].mask |= PTP_INT; hw->ptp_intr_mask = PPS_IN; unlock_out: Loading @@ -436,7 +436,7 @@ int emac_ptp_stop(struct emac_hw *hw) ret = emac_hw_1588_core_disable(hw); hw->ptp_intr_mask = 0; emac_hw_get_adap(hw)->irq_info[0].mask &= ~PTP_INT; emac_hw_get_adap(hw)->irq[0].mask &= ~PTP_INT; spin_unlock_irqrestore(&hw->ptp_lock, flag); Loading Loading
drivers/net/ethernet/msm/emac/emac.h +42 −7 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ #define EMAC_NUM_CORE_IRQ 4 #define EMAC_WOL_IRQ 4 #define EMAC_SGMII_PHY_IRQ 5 #define EMAC_NUM_IRQ 6 #define EMAC_IRQ_CNT 6 /* mdio/mdc gpios */ #define EMAC_GPIO_CNT 2 Loading Loading @@ -519,19 +519,42 @@ union emac_sw_tpdesc { #define EMAC_TPD_LAST_FRAGMENT 0x80000000 #define EMAC_TPD_TSTAMP_SAVE 0x80000000 struct emac_irq_info { /* emac_irq_per_dev per-device (per-adapter) irq properties. * @idx: index of this irq entry in the adapter irq array. * @irq: irq number. * @mask mask to use over status register. */ struct emac_irq_per_dev { int idx; unsigned int irq; u32 mask; }; /* emac_irq_common irq properties which are common to all devices of this driver * @name name in configuration (devicetree). * @handler ISR. * @status_reg status register offset. * @mask_reg mask register offset. * @init_mask initial value for mask to use over status register. * @irqflags request_irq() flags. */ struct emac_irq_common { char *name; irq_handler_t handler; u32 status_reg; u32 mask_reg; u32 mask; u32 init_mask; struct emac_rx_queue *rxque; struct emac_adapter *adpt; unsigned long irqflags; }; /* emac_irq_cmn_tbl a table of common irq properties to all devices of this * driver. */ extern const struct emac_irq_common emac_irq_cmn_tbl[]; struct emac_clk { struct clk *clk; bool enabled; Loading Loading @@ -600,7 +623,7 @@ struct emac_rx_queue { u8 consume_shft; u32 intr; struct emac_irq_info *irq_info; struct emac_irq_per_dev *irq; }; #define GET_RFD_BUFFER(_rque, _i) (&((_rque)->rfd.rfbuff[(_i)])) Loading Loading @@ -662,7 +685,7 @@ struct emac_tx_queue { struct emac_adapter { struct net_device *netdev; struct emac_irq_info irq_info[EMAC_NUM_IRQ]; struct emac_irq_per_dev irq[EMAC_IRQ_CNT]; unsigned int gpio[EMAC_GPIO_CNT]; struct emac_clk clk[EMAC_CLK_CNT]; Loading Loading @@ -713,6 +736,18 @@ static inline struct emac_adapter *emac_hw_get_adap(struct emac_hw *hw) return container_of(hw, struct emac_adapter, hw); } static inline struct emac_adapter *emac_irq_get_adpt(struct emac_irq_per_dev *irq) { struct emac_irq_per_dev *irq_0 = irq - irq->idx; /* why using __builtin_offsetof() and not container_of() ? * container_of(irq_0, struct emac_adapter, irq) fails to compile * because emac->irq is of array type. */ return (struct emac_adapter *) ((char *)irq_0 - __builtin_offsetof(struct emac_adapter, irq)); } /* default to trying for four seconds */ #define EMAC_TRY_LINK_TIMEOUT (4 * HZ) Loading
drivers/net/ethernet/msm/emac/emac_hw.c +18 −19 Original line number Diff line number Diff line Loading @@ -887,21 +887,21 @@ int emac_check_sgmii_autoneg(struct emac_hw *hw, u32 *speed, bool *link_up) void emac_hw_enable_intr(struct emac_hw *hw) { struct emac_adapter *adpt = emac_hw_get_adap(hw); struct emac_irq_info *irq_info; int i; for (i = 0; i < EMAC_NUM_CORE_IRQ; i++) { irq_info = &adpt->irq_info[i]; emac_reg_w32(hw, EMAC, irq_info->status_reg, ~DIS_INT); emac_reg_w32(hw, EMAC, irq_info->mask_reg, irq_info->mask); } struct emac_irq_per_dev *irq = &adpt->irq[i]; const struct emac_irq_common *irq_cmn = &emac_irq_cmn_tbl[i]; if (adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) { irq_info = &adpt->irq_info[EMAC_SGMII_PHY_IRQ]; emac_reg_w32(hw, EMAC_SGMII_PHY, irq_info->mask_reg, irq_info->mask); emac_reg_w32(hw, EMAC, irq_cmn->status_reg, ~DIS_INT); emac_reg_w32(hw, EMAC, irq_cmn->mask_reg, irq->mask); } if (adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) emac_reg_w32(hw, EMAC_SGMII_PHY, emac_irq_cmn_tbl[EMAC_SGMII_PHY_IRQ].mask_reg, adpt->irq[EMAC_SGMII_PHY_IRQ].mask); if (adpt->tstamp_en) emac_reg_w32(hw, EMAC_1588, EMAC_P1588_PTP_EXPANDED_INT_MASK, hw->ptp_intr_mask); Loading @@ -911,23 +911,22 @@ void emac_hw_enable_intr(struct emac_hw *hw) void emac_hw_disable_intr(struct emac_hw *hw) { struct emac_adapter *adpt = emac_hw_get_adap(hw); struct emac_irq_info *irq_info; int i; for (i = 0; i < EMAC_NUM_CORE_IRQ; i++) { irq_info = &adpt->irq_info[i]; emac_reg_w32(hw, EMAC, irq_info->status_reg, DIS_INT); emac_reg_w32(hw, EMAC, irq_info->mask_reg, 0); const struct emac_irq_common *irq_cmn = &emac_irq_cmn_tbl[i]; emac_reg_w32(hw, EMAC, irq_cmn->status_reg, DIS_INT); emac_reg_w32(hw, EMAC, irq_cmn->mask_reg, 0); } if (adpt->tstamp_en) emac_reg_w32(hw, EMAC_1588, EMAC_P1588_PTP_EXPANDED_INT_MASK, 0); emac_reg_w32(hw, EMAC_1588, EMAC_P1588_PTP_EXPANDED_INT_MASK, 0); if (adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) emac_reg_w32(hw, EMAC_SGMII_PHY, emac_irq_cmn_tbl[EMAC_SGMII_PHY_IRQ].mask_reg, 0); if (adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) { irq_info = &adpt->irq_info[EMAC_SGMII_PHY_IRQ]; emac_reg_w32(hw, EMAC_SGMII_PHY, irq_info->mask_reg, 0); } wmb(); } Loading
drivers/net/ethernet/msm/emac/emac_main.c +85 −88 Original line number Diff line number Diff line Loading @@ -79,32 +79,31 @@ static int msm_emac_intr_ext; module_param_named(intr_ext, msm_emac_intr_ext, int, S_IRUGO | S_IWUSR | S_IWGRP); static irqreturn_t emac_interrupt(int irq, void *data); static irqreturn_t emac_sgmii_interrupt(int irq, void *data); static irqreturn_t emac_wol_interrupt(int irq, void *data); /* EMAC HW has an issue with interrupt assignment because of which receive queue 1 is disabled and following receive rss queue to interrupt mapping is used. rss-queue intr 0 core0 1 core3 (disabled) 2 core1 3 core2 static irqreturn_t emac_isr(int irq, void *data); static irqreturn_t emac_sgmii_isr(int irq, void *data); static irqreturn_t emac_wol_isr(int irq, void *data); /* EMAC HW has an issue with interrupt assignment because of which receive queue * 1 is disabled and following receive rss queue to interrupt mapping is used: * rss-queue intr * 0 core0 * 1 core3 (disabled) * 2 core1 * 3 core2 */ static struct emac_irq_info emac_irq[EMAC_NUM_IRQ] = { { 0, "emac_core0_irq", emac_interrupt, EMAC_INT_STATUS, EMAC_INT_MASK, RX_PKT_INT0, NULL, NULL }, { 0, "emac_core3_irq", emac_interrupt, EMAC_INT3_STATUS, EMAC_INT3_MASK, 0, NULL, NULL }, { 0, "emac_core1_irq", emac_interrupt, EMAC_INT1_STATUS, EMAC_INT1_MASK, RX_PKT_INT2, NULL, NULL }, { 0, "emac_core2_irq", emac_interrupt, EMAC_INT2_STATUS, EMAC_INT2_MASK, RX_PKT_INT3, NULL, NULL }, { 0, "emac_wol_irq", emac_wol_interrupt, 0, 0, 0, NULL, NULL }, { 0, "emac_sgmii_irq", emac_sgmii_interrupt, 0, EMAC_SGMII_PHY_INTERRUPT_MASK, SGMII_ISR_MASK, NULL, NULL }, const struct emac_irq_common emac_irq_cmn_tbl[EMAC_IRQ_CNT] = { { "emac_core0_irq", emac_isr, EMAC_INT_STATUS, EMAC_INT_MASK, RX_PKT_INT0, 0}, { "emac_core3_irq", emac_isr, EMAC_INT3_STATUS, EMAC_INT3_MASK, 0, 0}, { "emac_core1_irq", emac_isr, EMAC_INT1_STATUS, EMAC_INT1_MASK, RX_PKT_INT2, 0}, { "emac_core2_irq", emac_isr, EMAC_INT2_STATUS, EMAC_INT2_MASK, RX_PKT_INT3, 0}, { "emac_wol_irq" , emac_wol_isr, 0, 0, 0, 0}, { "emac_sgmii_irq", emac_sgmii_isr, 0, EMAC_SGMII_PHY_INTERRUPT_MASK, SGMII_ISR_MASK, IRQF_TRIGGER_RISING}, }; static const char * const emac_gpio_name[] = { Loading Loading @@ -731,7 +730,7 @@ static int emac_napi_rtx(struct napi_struct *napi, int budget) struct emac_rx_queue *rxque = container_of(napi, struct emac_rx_queue, napi); struct emac_adapter *adpt = netdev_priv(rxque->netdev); struct emac_irq_info *irq_info = rxque->irq_info; struct emac_irq_per_dev *irq = rxque->irq; struct emac_hw *hw = &adpt->hw; int work_done = 0; Loading @@ -745,8 +744,9 @@ static int emac_napi_rtx(struct napi_struct *napi, int budget) quit_polling: napi_complete(napi); irq_info->mask |= rxque->intr; emac_reg_w32(hw, EMAC, irq_info->mask_reg, irq_info->mask); irq->mask |= rxque->intr; emac_reg_w32(hw, EMAC, emac_irq_cmn_tbl[irq->idx].mask_reg, irq->mask); wmb(); } Loading Loading @@ -1022,30 +1022,30 @@ static int emac_start_xmit(struct sk_buff *skb, } /* ISR */ static irqreturn_t emac_wol_interrupt(int irq, void *data) static irqreturn_t emac_wol_isr(int irq, void *data) { struct emac_irq_info *irq_info = data; struct emac_adapter *adpt = irq_info->adpt; emac_dbg(adpt, wol, "EMAC wol interrupt received\n"); emac_dbg(emac_irq_get_adpt(data), wol, "EMAC wol interrupt received\n"); return IRQ_HANDLED; } static irqreturn_t emac_interrupt(int irq, void *data) static irqreturn_t emac_isr(int _irq, void *data) { struct emac_irq_info *irq_info = data; struct emac_adapter *adpt = irq_info->adpt; struct emac_irq_per_dev *irq = data; const struct emac_irq_common *irq_cmn = &emac_irq_cmn_tbl[irq->idx]; struct emac_adapter *adpt = emac_irq_get_adpt(data); struct emac_rx_queue *rxque = &adpt->rx_queue[irq->idx]; struct emac_hw *hw = &adpt->hw; int max_ints = 1; u32 isr, status; emac_dbg(emac_irq_get_adpt(data), wol, "EMAC wol interrupt received\n"); /* disable the interrupt */ emac_reg_w32(hw, EMAC, irq_info->mask_reg, 0); emac_reg_w32(hw, EMAC, irq_cmn->mask_reg, 0); wmb(); do { isr = emac_reg_r32(hw, EMAC, irq_info->status_reg); status = isr & irq_info->mask; isr = emac_reg_r32(hw, EMAC, irq_cmn->status_reg); status = isr & irq->mask; if (status == 0) break; Loading @@ -1065,10 +1065,10 @@ static irqreturn_t emac_interrupt(int irq, void *data) /* Schedule the napi for receive queue with interrupt * status bit set */ if ((status & irq_info->rxque->intr)) { if (napi_schedule_prep(&irq_info->rxque->napi)) { irq_info->mask &= ~irq_info->rxque->intr; __napi_schedule(&irq_info->rxque->napi); if ((status & rxque->intr)) { if (napi_schedule_prep(&rxque->napi)) { irq->mask &= ~rxque->intr; __napi_schedule(&rxque->napi); } } Loading Loading @@ -1098,15 +1098,15 @@ static irqreturn_t emac_interrupt(int irq, void *data) } while (--max_ints > 0); /* enable the interrupt */ emac_reg_w32(hw, EMAC, irq_info->mask_reg, irq_info->mask); emac_reg_w32(hw, EMAC, irq_cmn->mask_reg, irq->mask); wmb(); return IRQ_HANDLED; } static irqreturn_t emac_sgmii_interrupt(int irq, void *data) static irqreturn_t emac_sgmii_isr(int _irq, void *data) { struct emac_irq_info *irq_info = data; struct emac_adapter *adpt = irq_info->adpt; struct emac_irq_per_dev *irq = data; struct emac_adapter *adpt = emac_irq_get_adpt(data); struct emac_hw *hw = &adpt->hw; u32 status; Loading @@ -1115,7 +1115,7 @@ static irqreturn_t emac_sgmii_interrupt(int irq, void *data) do { status = emac_reg_r32(hw, EMAC_SGMII_PHY, EMAC_SGMII_PHY_INTERRUPT_STATUS); status &= irq_info->mask; status &= irq->mask; if (!status) break; Loading Loading @@ -1158,10 +1158,10 @@ static inline void emac_disable_intr(struct emac_adapter *adpt) emac_hw_disable_intr(hw); for (i = 0; i < EMAC_NUM_CORE_IRQ; i++) synchronize_irq(adpt->irq_info[i].irq); synchronize_irq(adpt->irq[i].irq); /* SGMII IRQ */ synchronize_irq(adpt->irq_info[EMAC_SGMII_PHY_IRQ].irq); synchronize_irq(adpt->irq[EMAC_SGMII_PHY_IRQ].irq); } /* Configure VLAN tag strip/insert feature */ Loading Loading @@ -1638,22 +1638,24 @@ int emac_up(struct emac_adapter *adpt) } } for (i = 0; i < EMAC_NUM_IRQ; i++) { struct emac_irq_info *irq_info = &adpt->irq_info[i]; u32 flag = (i == EMAC_SGMII_PHY_IRQ) ? IRQF_TRIGGER_RISING : 0; for (i = 0; i < EMAC_IRQ_CNT; i++) { struct emac_irq_per_dev *irq = &adpt->irq[i]; const struct emac_irq_common *irq_cmn = &emac_irq_cmn_tbl[i]; if (irq_info->irq == 0) if (!irq->irq) continue; retval = request_irq(irq_info->irq, irq_info->handler, flag, irq_info->name, irq_info); retval = request_irq(irq->irq, irq_cmn->handler, irq_cmn->irqflags, irq_cmn->name, irq); if (retval) { emac_err(adpt, "Unable to allocate interrupt %d: %d\n", irq_info->irq, retval); emac_err(adpt, "error:%d on request_irq(%d:%s flags:0x%lx)\n", retval, irq->irq, irq_cmn->name, irq_cmn->irqflags); while (--i >= 0) if (adpt->irq_info[i].irq) free_irq(adpt->irq_info[i].irq, &adpt->irq_info[i]); if (adpt->irq[i].irq) free_irq(adpt->irq[i].irq, &adpt->irq[i]); goto err_request_irq; } } Loading Loading @@ -1697,9 +1699,9 @@ void emac_down(struct emac_adapter *adpt, u32 ctrl) emac_disable_intr(adpt); emac_napi_disable_all(adpt); for (i = 0; i < EMAC_NUM_IRQ; i++) if (adpt->irq_info[i].irq) free_irq(adpt->irq_info[i].irq, &adpt->irq_info[i]); for (i = 0; i < EMAC_IRQ_CNT; i++) if (adpt->irq[i].irq) free_irq(adpt->irq[i].irq, &adpt->irq[i]); for (i = 0; (!adpt->no_mdio_gpio) && i < EMAC_GPIO_CNT; i++) gpio_free(adpt->gpio[i]); Loading Loading @@ -2176,8 +2178,8 @@ static void emac_init_rtx_queues(struct platform_device *pdev, adpt->rx_queue[3].consume_mask = RFD3_CONS_IDX_BMSK; adpt->rx_queue[3].consume_shft = RFD3_CONS_IDX_SHFT; adpt->rx_queue[3].irq_info = &adpt->irq_info[3]; adpt->rx_queue[3].intr = adpt->irq_info[3].mask & ISR_RX_PKT; adpt->rx_queue[3].irq = &adpt->irq[3]; adpt->rx_queue[3].intr = adpt->irq[3].mask & ISR_RX_PKT; case 3: adpt->rx_queue[2].produce_reg = EMAC_MAILBOX_6; adpt->rx_queue[2].produce_mask = RFD2_PROD_IDX_BMSK; Loading @@ -2191,8 +2193,8 @@ static void emac_init_rtx_queues(struct platform_device *pdev, adpt->rx_queue[2].consume_mask = RFD2_CONS_IDX_BMSK; adpt->rx_queue[2].consume_shft = RFD2_CONS_IDX_SHFT; adpt->rx_queue[2].irq_info = &adpt->irq_info[2]; adpt->rx_queue[2].intr = adpt->irq_info[2].mask & ISR_RX_PKT; adpt->rx_queue[2].irq = &adpt->irq[2]; adpt->rx_queue[2].intr = adpt->irq[2].mask & ISR_RX_PKT; case 2: adpt->rx_queue[1].produce_reg = EMAC_MAILBOX_5; adpt->rx_queue[1].produce_mask = RFD1_PROD_IDX_BMSK; Loading @@ -2206,8 +2208,8 @@ static void emac_init_rtx_queues(struct platform_device *pdev, adpt->rx_queue[1].consume_mask = RFD1_CONS_IDX_BMSK; adpt->rx_queue[1].consume_shft = RFD1_CONS_IDX_SHFT; adpt->rx_queue[1].irq_info = &adpt->irq_info[1]; adpt->rx_queue[1].intr = adpt->irq_info[1].mask & ISR_RX_PKT; adpt->rx_queue[1].irq = &adpt->irq[1]; adpt->rx_queue[1].intr = adpt->irq[1].mask & ISR_RX_PKT; case 1: adpt->rx_queue[0].produce_reg = EMAC_MAILBOX_0; adpt->rx_queue[0].produce_mask = RFD0_PROD_IDX_BMSK; Loading @@ -2221,8 +2223,8 @@ static void emac_init_rtx_queues(struct platform_device *pdev, adpt->rx_queue[0].consume_mask = RFD0_CONS_IDX_BMSK; adpt->rx_queue[0].consume_shft = RFD0_CONS_IDX_SHFT; adpt->rx_queue[0].irq_info = &adpt->irq_info[0]; adpt->rx_queue[0].intr = adpt->irq_info[0].mask & ISR_RX_PKT; adpt->rx_queue[0].irq = &adpt->irq[0]; adpt->rx_queue[0].intr = adpt->irq[0].mask & ISR_RX_PKT; break; } Loading Loading @@ -2366,7 +2368,7 @@ static int emac_suspend(struct device *device) int retval = 0; /* cannot suspend if WOL is disabled */ if (!adpt->irq_info[EMAC_WOL_IRQ].irq) if (!adpt->irq[EMAC_WOL_IRQ].irq) return -EPERM; netif_device_detach(netdev); Loading Loading @@ -2549,7 +2551,6 @@ static int emac_get_resources(struct platform_device *pdev, u8 i; struct resource *res; struct net_device *netdev = adpt->netdev; struct emac_irq_info *irq_info; struct device_node *node = pdev->dev.of_node; char *res_name[NUM_EMAC_REG_BASES] = {"emac", "emac_csr", "emac_1588", "emac_qserdes", "emac_sgmii_phy"}; Loading Loading @@ -2605,14 +2606,14 @@ static int emac_get_resources(struct platform_device *pdev, memcpy(adpt->hw.mac_perm_addr, maddr, netdev->addr_len); /* get irqs */ for (i = 0; i < EMAC_NUM_IRQ; i++) { for (i = 0; i < EMAC_IRQ_CNT; i++) { /* SGMII_PHY IRQ is only required if phy_mode is "sgmii" */ if ((i == EMAC_SGMII_PHY_IRQ) && (adpt->phy_mode != PHY_INTERFACE_MODE_SGMII)) continue; irq_info = &adpt->irq_info[i]; retval = platform_get_irq_byname(pdev, irq_info->name); retval = platform_get_irq_byname(pdev, emac_irq_cmn_tbl[i].name); if (retval < 0) { /* If WOL IRQ is not specified, WOL is disabled */ if (i == EMAC_WOL_IRQ) Loading @@ -2621,7 +2622,7 @@ static int emac_get_resources(struct platform_device *pdev, return retval; } irq_info->irq = retval; adpt->irq[i].irq = retval; } retval = emac_get_clk(pdev, adpt); Loading Loading @@ -2724,15 +2725,11 @@ static int emac_probe(struct platform_device *pdev) dma_set_max_seg_size(&pdev->dev, 65536); dma_set_seg_boundary(&pdev->dev, 0xffffffff); memcpy(adpt->irq_info, emac_irq, sizeof(adpt->irq_info)); for (i = 0; i < EMAC_NUM_CORE_IRQ; i++) { adpt->irq_info[i].adpt = adpt; adpt->irq_info[i].rxque = &adpt->rx_queue[i]; adpt->irq[i].idx = i; adpt->irq[i].mask = emac_irq_cmn_tbl[i].init_mask; } adpt->irq_info[EMAC_WOL_IRQ].adpt = adpt; adpt->irq_info[EMAC_SGMII_PHY_IRQ].adpt = adpt; adpt->irq_info[0].mask |= (msm_emac_intr_ext ? IMR_EXTENDED_MASK : adpt->irq[0].mask |= (msm_emac_intr_ext ? IMR_EXTENDED_MASK : IMR_NORMAL_MASK); retval = emac_get_resources(pdev, adpt); Loading @@ -2747,7 +2744,7 @@ static int emac_probe(struct platform_device *pdev) hw_ver = emac_reg_r32(hw, EMAC, EMAC_CORE_HW_VERSION); netdev->watchdog_timeo = EMAC_WATCHDOG_TIME; netdev->irq = adpt->irq_info[0].irq; netdev->irq = adpt->irq[0].irq; if (adpt->tstamp_en) adpt->rrdesc_size = EMAC_TS_RRDESC_SIZE; Loading
drivers/net/ethernet/msm/emac/emac_ptp.c +2 −2 Original line number Diff line number Diff line Loading @@ -416,7 +416,7 @@ int emac_ptp_config(struct emac_hw *hw) getnstimeofday(&ts); rtc_settime(hw, &ts); emac_hw_get_adap(hw)->irq_info[0].mask |= PTP_INT; emac_hw_get_adap(hw)->irq[0].mask |= PTP_INT; hw->ptp_intr_mask = PPS_IN; unlock_out: Loading @@ -436,7 +436,7 @@ int emac_ptp_stop(struct emac_hw *hw) ret = emac_hw_1588_core_disable(hw); hw->ptp_intr_mask = 0; emac_hw_get_adap(hw)->irq_info[0].mask &= ~PTP_INT; emac_hw_get_adap(hw)->irq[0].mask &= ~PTP_INT; spin_unlock_irqrestore(&hw->ptp_lock, flag); Loading