aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pm8001/pm8001_sas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_sas.c')
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c119
1 files changed, 104 insertions, 15 deletions
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index b961112395d5..a85d73de7c80 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver 2 * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver
3 * 3 *
4 * Copyright (c) 2008-2009 USI Co., Ltd. 4 * Copyright (c) 2008-2009 USI Co., Ltd.
5 * All rights reserved. 5 * All rights reserved.
@@ -68,7 +68,7 @@ static void pm8001_tag_clear(struct pm8001_hba_info *pm8001_ha, u32 tag)
68 clear_bit(tag, bitmap); 68 clear_bit(tag, bitmap);
69} 69}
70 70
71static void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag) 71void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
72{ 72{
73 pm8001_tag_clear(pm8001_ha, tag); 73 pm8001_tag_clear(pm8001_ha, tag);
74} 74}
@@ -212,10 +212,12 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
212 break; 212 break;
213 case PHY_FUNC_GET_EVENTS: 213 case PHY_FUNC_GET_EVENTS:
214 spin_lock_irqsave(&pm8001_ha->lock, flags); 214 spin_lock_irqsave(&pm8001_ha->lock, flags);
215 if (-1 == pm8001_bar4_shift(pm8001_ha, 215 if (pm8001_ha->chip_id == chip_8001) {
216 if (-1 == pm8001_bar4_shift(pm8001_ha,
216 (phy_id < 4) ? 0x30000 : 0x40000)) { 217 (phy_id < 4) ? 0x30000 : 0x40000)) {
217 spin_unlock_irqrestore(&pm8001_ha->lock, flags); 218 spin_unlock_irqrestore(&pm8001_ha->lock, flags);
218 return -EINVAL; 219 return -EINVAL;
220 }
219 } 221 }
220 { 222 {
221 struct sas_phy *phy = sas_phy->phy; 223 struct sas_phy *phy = sas_phy->phy;
@@ -228,7 +230,8 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
228 phy->loss_of_dword_sync_count = qp[3]; 230 phy->loss_of_dword_sync_count = qp[3];
229 phy->phy_reset_problem_count = qp[4]; 231 phy->phy_reset_problem_count = qp[4];
230 } 232 }
231 pm8001_bar4_shift(pm8001_ha, 0); 233 if (pm8001_ha->chip_id == chip_8001)
234 pm8001_bar4_shift(pm8001_ha, 0);
232 spin_unlock_irqrestore(&pm8001_ha->lock, flags); 235 spin_unlock_irqrestore(&pm8001_ha->lock, flags);
233 return 0; 236 return 0;
234 default: 237 default:
@@ -249,7 +252,9 @@ void pm8001_scan_start(struct Scsi_Host *shost)
249 struct pm8001_hba_info *pm8001_ha; 252 struct pm8001_hba_info *pm8001_ha;
250 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 253 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
251 pm8001_ha = sha->lldd_ha; 254 pm8001_ha = sha->lldd_ha;
252 PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha); 255 /* SAS_RE_INITIALIZATION not available in SPCv/ve */
256 if (pm8001_ha->chip_id == chip_8001)
257 PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha);
253 for (i = 0; i < pm8001_ha->chip->n_phy; ++i) 258 for (i = 0; i < pm8001_ha->chip->n_phy; ++i)
254 PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i); 259 PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i);
255} 260}
@@ -352,7 +357,7 @@ static int sas_find_local_port_id(struct domain_device *dev)
352 * @tmf: the task management IU 357 * @tmf: the task management IU
353 */ 358 */
354#define DEV_IS_GONE(pm8001_dev) \ 359#define DEV_IS_GONE(pm8001_dev) \
355 ((!pm8001_dev || (pm8001_dev->dev_type == NO_DEVICE))) 360 ((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED)))
356static int pm8001_task_exec(struct sas_task *task, const int num, 361static int pm8001_task_exec(struct sas_task *task, const int num,
357 gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf) 362 gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf)
358{ 363{
@@ -370,7 +375,7 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
370 struct task_status_struct *tsm = &t->task_status; 375 struct task_status_struct *tsm = &t->task_status;
371 tsm->resp = SAS_TASK_UNDELIVERED; 376 tsm->resp = SAS_TASK_UNDELIVERED;
372 tsm->stat = SAS_PHY_DOWN; 377 tsm->stat = SAS_PHY_DOWN;
373 if (dev->dev_type != SATA_DEV) 378 if (dev->dev_type != SAS_SATA_DEV)
374 t->task_done(t); 379 t->task_done(t);
375 return 0; 380 return 0;
376 } 381 }
@@ -548,7 +553,7 @@ struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha)
548{ 553{
549 u32 dev; 554 u32 dev;
550 for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) { 555 for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) {
551 if (pm8001_ha->devices[dev].dev_type == NO_DEVICE) { 556 if (pm8001_ha->devices[dev].dev_type == SAS_PHY_UNUSED) {
552 pm8001_ha->devices[dev].id = dev; 557 pm8001_ha->devices[dev].id = dev;
553 return &pm8001_ha->devices[dev]; 558 return &pm8001_ha->devices[dev];
554 } 559 }
@@ -560,13 +565,31 @@ struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha)
560 } 565 }
561 return NULL; 566 return NULL;
562} 567}
568/**
569 * pm8001_find_dev - find a matching pm8001_device
570 * @pm8001_ha: our hba card information
571 */
572struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
573 u32 device_id)
574{
575 u32 dev;
576 for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) {
577 if (pm8001_ha->devices[dev].device_id == device_id)
578 return &pm8001_ha->devices[dev];
579 }
580 if (dev == PM8001_MAX_DEVICES) {
581 PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("NO MATCHING "
582 "DEVICE FOUND !!!\n"));
583 }
584 return NULL;
585}
563 586
564static void pm8001_free_dev(struct pm8001_device *pm8001_dev) 587static void pm8001_free_dev(struct pm8001_device *pm8001_dev)
565{ 588{
566 u32 id = pm8001_dev->id; 589 u32 id = pm8001_dev->id;
567 memset(pm8001_dev, 0, sizeof(*pm8001_dev)); 590 memset(pm8001_dev, 0, sizeof(*pm8001_dev));
568 pm8001_dev->id = id; 591 pm8001_dev->id = id;
569 pm8001_dev->dev_type = NO_DEVICE; 592 pm8001_dev->dev_type = SAS_PHY_UNUSED;
570 pm8001_dev->device_id = PM8001_MAX_DEVICES; 593 pm8001_dev->device_id = PM8001_MAX_DEVICES;
571 pm8001_dev->sas_device = NULL; 594 pm8001_dev->sas_device = NULL;
572} 595}
@@ -624,7 +647,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
624 res = -1; 647 res = -1;
625 } 648 }
626 } else { 649 } else {
627 if (dev->dev_type == SATA_DEV) { 650 if (dev->dev_type == SAS_SATA_DEV) {
628 pm8001_device->attached_phy = 651 pm8001_device->attached_phy =
629 dev->rphy->identify.phy_identifier; 652 dev->rphy->identify.phy_identifier;
630 flag = 1; /* directly sata*/ 653 flag = 1; /* directly sata*/
@@ -634,7 +657,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
634 PM8001_CHIP_DISP->reg_dev_req(pm8001_ha, pm8001_device, flag); 657 PM8001_CHIP_DISP->reg_dev_req(pm8001_ha, pm8001_device, flag);
635 spin_unlock_irqrestore(&pm8001_ha->lock, flags); 658 spin_unlock_irqrestore(&pm8001_ha->lock, flags);
636 wait_for_completion(&completion); 659 wait_for_completion(&completion);
637 if (dev->dev_type == SAS_END_DEV) 660 if (dev->dev_type == SAS_END_DEVICE)
638 msleep(50); 661 msleep(50);
639 pm8001_ha->flags = PM8001F_RUN_TIME; 662 pm8001_ha->flags = PM8001F_RUN_TIME;
640 return 0; 663 return 0;
@@ -648,7 +671,7 @@ int pm8001_dev_found(struct domain_device *dev)
648 return pm8001_dev_found_notify(dev); 671 return pm8001_dev_found_notify(dev);
649} 672}
650 673
651static void pm8001_task_done(struct sas_task *task) 674void pm8001_task_done(struct sas_task *task)
652{ 675{
653 if (!del_timer(&task->slow_task->timer)) 676 if (!del_timer(&task->slow_task->timer))
654 return; 677 return;
@@ -904,7 +927,7 @@ void pm8001_open_reject_retry(
904 struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[i]; 927 struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[i];
905 928
906 pm8001_dev = ccb->device; 929 pm8001_dev = ccb->device;
907 if (!pm8001_dev || (pm8001_dev->dev_type == NO_DEVICE)) 930 if (!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED))
908 continue; 931 continue;
909 if (!device_to_close) { 932 if (!device_to_close) {
910 uintptr_t d = (uintptr_t)pm8001_dev 933 uintptr_t d = (uintptr_t)pm8001_dev
@@ -995,6 +1018,72 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
995 return rc; 1018 return rc;
996} 1019}
997 1020
1021/*
1022* This function handle the IT_NEXUS_XXX event or completion
1023* status code for SSP/SATA/SMP I/O request.
1024*/
1025int pm8001_I_T_nexus_event_handler(struct domain_device *dev)
1026{
1027 int rc = TMF_RESP_FUNC_FAILED;
1028 struct pm8001_device *pm8001_dev;
1029 struct pm8001_hba_info *pm8001_ha;
1030 struct sas_phy *phy;
1031 u32 device_id = 0;
1032
1033 if (!dev || !dev->lldd_dev)
1034 return -1;
1035
1036 pm8001_dev = dev->lldd_dev;
1037 device_id = pm8001_dev->device_id;
1038 pm8001_ha = pm8001_find_ha_by_dev(dev);
1039
1040 PM8001_EH_DBG(pm8001_ha,
1041 pm8001_printk("I_T_Nexus handler invoked !!"));
1042
1043 phy = sas_get_local_phy(dev);
1044
1045 if (dev_is_sata(dev)) {
1046 DECLARE_COMPLETION_ONSTACK(completion_setstate);
1047 if (scsi_is_sas_phy_local(phy)) {
1048 rc = 0;
1049 goto out;
1050 }
1051 /* send internal ssp/sata/smp abort command to FW */
1052 rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
1053 dev, 1, 0);
1054 msleep(100);
1055
1056 /* deregister the target device */
1057 pm8001_dev_gone_notify(dev);
1058 msleep(200);
1059
1060 /*send phy reset to hard reset target */
1061 rc = sas_phy_reset(phy, 1);
1062 msleep(2000);
1063 pm8001_dev->setds_completion = &completion_setstate;
1064
1065 wait_for_completion(&completion_setstate);
1066 } else {
1067 /* send internal ssp/sata/smp abort command to FW */
1068 rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
1069 dev, 1, 0);
1070 msleep(100);
1071
1072 /* deregister the target device */
1073 pm8001_dev_gone_notify(dev);
1074 msleep(200);
1075
1076 /*send phy reset to hard reset target */
1077 rc = sas_phy_reset(phy, 1);
1078 msleep(2000);
1079 }
1080 PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n",
1081 pm8001_dev->device_id, rc));
1082out:
1083 sas_put_local_phy(phy);
1084
1085 return rc;
1086}
998/* mandatory SAM-3, the task reset the specified LUN*/ 1087/* mandatory SAM-3, the task reset the specified LUN*/
999int pm8001_lu_reset(struct domain_device *dev, u8 *lun) 1088int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
1000{ 1089{