Re: [PATCH v3 13/23] scsi: hisi_sas: add phy up/down/bcast and channel ISR
On 01/06/2017 06:41, Christoph Hellwig wrote: > +static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) > +{ > + struct device *dev = hisi_hba->dev; > + struct pci_dev *pdev = hisi_hba->pci_dev; > + int vectors, i, irq, rc; > + int max_msi = HISI_SAS_MSI_COUNT_V3_HW; > + int msi_vectors[HISI_SAS_MSI_COUNT_V3_HW]; > + > + if (pdev->msi_enabled) > + pci_disable_msi(pdev); How could MSIs be enabled at init time? Even if so you should use pci_free_irq_vectors. Right, I don't think it could, so this can be removed. > + for (i = 0; i < vectors; i++) > + msi_vectors[i] = pdev->irq + i; You should not need this array, just use pci_irq_vectors(). That should be ok. . Thanks, John
Re: [PATCH v3 13/23] scsi: hisi_sas: add phy up/down/bcast and channel ISR
On Wed, May 31, 2017 at 10:33:05PM +0800, John Garry wrote: > From: Xiang Chen > > Add code to initialise interrupts and add some interrupt handlers. > > Signed-off-by: John Garry > Signed-off-by: Xiang Chen > --- > drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 281 > + > 1 file changed, 281 insertions(+) > > diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c > b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c > index 9651658..49f14d2 100644 > --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c > +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c > @@ -173,6 +173,13 @@ enum { > HISI_SAS_PHY_INT_NR > }; > > +static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) > +{ > + void __iomem *regs = hisi_hba->regs + off; > + > + return readl(regs); > +} > + > static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val) > { > void __iomem *regs = hisi_hba->regs + off; > @@ -397,6 +404,276 @@ static void sl_notify_v3_hw(struct hisi_hba *hisi_hba, > int phy_no) > hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control); > } > > +static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) > +{ > + int i, res = 0; > + u32 context, port_id, link_rate, hard_phy_linkrate; > + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; > + struct asd_sas_phy *sas_phy = &phy->sas_phy; > + struct device *dev = hisi_hba->dev; > + > + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1); > + > + port_id = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA); > + port_id = (port_id >> (4 * phy_no)) & 0xf; > + link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE); > + link_rate = (link_rate >> (phy_no * 4)) & 0xf; > + > + if (port_id == 0xf) { > + dev_err(dev, "phyup: phy%d invalid portid\n", phy_no); > + res = IRQ_NONE; > + goto end; > + } > + sas_phy->linkrate = link_rate; > + hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no, > + HARD_PHY_LINKRATE); > + phy->maximum_linkrate = hard_phy_linkrate & 0xf; > + phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf; > + phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA); > + > + /* Check for SATA dev */ > + context = hisi_sas_read32(hisi_hba, PHY_CONTEXT); > + if (context & (1 << phy_no)) { > + struct hisi_sas_initial_fis *initial_fis; > + struct dev_to_host_fis *fis; > + u8 attached_sas_addr[SAS_ADDR_SIZE] = {0}; > + > + dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate); > + initial_fis = &hisi_hba->initial_fis[phy_no]; > + fis = &initial_fis->fis; > + sas_phy->oob_mode = SATA_OOB_MODE; > + attached_sas_addr[0] = 0x50; > + attached_sas_addr[7] = phy_no; > + memcpy(sas_phy->attached_sas_addr, > +attached_sas_addr, > +SAS_ADDR_SIZE); > + memcpy(sas_phy->frame_rcvd, fis, > +sizeof(struct dev_to_host_fis)); > + phy->phy_type |= PORT_TYPE_SATA; > + phy->identify.device_type = SAS_SATA_DEV; > + phy->frame_rcvd_size = sizeof(struct dev_to_host_fis); > + phy->identify.target_port_protocols = SAS_PROTOCOL_SATA; > + } else { > + u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd; > + struct sas_identify_frame *id = > + (struct sas_identify_frame *)frame_rcvd; > + > + dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate); > + for (i = 0; i < 6; i++) { > + u32 idaf = hisi_sas_phy_read32(hisi_hba, phy_no, > +RX_IDAF_DWORD0 + (i * 4)); > + frame_rcvd[i] = __swab32(idaf); > + } > + sas_phy->oob_mode = SAS_OOB_MODE; > + memcpy(sas_phy->attached_sas_addr, > +&id->sas_addr, > +SAS_ADDR_SIZE); > + phy->phy_type |= PORT_TYPE_SAS; > + phy->identify.device_type = id->dev_type; > + phy->frame_rcvd_size = sizeof(struct sas_identify_frame); > + if (phy->identify.device_type == SAS_END_DEVICE) > + phy->identify.target_port_protocols = > + SAS_PROTOCOL_SSP; > + else if (phy->identify.device_type != SAS_PHY_UNUSED) > + phy->identify.target_port_protocols = > + SAS_PROTOCOL_SMP; > + } > + > + phy->port_id = port_id; > + phy->phy_attached = 1; > + queue_work(hisi_hba->wq, &phy->phyup_ws); > + > +end: > + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, > + CHL_INT0_SL_PHY_ENABLE_MSK); > + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 0); > + > + return res; > +} > + > +static int
[PATCH v3 13/23] scsi: hisi_sas: add phy up/down/bcast and channel ISR
From: Xiang Chen Add code to initialise interrupts and add some interrupt handlers. Signed-off-by: John Garry Signed-off-by: Xiang Chen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 281 + 1 file changed, 281 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 9651658..49f14d2 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -173,6 +173,13 @@ enum { HISI_SAS_PHY_INT_NR }; +static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) +{ + void __iomem *regs = hisi_hba->regs + off; + + return readl(regs); +} + static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val) { void __iomem *regs = hisi_hba->regs + off; @@ -397,6 +404,276 @@ static void sl_notify_v3_hw(struct hisi_hba *hisi_hba, int phy_no) hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control); } +static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) +{ + int i, res = 0; + u32 context, port_id, link_rate, hard_phy_linkrate; + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; + struct device *dev = hisi_hba->dev; + + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1); + + port_id = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA); + port_id = (port_id >> (4 * phy_no)) & 0xf; + link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE); + link_rate = (link_rate >> (phy_no * 4)) & 0xf; + + if (port_id == 0xf) { + dev_err(dev, "phyup: phy%d invalid portid\n", phy_no); + res = IRQ_NONE; + goto end; + } + sas_phy->linkrate = link_rate; + hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no, + HARD_PHY_LINKRATE); + phy->maximum_linkrate = hard_phy_linkrate & 0xf; + phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf; + phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA); + + /* Check for SATA dev */ + context = hisi_sas_read32(hisi_hba, PHY_CONTEXT); + if (context & (1 << phy_no)) { + struct hisi_sas_initial_fis *initial_fis; + struct dev_to_host_fis *fis; + u8 attached_sas_addr[SAS_ADDR_SIZE] = {0}; + + dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate); + initial_fis = &hisi_hba->initial_fis[phy_no]; + fis = &initial_fis->fis; + sas_phy->oob_mode = SATA_OOB_MODE; + attached_sas_addr[0] = 0x50; + attached_sas_addr[7] = phy_no; + memcpy(sas_phy->attached_sas_addr, + attached_sas_addr, + SAS_ADDR_SIZE); + memcpy(sas_phy->frame_rcvd, fis, + sizeof(struct dev_to_host_fis)); + phy->phy_type |= PORT_TYPE_SATA; + phy->identify.device_type = SAS_SATA_DEV; + phy->frame_rcvd_size = sizeof(struct dev_to_host_fis); + phy->identify.target_port_protocols = SAS_PROTOCOL_SATA; + } else { + u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd; + struct sas_identify_frame *id = + (struct sas_identify_frame *)frame_rcvd; + + dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate); + for (i = 0; i < 6; i++) { + u32 idaf = hisi_sas_phy_read32(hisi_hba, phy_no, + RX_IDAF_DWORD0 + (i * 4)); + frame_rcvd[i] = __swab32(idaf); + } + sas_phy->oob_mode = SAS_OOB_MODE; + memcpy(sas_phy->attached_sas_addr, + &id->sas_addr, + SAS_ADDR_SIZE); + phy->phy_type |= PORT_TYPE_SAS; + phy->identify.device_type = id->dev_type; + phy->frame_rcvd_size = sizeof(struct sas_identify_frame); + if (phy->identify.device_type == SAS_END_DEVICE) + phy->identify.target_port_protocols = + SAS_PROTOCOL_SSP; + else if (phy->identify.device_type != SAS_PHY_UNUSED) + phy->identify.target_port_protocols = + SAS_PROTOCOL_SMP; + } + + phy->port_id = port_id; + phy->phy_attached = 1; + queue_work(hisi_hba->wq, &phy->phyup_ws); + +end: + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, +CHL_INT0_SL_PHY_ENABLE_MSK); + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 0); + + return res; +} + +static int phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba) +{ + int res = 0; + u32 phy_state, sl_ctrl, txid_auto; + struct device *dev =