Commit 66139921 authored by John Garry's avatar John Garry Committed by Martin K. Petersen

hisi_sas: Add path from phyup irq to SAS framework

Signed-off-by: default avatarJohn Garry <john.garry@huawei.com>
Reviewed-by: default avatarArnd Bergmann <arnd@arndb.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 07d78592
...@@ -53,6 +53,7 @@ struct hisi_sas_phy { ...@@ -53,6 +53,7 @@ struct hisi_sas_phy {
struct asd_sas_phy sas_phy; struct asd_sas_phy sas_phy;
struct sas_identify identify; struct sas_identify identify;
struct timer_list timer; struct timer_list timer;
struct work_struct phyup_ws;
u64 port_id; /* from hw */ u64 port_id; /* from hw */
u64 dev_sas_addr; u64 dev_sas_addr;
u64 phy_type; u64 phy_type;
...@@ -87,6 +88,7 @@ struct hisi_sas_slot { ...@@ -87,6 +88,7 @@ struct hisi_sas_slot {
struct hisi_sas_hw { struct hisi_sas_hw {
int (*hw_init)(struct hisi_hba *hisi_hba); int (*hw_init)(struct hisi_hba *hisi_hba);
void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no);
int complete_hdr_size; int complete_hdr_size;
}; };
......
...@@ -27,6 +27,53 @@ static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba) ...@@ -27,6 +27,53 @@ static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba)
hisi_sas_slot_index_clear(hisi_hba, i); hisi_sas_slot_index_clear(hisi_hba, i);
} }
static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no)
{
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
struct sas_ha_struct *sas_ha;
if (!phy->phy_attached)
return;
sas_ha = &hisi_hba->sha;
sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE);
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
sphy->negotiated_linkrate = sas_phy->linkrate;
sphy->minimum_linkrate = phy->minimum_linkrate;
sphy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
sphy->maximum_linkrate = phy->maximum_linkrate;
}
if (phy->phy_type & PORT_TYPE_SAS) {
struct sas_identify_frame *id;
id = (struct sas_identify_frame *)phy->frame_rcvd;
id->dev_type = phy->identify.device_type;
id->initiator_bits = SAS_PROTOCOL_ALL;
id->target_bits = phy->identify.target_port_protocols;
} else if (phy->phy_type & PORT_TYPE_SATA) {
/*Nothing*/
}
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
sas_ha->notify_port_event(sas_phy, PORTE_BYTES_DMAED);
}
static void hisi_sas_phyup_work(struct work_struct *work)
{
struct hisi_sas_phy *phy =
container_of(work, struct hisi_sas_phy, phyup_ws);
struct hisi_hba *hisi_hba = phy->hisi_hba;
struct asd_sas_phy *sas_phy = &phy->sas_phy;
int phy_no = sas_phy->id;
hisi_hba->hw->sl_notify(hisi_hba, phy_no); /* This requires a sleep */
hisi_sas_bytes_dmaed(hisi_hba, phy_no);
}
static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no) static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no)
{ {
...@@ -49,6 +96,8 @@ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no) ...@@ -49,6 +96,8 @@ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no)
sas_phy->frame_rcvd = &phy->frame_rcvd[0]; sas_phy->frame_rcvd = &phy->frame_rcvd[0];
sas_phy->ha = (struct sas_ha_struct *)hisi_hba->shost->hostdata; sas_phy->ha = (struct sas_ha_struct *)hisi_hba->shost->hostdata;
sas_phy->lldd_phy = phy; sas_phy->lldd_phy = phy;
INIT_WORK(&phy->phyup_ws, hisi_sas_phyup_work);
} }
static struct scsi_transport_template *hisi_sas_stt; static struct scsi_transport_template *hisi_sas_stt;
......
...@@ -728,6 +728,19 @@ static void phys_init_v1_hw(struct hisi_hba *hisi_hba) ...@@ -728,6 +728,19 @@ static void phys_init_v1_hw(struct hisi_hba *hisi_hba)
mod_timer(timer, jiffies + HZ); mod_timer(timer, jiffies + HZ);
} }
static void sl_notify_v1_hw(struct hisi_hba *hisi_hba, int phy_no)
{
u32 sl_control;
sl_control = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
sl_control |= SL_CONTROL_NOTIFY_EN_MSK;
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
msleep(1);
sl_control = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
sl_control &= ~SL_CONTROL_NOTIFY_EN_MSK;
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
}
/* Interrupts */ /* Interrupts */
static irqreturn_t int_phyup_v1_hw(int irq_no, void *p) static irqreturn_t int_phyup_v1_hw(int irq_no, void *p)
{ {
...@@ -791,6 +804,7 @@ static irqreturn_t int_phyup_v1_hw(int irq_no, void *p) ...@@ -791,6 +804,7 @@ static irqreturn_t int_phyup_v1_hw(int irq_no, void *p)
else if (phy->identify.device_type != SAS_PHY_UNUSED) else if (phy->identify.device_type != SAS_PHY_UNUSED)
phy->identify.target_port_protocols = phy->identify.target_port_protocols =
SAS_PROTOCOL_SMP; SAS_PROTOCOL_SMP;
queue_work(hisi_hba->wq, &phy->phyup_ws);
end: end:
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2, hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
...@@ -904,6 +918,7 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba) ...@@ -904,6 +918,7 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba)
static const struct hisi_sas_hw hisi_sas_v1_hw = { static const struct hisi_sas_hw hisi_sas_v1_hw = {
.hw_init = hisi_sas_v1_init, .hw_init = hisi_sas_v1_init,
.sl_notify = sl_notify_v1_hw,
.complete_hdr_size = sizeof(struct hisi_sas_complete_v1_hdr), .complete_hdr_size = sizeof(struct hisi_sas_complete_v1_hdr),
}; };
......
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