aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjack wang <jack_wang@usish.com>2009-12-07 04:22:42 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-12-10 11:00:12 -0500
commit1cc943ae5003e4612a73119cb6fb637a45c2714d (patch)
tree07d7c64475aaec5f05eeea86d13d81b27baee3e1
parent9e79e12554d651f586ff2364e69a8e9cd5e9dbcb (diff)
[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>
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c29
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c7
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c49
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h4
4 files changed, 84 insertions, 5 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 68695b72e1ef..3a121fbd4fc5 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -2906,13 +2906,17 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
2906 le32_to_cpu(pPayload->lr_evt_status_phyid_portid); 2906 le32_to_cpu(pPayload->lr_evt_status_phyid_portid);
2907 u8 link_rate = 2907 u8 link_rate =
2908 (u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28); 2908 (u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
2909 u8 port_id = (u8)(lr_evt_status_phyid_portid & 0x0000000F);
2909 u8 phy_id = 2910 u8 phy_id =
2910 (u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4); 2911 (u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
2912 u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
2913 u8 portstate = (u8)(npip_portstate & 0x0000000F);
2914 struct pm8001_port *port = &pm8001_ha->port[port_id];
2911 struct sas_ha_struct *sas_ha = pm8001_ha->sas; 2915 struct sas_ha_struct *sas_ha = pm8001_ha->sas;
2912 struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; 2916 struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
2913 unsigned long flags; 2917 unsigned long flags;
2914 u8 deviceType = pPayload->sas_identify.dev_type; 2918 u8 deviceType = pPayload->sas_identify.dev_type;
2915 2919 port->port_state = portstate;
2916 PM8001_MSG_DBG(pm8001_ha, 2920 PM8001_MSG_DBG(pm8001_ha,
2917 pm8001_printk("HW_EVENT_SAS_PHY_UP \n")); 2921 pm8001_printk("HW_EVENT_SAS_PHY_UP \n"));
2918 2922
@@ -2925,16 +2929,19 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
2925 PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n")); 2929 PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n"));
2926 pm8001_chip_phy_ctl_req(pm8001_ha, phy_id, 2930 pm8001_chip_phy_ctl_req(pm8001_ha, phy_id,
2927 PHY_NOTIFY_ENABLE_SPINUP); 2931 PHY_NOTIFY_ENABLE_SPINUP);
2932 port->port_attached = 1;
2928 get_lrate_mode(phy, link_rate); 2933 get_lrate_mode(phy, link_rate);
2929 break; 2934 break;
2930 case SAS_EDGE_EXPANDER_DEVICE: 2935 case SAS_EDGE_EXPANDER_DEVICE:
2931 PM8001_MSG_DBG(pm8001_ha, 2936 PM8001_MSG_DBG(pm8001_ha,
2932 pm8001_printk("expander device.\n")); 2937 pm8001_printk("expander device.\n"));
2938 port->port_attached = 1;
2933 get_lrate_mode(phy, link_rate); 2939 get_lrate_mode(phy, link_rate);
2934 break; 2940 break;
2935 case SAS_FANOUT_EXPANDER_DEVICE: 2941 case SAS_FANOUT_EXPANDER_DEVICE:
2936 PM8001_MSG_DBG(pm8001_ha, 2942 PM8001_MSG_DBG(pm8001_ha,
2937 pm8001_printk("fanout expander device.\n")); 2943 pm8001_printk("fanout expander device.\n"));
2944 port->port_attached = 1;
2938 get_lrate_mode(phy, link_rate); 2945 get_lrate_mode(phy, link_rate);
2939 break; 2946 break;
2940 default: 2947 default:
@@ -2976,11 +2983,17 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
2976 le32_to_cpu(pPayload->lr_evt_status_phyid_portid); 2983 le32_to_cpu(pPayload->lr_evt_status_phyid_portid);
2977 u8 link_rate = 2984 u8 link_rate =
2978 (u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28); 2985 (u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
2986 u8 port_id = (u8)(lr_evt_status_phyid_portid & 0x0000000F);
2979 u8 phy_id = 2987 u8 phy_id =
2980 (u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4); 2988 (u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
2989 u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
2990 u8 portstate = (u8)(npip_portstate & 0x0000000F);
2991 struct pm8001_port *port = &pm8001_ha->port[port_id];
2981 struct sas_ha_struct *sas_ha = pm8001_ha->sas; 2992 struct sas_ha_struct *sas_ha = pm8001_ha->sas;
2982 struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; 2993 struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
2983 unsigned long flags; 2994 unsigned long flags;
2995 port->port_state = portstate;
2996 port->port_attached = 1;
2984 get_lrate_mode(phy, link_rate); 2997 get_lrate_mode(phy, link_rate);
2985 phy->phy_type |= PORT_TYPE_SATA; 2998 phy->phy_type |= PORT_TYPE_SATA;
2986 phy->phy_attached = 1; 2999 phy->phy_attached = 1;
@@ -3014,7 +3027,13 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
3014 (u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4); 3027 (u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
3015 u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate); 3028 u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
3016 u8 portstate = (u8)(npip_portstate & 0x0000000F); 3029 u8 portstate = (u8)(npip_portstate & 0x0000000F);
3017 3030 struct pm8001_port *port = &pm8001_ha->port[port_id];
3031 struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
3032 port->port_state = portstate;
3033 phy->phy_type = 0;
3034 phy->identify.device_type = 0;
3035 phy->phy_attached = 0;
3036 memset(&phy->dev_sas_addr, 0, SAS_ADDR_SIZE);
3018 switch (portstate) { 3037 switch (portstate) {
3019 case PORT_VALID: 3038 case PORT_VALID:
3020 break; 3039 break;
@@ -3023,26 +3042,30 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
3023 pm8001_printk(" PortInvalid portID %d \n", port_id)); 3042 pm8001_printk(" PortInvalid portID %d \n", port_id));
3024 PM8001_MSG_DBG(pm8001_ha, 3043 PM8001_MSG_DBG(pm8001_ha,
3025 pm8001_printk(" Last phy Down and port invalid\n")); 3044 pm8001_printk(" Last phy Down and port invalid\n"));
3045 port->port_attached = 0;
3026 pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, 3046 pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
3027 port_id, phy_id, 0, 0); 3047 port_id, phy_id, 0, 0);
3028 break; 3048 break;
3029 case PORT_IN_RESET: 3049 case PORT_IN_RESET:
3030 PM8001_MSG_DBG(pm8001_ha, 3050 PM8001_MSG_DBG(pm8001_ha,
3031 pm8001_printk(" PortInReset portID %d \n", port_id)); 3051 pm8001_printk(" Port In Reset portID %d \n", port_id));
3032 break; 3052 break;
3033 case PORT_NOT_ESTABLISHED: 3053 case PORT_NOT_ESTABLISHED:
3034 PM8001_MSG_DBG(pm8001_ha, 3054 PM8001_MSG_DBG(pm8001_ha,
3035 pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n")); 3055 pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n"));
3056 port->port_attached = 0;
3036 break; 3057 break;
3037 case PORT_LOSTCOMM: 3058 case PORT_LOSTCOMM:
3038 PM8001_MSG_DBG(pm8001_ha, 3059 PM8001_MSG_DBG(pm8001_ha,
3039 pm8001_printk(" phy Down and PORT_LOSTCOMM\n")); 3060 pm8001_printk(" phy Down and PORT_LOSTCOMM\n"));
3040 PM8001_MSG_DBG(pm8001_ha, 3061 PM8001_MSG_DBG(pm8001_ha,
3041 pm8001_printk(" Last phy Down and port invalid\n")); 3062 pm8001_printk(" Last phy Down and port invalid\n"));
3063 port->port_attached = 0;
3042 pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, 3064 pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
3043 port_id, phy_id, 0, 0); 3065 port_id, phy_id, 0, 0);
3044 break; 3066 break;
3045 default: 3067 default:
3068 port->port_attached = 0;
3046 PM8001_MSG_DBG(pm8001_ha, 3069 PM8001_MSG_DBG(pm8001_ha,
3047 pm8001_printk(" phy Down and(default) = %x\n", 3070 pm8001_printk(" phy Down and(default) = %x\n",
3048 portstate)); 3071 portstate));
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 42ebe725d5a5..fb6379a4bee4 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -200,8 +200,13 @@ static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha)
200{ 200{
201 int i; 201 int i;
202 spin_lock_init(&pm8001_ha->lock); 202 spin_lock_init(&pm8001_ha->lock);
203 for (i = 0; i < pm8001_ha->chip->n_phy; i++) 203 for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
204 pm8001_phy_init(pm8001_ha, i); 204 pm8001_phy_init(pm8001_ha, i);
205 pm8001_ha->port[i].wide_port_phymap = 0;
206 pm8001_ha->port[i].port_attached = 0;
207 pm8001_ha->port[i].port_state = 0;
208 INIT_LIST_HEAD(&pm8001_ha->port[i].list);
209 }
205 210
206 pm8001_ha->tags = kzalloc(PM8001_MAX_CCB, GFP_KERNEL); 211 pm8001_ha->tags = kzalloc(PM8001_MAX_CCB, GFP_KERNEL);
207 if (!pm8001_ha->tags) 212 if (!pm8001_ha->tags)
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 1f767a0e727a..49721c886c26 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -329,6 +329,23 @@ int pm8001_slave_configure(struct scsi_device *sdev)
329 } 329 }
330 return 0; 330 return 0;
331} 331}
332 /* Find the local port id that's attached to this device */
333static int sas_find_local_port_id(struct domain_device *dev)
334{
335 struct domain_device *pdev = dev->parent;
336
337 /* Directly attached device */
338 if (!pdev)
339 return dev->port->id;
340 while (pdev) {
341 struct domain_device *pdev_p = pdev->parent;
342 if (!pdev_p)
343 return pdev->port->id;
344 pdev = pdev->parent;
345 }
346 return 0;
347}
348
332/** 349/**
333 * pm8001_task_exec - queue the task(ssp, smp && ata) to the hardware. 350 * pm8001_task_exec - queue the task(ssp, smp && ata) to the hardware.
334 * @task: the task to be execute. 351 * @task: the task to be execute.
@@ -346,11 +363,12 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
346 struct domain_device *dev = task->dev; 363 struct domain_device *dev = task->dev;
347 struct pm8001_hba_info *pm8001_ha; 364 struct pm8001_hba_info *pm8001_ha;
348 struct pm8001_device *pm8001_dev; 365 struct pm8001_device *pm8001_dev;
366 struct pm8001_port *port = NULL;
349 struct sas_task *t = task; 367 struct sas_task *t = task;
350 struct pm8001_ccb_info *ccb; 368 struct pm8001_ccb_info *ccb;
351 u32 tag = 0xdeadbeef, rc, n_elem = 0; 369 u32 tag = 0xdeadbeef, rc, n_elem = 0;
352 u32 n = num; 370 u32 n = num;
353 unsigned long flags = 0; 371 unsigned long flags = 0, flags_libsas = 0;
354 372
355 if (!dev->port) { 373 if (!dev->port) {
356 struct task_status_struct *tsm = &t->task_status; 374 struct task_status_struct *tsm = &t->task_status;
@@ -379,6 +397,35 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
379 rc = SAS_PHY_DOWN; 397 rc = SAS_PHY_DOWN;
380 goto out_done; 398 goto out_done;
381 } 399 }
400 port = &pm8001_ha->port[sas_find_local_port_id(dev)];
401 if (!port->port_attached) {
402 if (sas_protocol_ata(t->task_proto)) {
403 struct task_status_struct *ts = &t->task_status;
404 ts->resp = SAS_TASK_UNDELIVERED;
405 ts->stat = SAS_PHY_DOWN;
406
407 spin_unlock_irqrestore(&pm8001_ha->lock, flags);
408 spin_unlock_irqrestore(dev->sata_dev.ap->lock,
409 flags_libsas);
410 t->task_done(t);
411 spin_lock_irqsave(dev->sata_dev.ap->lock,
412 flags_libsas);
413 spin_lock_irqsave(&pm8001_ha->lock, flags);
414 if (n > 1)
415 t = list_entry(t->list.next,
416 struct sas_task, list);
417 continue;
418 } else {
419 struct task_status_struct *ts = &t->task_status;
420 ts->resp = SAS_TASK_UNDELIVERED;
421 ts->stat = SAS_PHY_DOWN;
422 t->task_done(t);
423 if (n > 1)
424 t = list_entry(t->list.next,
425 struct sas_task, list);
426 continue;
427 }
428 }
382 rc = pm8001_tag_alloc(pm8001_ha, &tag); 429 rc = pm8001_tag_alloc(pm8001_ha, &tag);
383 if (rc) 430 if (rc)
384 goto err_out; 431 goto err_out;
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 30f2ede55a75..c44a1150d70d 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -164,6 +164,10 @@ struct pm8001_chip_info {
164 164
165struct pm8001_port { 165struct pm8001_port {
166 struct asd_sas_port sas_port; 166 struct asd_sas_port sas_port;
167 u8 port_attached;
168 u8 wide_port_phymap;
169 u8 port_state;
170 struct list_head list;
167}; 171};
168 172
169struct pm8001_phy { 173struct pm8001_phy {