Skip to content

Commit

Permalink
[SCSI] pm8001: enhance error handle for IO patch
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
jack wang authored and James Bottomley committed Dec 10, 2009
1 parent 9e79e12 commit 1cc943a
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 5 deletions.
29 changes: 26 additions & 3 deletions drivers/scsi/pm8001/pm8001_hwi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
u8 link_rate =
(u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
u8 port_id = (u8)(lr_evt_status_phyid_portid & 0x0000000F);
u8 phy_id =
(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 pm8001_phy *phy = &pm8001_ha->phy[phy_id];
unsigned long flags;
u8 deviceType = pPayload->sas_identify.dev_type;

port->port_state = portstate;
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("HW_EVENT_SAS_PHY_UP \n"));

Expand All @@ -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_chip_phy_ctl_req(pm8001_ha, phy_id,
PHY_NOTIFY_ENABLE_SPINUP);
port->port_attached = 1;
get_lrate_mode(phy, link_rate);
break;
case SAS_EDGE_EXPANDER_DEVICE:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("expander device.\n"));
port->port_attached = 1;
get_lrate_mode(phy, link_rate);
break;
case SAS_FANOUT_EXPANDER_DEVICE:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("fanout expander device.\n"));
port->port_attached = 1;
get_lrate_mode(phy, link_rate);
break;
default:
Expand Down Expand Up @@ -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);
u8 link_rate =
(u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
u8 port_id = (u8)(lr_evt_status_phyid_portid & 0x0000000F);
u8 phy_id =
(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 pm8001_phy *phy = &pm8001_ha->phy[phy_id];
unsigned long flags;
port->port_state = portstate;
port->port_attached = 1;
get_lrate_mode(phy, link_rate);
phy->phy_type |= PORT_TYPE_SATA;
phy->phy_attached = 1;
Expand Down Expand Up @@ -3014,7 +3027,13 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
(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 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) {
case PORT_VALID:
break;
Expand All @@ -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_MSG_DBG(pm8001_ha,
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,
port_id, phy_id, 0, 0);
break;
case PORT_IN_RESET:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk(" PortInReset portID %d \n", port_id));
pm8001_printk(" Port In Reset portID %d \n", port_id));
break;
case PORT_NOT_ESTABLISHED:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n"));
port->port_attached = 0;
break;
case PORT_LOSTCOMM:
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk(" phy Down and PORT_LOSTCOMM\n"));
PM8001_MSG_DBG(pm8001_ha,
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,
port_id, phy_id, 0, 0);
break;
default:
port->port_attached = 0;
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk(" phy Down and(default) = %x\n",
portstate));
Expand Down
7 changes: 6 additions & 1 deletion drivers/scsi/pm8001/pm8001_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,13 @@ static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
{
int i;
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_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);
if (!pm8001_ha->tags)
Expand Down
49 changes: 48 additions & 1 deletion drivers/scsi/pm8001/pm8001_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,23 @@ int pm8001_slave_configure(struct scsi_device *sdev)
}
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.
* @task: the task to be execute.
Expand All @@ -346,11 +363,12 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
struct domain_device *dev = task->dev;
struct pm8001_hba_info *pm8001_ha;
struct pm8001_device *pm8001_dev;
struct pm8001_port *port = NULL;
struct sas_task *t = task;
struct pm8001_ccb_info *ccb;
u32 tag = 0xdeadbeef, rc, n_elem = 0;
u32 n = num;
unsigned long flags = 0;
unsigned long flags = 0, flags_libsas = 0;

if (!dev->port) {
struct task_status_struct *tsm = &t->task_status;
Expand Down Expand Up @@ -379,6 +397,35 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
rc = SAS_PHY_DOWN;
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);
if (rc)
goto err_out;
Expand Down
4 changes: 4 additions & 0 deletions drivers/scsi/pm8001/pm8001_sas.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ struct pm8001_chip_info {

struct pm8001_port {
struct asd_sas_port sas_port;
u8 port_attached;
u8 wide_port_phymap;
u8 port_state;
struct list_head list;
};

struct pm8001_phy {
Expand Down

0 comments on commit 1cc943a

Please sign in to comment.