mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-04-09 17:48:02 +07:00
[SCSI] pm8001: enhance error handle for IO patch
Enhance error handle for IO patch, when the port is down, fast return phy down for task. Signed-off-by: Jack Wang <jack_wang@usish.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
9e79e12554
commit
1cc943ae50
@ -2906,13 +2906,17 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
|
|||||||
le32_to_cpu(pPayload->lr_evt_status_phyid_portid);
|
le32_to_cpu(pPayload->lr_evt_status_phyid_portid);
|
||||||
u8 link_rate =
|
u8 link_rate =
|
||||||
(u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
|
(u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
|
||||||
|
u8 port_id = (u8)(lr_evt_status_phyid_portid & 0x0000000F);
|
||||||
u8 phy_id =
|
u8 phy_id =
|
||||||
(u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
|
(u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
|
||||||
|
u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
|
||||||
|
u8 portstate = (u8)(npip_portstate & 0x0000000F);
|
||||||
|
struct pm8001_port *port = &pm8001_ha->port[port_id];
|
||||||
struct sas_ha_struct *sas_ha = pm8001_ha->sas;
|
struct sas_ha_struct *sas_ha = pm8001_ha->sas;
|
||||||
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
|
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u8 deviceType = pPayload->sas_identify.dev_type;
|
u8 deviceType = pPayload->sas_identify.dev_type;
|
||||||
|
port->port_state = portstate;
|
||||||
PM8001_MSG_DBG(pm8001_ha,
|
PM8001_MSG_DBG(pm8001_ha,
|
||||||
pm8001_printk("HW_EVENT_SAS_PHY_UP \n"));
|
pm8001_printk("HW_EVENT_SAS_PHY_UP \n"));
|
||||||
|
|
||||||
@ -2925,16 +2929,19 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
|
|||||||
PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n"));
|
PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n"));
|
||||||
pm8001_chip_phy_ctl_req(pm8001_ha, phy_id,
|
pm8001_chip_phy_ctl_req(pm8001_ha, phy_id,
|
||||||
PHY_NOTIFY_ENABLE_SPINUP);
|
PHY_NOTIFY_ENABLE_SPINUP);
|
||||||
|
port->port_attached = 1;
|
||||||
get_lrate_mode(phy, link_rate);
|
get_lrate_mode(phy, link_rate);
|
||||||
break;
|
break;
|
||||||
case SAS_EDGE_EXPANDER_DEVICE:
|
case SAS_EDGE_EXPANDER_DEVICE:
|
||||||
PM8001_MSG_DBG(pm8001_ha,
|
PM8001_MSG_DBG(pm8001_ha,
|
||||||
pm8001_printk("expander device.\n"));
|
pm8001_printk("expander device.\n"));
|
||||||
|
port->port_attached = 1;
|
||||||
get_lrate_mode(phy, link_rate);
|
get_lrate_mode(phy, link_rate);
|
||||||
break;
|
break;
|
||||||
case SAS_FANOUT_EXPANDER_DEVICE:
|
case SAS_FANOUT_EXPANDER_DEVICE:
|
||||||
PM8001_MSG_DBG(pm8001_ha,
|
PM8001_MSG_DBG(pm8001_ha,
|
||||||
pm8001_printk("fanout expander device.\n"));
|
pm8001_printk("fanout expander device.\n"));
|
||||||
|
port->port_attached = 1;
|
||||||
get_lrate_mode(phy, link_rate);
|
get_lrate_mode(phy, link_rate);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2976,11 +2983,17 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
|
|||||||
le32_to_cpu(pPayload->lr_evt_status_phyid_portid);
|
le32_to_cpu(pPayload->lr_evt_status_phyid_portid);
|
||||||
u8 link_rate =
|
u8 link_rate =
|
||||||
(u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
|
(u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
|
||||||
|
u8 port_id = (u8)(lr_evt_status_phyid_portid & 0x0000000F);
|
||||||
u8 phy_id =
|
u8 phy_id =
|
||||||
(u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
|
(u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
|
||||||
|
u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
|
||||||
|
u8 portstate = (u8)(npip_portstate & 0x0000000F);
|
||||||
|
struct pm8001_port *port = &pm8001_ha->port[port_id];
|
||||||
struct sas_ha_struct *sas_ha = pm8001_ha->sas;
|
struct sas_ha_struct *sas_ha = pm8001_ha->sas;
|
||||||
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
|
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
port->port_state = portstate;
|
||||||
|
port->port_attached = 1;
|
||||||
get_lrate_mode(phy, link_rate);
|
get_lrate_mode(phy, link_rate);
|
||||||
phy->phy_type |= PORT_TYPE_SATA;
|
phy->phy_type |= PORT_TYPE_SATA;
|
||||||
phy->phy_attached = 1;
|
phy->phy_attached = 1;
|
||||||
@ -3014,7 +3027,13 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
|
|||||||
(u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
|
(u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
|
||||||
u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
|
u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
|
||||||
u8 portstate = (u8)(npip_portstate & 0x0000000F);
|
u8 portstate = (u8)(npip_portstate & 0x0000000F);
|
||||||
|
struct pm8001_port *port = &pm8001_ha->port[port_id];
|
||||||
|
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
|
||||||
|
port->port_state = portstate;
|
||||||
|
phy->phy_type = 0;
|
||||||
|
phy->identify.device_type = 0;
|
||||||
|
phy->phy_attached = 0;
|
||||||
|
memset(&phy->dev_sas_addr, 0, SAS_ADDR_SIZE);
|
||||||
switch (portstate) {
|
switch (portstate) {
|
||||||
case PORT_VALID:
|
case PORT_VALID:
|
||||||
break;
|
break;
|
||||||
@ -3023,26 +3042,30 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
|
|||||||
pm8001_printk(" PortInvalid portID %d \n", port_id));
|
pm8001_printk(" PortInvalid portID %d \n", port_id));
|
||||||
PM8001_MSG_DBG(pm8001_ha,
|
PM8001_MSG_DBG(pm8001_ha,
|
||||||
pm8001_printk(" Last phy Down and port invalid\n"));
|
pm8001_printk(" Last phy Down and port invalid\n"));
|
||||||
|
port->port_attached = 0;
|
||||||
pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
|
pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
|
||||||
port_id, phy_id, 0, 0);
|
port_id, phy_id, 0, 0);
|
||||||
break;
|
break;
|
||||||
case PORT_IN_RESET:
|
case PORT_IN_RESET:
|
||||||
PM8001_MSG_DBG(pm8001_ha,
|
PM8001_MSG_DBG(pm8001_ha,
|
||||||
pm8001_printk(" PortInReset portID %d \n", port_id));
|
pm8001_printk(" Port In Reset portID %d \n", port_id));
|
||||||
break;
|
break;
|
||||||
case PORT_NOT_ESTABLISHED:
|
case PORT_NOT_ESTABLISHED:
|
||||||
PM8001_MSG_DBG(pm8001_ha,
|
PM8001_MSG_DBG(pm8001_ha,
|
||||||
pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n"));
|
pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n"));
|
||||||
|
port->port_attached = 0;
|
||||||
break;
|
break;
|
||||||
case PORT_LOSTCOMM:
|
case PORT_LOSTCOMM:
|
||||||
PM8001_MSG_DBG(pm8001_ha,
|
PM8001_MSG_DBG(pm8001_ha,
|
||||||
pm8001_printk(" phy Down and PORT_LOSTCOMM\n"));
|
pm8001_printk(" phy Down and PORT_LOSTCOMM\n"));
|
||||||
PM8001_MSG_DBG(pm8001_ha,
|
PM8001_MSG_DBG(pm8001_ha,
|
||||||
pm8001_printk(" Last phy Down and port invalid\n"));
|
pm8001_printk(" Last phy Down and port invalid\n"));
|
||||||
|
port->port_attached = 0;
|
||||||
pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
|
pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
|
||||||
port_id, phy_id, 0, 0);
|
port_id, phy_id, 0, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
port->port_attached = 0;
|
||||||
PM8001_MSG_DBG(pm8001_ha,
|
PM8001_MSG_DBG(pm8001_ha,
|
||||||
pm8001_printk(" phy Down and(default) = %x\n",
|
pm8001_printk(" phy Down and(default) = %x\n",
|
||||||
portstate));
|
portstate));
|
||||||
|
@ -200,8 +200,13 @@ static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
spin_lock_init(&pm8001_ha->lock);
|
spin_lock_init(&pm8001_ha->lock);
|
||||||
for (i = 0; i < pm8001_ha->chip->n_phy; i++)
|
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
|
||||||
pm8001_phy_init(pm8001_ha, i);
|
pm8001_phy_init(pm8001_ha, i);
|
||||||
|
pm8001_ha->port[i].wide_port_phymap = 0;
|
||||||
|
pm8001_ha->port[i].port_attached = 0;
|
||||||
|
pm8001_ha->port[i].port_state = 0;
|
||||||
|
INIT_LIST_HEAD(&pm8001_ha->port[i].list);
|
||||||
|
}
|
||||||
|
|
||||||
pm8001_ha->tags = kzalloc(PM8001_MAX_CCB, GFP_KERNEL);
|
pm8001_ha->tags = kzalloc(PM8001_MAX_CCB, GFP_KERNEL);
|
||||||
if (!pm8001_ha->tags)
|
if (!pm8001_ha->tags)
|
||||||
|
@ -329,6 +329,23 @@ int pm8001_slave_configure(struct scsi_device *sdev)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/* Find the local port id that's attached to this device */
|
||||||
|
static int sas_find_local_port_id(struct domain_device *dev)
|
||||||
|
{
|
||||||
|
struct domain_device *pdev = dev->parent;
|
||||||
|
|
||||||
|
/* Directly attached device */
|
||||||
|
if (!pdev)
|
||||||
|
return dev->port->id;
|
||||||
|
while (pdev) {
|
||||||
|
struct domain_device *pdev_p = pdev->parent;
|
||||||
|
if (!pdev_p)
|
||||||
|
return pdev->port->id;
|
||||||
|
pdev = pdev->parent;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pm8001_task_exec - queue the task(ssp, smp && ata) to the hardware.
|
* pm8001_task_exec - queue the task(ssp, smp && ata) to the hardware.
|
||||||
* @task: the task to be execute.
|
* @task: the task to be execute.
|
||||||
@ -346,11 +363,12 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
|
|||||||
struct domain_device *dev = task->dev;
|
struct domain_device *dev = task->dev;
|
||||||
struct pm8001_hba_info *pm8001_ha;
|
struct pm8001_hba_info *pm8001_ha;
|
||||||
struct pm8001_device *pm8001_dev;
|
struct pm8001_device *pm8001_dev;
|
||||||
|
struct pm8001_port *port = NULL;
|
||||||
struct sas_task *t = task;
|
struct sas_task *t = task;
|
||||||
struct pm8001_ccb_info *ccb;
|
struct pm8001_ccb_info *ccb;
|
||||||
u32 tag = 0xdeadbeef, rc, n_elem = 0;
|
u32 tag = 0xdeadbeef, rc, n_elem = 0;
|
||||||
u32 n = num;
|
u32 n = num;
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0, flags_libsas = 0;
|
||||||
|
|
||||||
if (!dev->port) {
|
if (!dev->port) {
|
||||||
struct task_status_struct *tsm = &t->task_status;
|
struct task_status_struct *tsm = &t->task_status;
|
||||||
@ -379,6 +397,35 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
|
|||||||
rc = SAS_PHY_DOWN;
|
rc = SAS_PHY_DOWN;
|
||||||
goto out_done;
|
goto out_done;
|
||||||
}
|
}
|
||||||
|
port = &pm8001_ha->port[sas_find_local_port_id(dev)];
|
||||||
|
if (!port->port_attached) {
|
||||||
|
if (sas_protocol_ata(t->task_proto)) {
|
||||||
|
struct task_status_struct *ts = &t->task_status;
|
||||||
|
ts->resp = SAS_TASK_UNDELIVERED;
|
||||||
|
ts->stat = SAS_PHY_DOWN;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
|
||||||
|
spin_unlock_irqrestore(dev->sata_dev.ap->lock,
|
||||||
|
flags_libsas);
|
||||||
|
t->task_done(t);
|
||||||
|
spin_lock_irqsave(dev->sata_dev.ap->lock,
|
||||||
|
flags_libsas);
|
||||||
|
spin_lock_irqsave(&pm8001_ha->lock, flags);
|
||||||
|
if (n > 1)
|
||||||
|
t = list_entry(t->list.next,
|
||||||
|
struct sas_task, list);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
struct task_status_struct *ts = &t->task_status;
|
||||||
|
ts->resp = SAS_TASK_UNDELIVERED;
|
||||||
|
ts->stat = SAS_PHY_DOWN;
|
||||||
|
t->task_done(t);
|
||||||
|
if (n > 1)
|
||||||
|
t = list_entry(t->list.next,
|
||||||
|
struct sas_task, list);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
rc = pm8001_tag_alloc(pm8001_ha, &tag);
|
rc = pm8001_tag_alloc(pm8001_ha, &tag);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
@ -164,6 +164,10 @@ struct pm8001_chip_info {
|
|||||||
|
|
||||||
struct pm8001_port {
|
struct pm8001_port {
|
||||||
struct asd_sas_port sas_port;
|
struct asd_sas_port sas_port;
|
||||||
|
u8 port_attached;
|
||||||
|
u8 wide_port_phymap;
|
||||||
|
u8 port_state;
|
||||||
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pm8001_phy {
|
struct pm8001_phy {
|
||||||
|
Loading…
Reference in New Issue
Block a user