diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2011-09-15 15:08:05 +0200 | 
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2011-09-15 15:08:18 +0200 | 
| commit | e060c38434b2caa78efe7cedaff4191040b65a15 (patch) | |
| tree | 407361230bf6733f63d8e788e4b5e6566ee04818 /drivers/scsi/mvsas/mv_sas.c | |
| parent | 10e4ac572eeffe5317019bd7330b6058a400dfc2 (diff) | |
| parent | cc39c6a9bbdebfcf1a7dee64d83bf302bc38d941 (diff) | |
| download | olio-linux-3.10-e060c38434b2caa78efe7cedaff4191040b65a15.tar.xz olio-linux-3.10-e060c38434b2caa78efe7cedaff4191040b65a15.zip  | |
Merge branch 'master' into for-next
Fast-forward merge with Linus to be able to merge patches
based on more recent version of the tree.
Diffstat (limited to 'drivers/scsi/mvsas/mv_sas.c')
| -rw-r--r-- | drivers/scsi/mvsas/mv_sas.c | 422 | 
1 files changed, 163 insertions, 259 deletions
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 0ef27425c44..4958fefff36 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -38,7 +38,7 @@ static int mvs_find_tag(struct mvs_info *mvi, struct sas_task *task, u32 *tag)  void mvs_tag_clear(struct mvs_info *mvi, u32 tag)  { -	void *bitmap = &mvi->tags; +	void *bitmap = mvi->tags;  	clear_bit(tag, bitmap);  } @@ -49,14 +49,14 @@ void mvs_tag_free(struct mvs_info *mvi, u32 tag)  void mvs_tag_set(struct mvs_info *mvi, unsigned int tag)  { -	void *bitmap = &mvi->tags; +	void *bitmap = mvi->tags;  	set_bit(tag, bitmap);  }  inline int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out)  {  	unsigned int index, tag; -	void *bitmap = &mvi->tags; +	void *bitmap = mvi->tags;  	index = find_first_zero_bit(bitmap, mvi->tags_num);  	tag = index; @@ -74,126 +74,6 @@ void mvs_tag_init(struct mvs_info *mvi)  		mvs_tag_clear(mvi, i);  } -void mvs_hexdump(u32 size, u8 *data, u32 baseaddr) -{ -	u32 i; -	u32 run; -	u32 offset; - -	offset = 0; -	while (size) { -		printk(KERN_DEBUG"%08X : ", baseaddr + offset); -		if (size >= 16) -			run = 16; -		else -			run = size; -		size -= run; -		for (i = 0; i < 16; i++) { -			if (i < run) -				printk(KERN_DEBUG"%02X ", (u32)data[i]); -			else -				printk(KERN_DEBUG"   "); -		} -		printk(KERN_DEBUG": "); -		for (i = 0; i < run; i++) -			printk(KERN_DEBUG"%c", -				isalnum(data[i]) ? data[i] : '.'); -		printk(KERN_DEBUG"\n"); -		data = &data[16]; -		offset += run; -	} -	printk(KERN_DEBUG"\n"); -} - -#if (_MV_DUMP > 1) -static void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag, -				   enum sas_protocol proto) -{ -	u32 offset; -	struct mvs_slot_info *slot = &mvi->slot_info[tag]; - -	offset = slot->cmd_size + MVS_OAF_SZ + -	    MVS_CHIP_DISP->prd_size() * slot->n_elem; -	dev_printk(KERN_DEBUG, mvi->dev, "+---->Status buffer[%d] :\n", -			tag); -	mvs_hexdump(32, (u8 *) slot->response, -		    (u32) slot->buf_dma + offset); -} -#endif - -static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag, -				enum sas_protocol proto) -{ -#if (_MV_DUMP > 1) -	u32 sz, w_ptr; -	u64 addr; -	struct mvs_slot_info *slot = &mvi->slot_info[tag]; - -	/*Delivery Queue */ -	sz = MVS_CHIP_SLOT_SZ; -	w_ptr = slot->tx; -	addr = mvi->tx_dma; -	dev_printk(KERN_DEBUG, mvi->dev, -		"Delivery Queue Size=%04d , WRT_PTR=%04X\n", sz, w_ptr); -	dev_printk(KERN_DEBUG, mvi->dev, -		"Delivery Queue Base Address=0x%llX (PA)" -		"(tx_dma=0x%llX), Entry=%04d\n", -		addr, (unsigned long long)mvi->tx_dma, w_ptr); -	mvs_hexdump(sizeof(u32), (u8 *)(&mvi->tx[mvi->tx_prod]), -			(u32) mvi->tx_dma + sizeof(u32) * w_ptr); -	/*Command List */ -	addr = mvi->slot_dma; -	dev_printk(KERN_DEBUG, mvi->dev, -		"Command List Base Address=0x%llX (PA)" -		"(slot_dma=0x%llX), Header=%03d\n", -		addr, (unsigned long long)slot->buf_dma, tag); -	dev_printk(KERN_DEBUG, mvi->dev, "Command Header[%03d]:\n", tag); -	/*mvs_cmd_hdr */ -	mvs_hexdump(sizeof(struct mvs_cmd_hdr), (u8 *)(&mvi->slot[tag]), -		(u32) mvi->slot_dma + tag * sizeof(struct mvs_cmd_hdr)); -	/*1.command table area */ -	dev_printk(KERN_DEBUG, mvi->dev, "+---->Command Table :\n"); -	mvs_hexdump(slot->cmd_size, (u8 *) slot->buf, (u32) slot->buf_dma); -	/*2.open address frame area */ -	dev_printk(KERN_DEBUG, mvi->dev, "+---->Open Address Frame :\n"); -	mvs_hexdump(MVS_OAF_SZ, (u8 *) slot->buf + slot->cmd_size, -				(u32) slot->buf_dma + slot->cmd_size); -	/*3.status buffer */ -	mvs_hba_sb_dump(mvi, tag, proto); -	/*4.PRD table */ -	dev_printk(KERN_DEBUG, mvi->dev, "+---->PRD table :\n"); -	mvs_hexdump(MVS_CHIP_DISP->prd_size() * slot->n_elem, -		(u8 *) slot->buf + slot->cmd_size + MVS_OAF_SZ, -		(u32) slot->buf_dma + slot->cmd_size + MVS_OAF_SZ); -#endif -} - -static void mvs_hba_cq_dump(struct mvs_info *mvi) -{ -#if (_MV_DUMP > 2) -	u64 addr; -	void __iomem *regs = mvi->regs; -	u32 entry = mvi->rx_cons + 1; -	u32 rx_desc = le32_to_cpu(mvi->rx[entry]); - -	/*Completion Queue */ -	addr = mr32(RX_HI) << 16 << 16 | mr32(RX_LO); -	dev_printk(KERN_DEBUG, mvi->dev, "Completion Task = 0x%p\n", -		   mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task); -	dev_printk(KERN_DEBUG, mvi->dev, -		"Completion List Base Address=0x%llX (PA), " -		"CQ_Entry=%04d, CQ_WP=0x%08X\n", -		addr, entry - 1, mvi->rx[0]); -	mvs_hexdump(sizeof(u32), (u8 *)(&rx_desc), -		    mvi->rx_dma + sizeof(u32) * entry); -#endif -} - -void mvs_get_sas_addr(void *buf, u32 buflen) -{ -	/*memcpy(buf, "\x50\x05\x04\x30\x11\xab\x64\x40", 8);*/ -} -  struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev)  {  	unsigned long i = 0, j = 0, hi = 0; @@ -222,7 +102,6 @@ struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev)  } -/* FIXME */  int mvs_find_dev_phyno(struct domain_device *dev, int *phyno)  {  	unsigned long i = 0, j = 0, n = 0, num = 0; @@ -253,6 +132,20 @@ int mvs_find_dev_phyno(struct domain_device *dev, int *phyno)  	return num;  } +struct mvs_device *mvs_find_dev_by_reg_set(struct mvs_info *mvi, +						u8 reg_set) +{ +	u32 dev_no; +	for (dev_no = 0; dev_no < MVS_MAX_DEVICES; dev_no++) { +		if (mvi->devices[dev_no].taskfileset == MVS_ID_NOT_MAPPED) +			continue; + +		if (mvi->devices[dev_no].taskfileset == reg_set) +			return &mvi->devices[dev_no]; +	} +	return NULL; +} +  static inline void mvs_free_reg_set(struct mvs_info *mvi,  				struct mvs_device *dev)  { @@ -283,7 +176,6 @@ void mvs_phys_reset(struct mvs_info *mvi, u32 phy_mask, int hard)  	}  } -/* FIXME: locking? */  int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,  			void *funcdata)  { @@ -309,12 +201,12 @@ int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,  		tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id);  		if (tmp & PHY_RST_HARD)  			break; -		MVS_CHIP_DISP->phy_reset(mvi, phy_id, 1); +		MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_HARD_RESET);  		break;  	case PHY_FUNC_LINK_RESET:  		MVS_CHIP_DISP->phy_enable(mvi, phy_id); -		MVS_CHIP_DISP->phy_reset(mvi, phy_id, 0); +		MVS_CHIP_DISP->phy_reset(mvi, phy_id, MVS_SOFT_RESET);  		break;  	case PHY_FUNC_DISABLE: @@ -406,14 +298,10 @@ int mvs_slave_configure(struct scsi_device *sdev)  	if (ret)  		return ret; -	if (dev_is_sata(dev)) { -		/* may set PIO mode */ -	#if MV_DISABLE_NCQ -		struct ata_port *ap = dev->sata_dev.ap; -		struct ata_device *adev = ap->link.device; -		adev->flags |= ATA_DFLAG_NCQ_OFF; -		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1); -	#endif +	if (!dev_is_sata(dev)) { +		sas_change_queue_depth(sdev, +			MVS_QUEUE_SIZE, +			SCSI_QDEPTH_DEFAULT);  	}  	return 0;  } @@ -424,6 +312,7 @@ void mvs_scan_start(struct Scsi_Host *shost)  	unsigned short core_nr;  	struct mvs_info *mvi;  	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); +	struct mvs_prv_info *mvs_prv = sha->lldd_ha;  	core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; @@ -432,15 +321,17 @@ void mvs_scan_start(struct Scsi_Host *shost)  		for (i = 0; i < mvi->chip->n_phy; ++i)  			mvs_bytes_dmaed(mvi, i);  	} +	mvs_prv->scan_finished = 1;  }  int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time)  { -	/* give the phy enabling interrupt event time to come in (1s -	 * is empirically about all it takes) */ -	if (time < HZ) +	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); +	struct mvs_prv_info *mvs_prv = sha->lldd_ha; + +	if (mvs_prv->scan_finished == 0)  		return 0; -	/* Wait for discovery to finish */ +  	scsi_flush_work(shost);  	return 1;  } @@ -461,10 +352,7 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,  	void *buf_prd;  	struct mvs_slot_info *slot = &mvi->slot_info[tag];  	u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); -#if _MV_DUMP -	u8 *buf_cmd; -	void *from; -#endif +  	/*  	 * DMA-map SMP request, response buffers  	 */ @@ -496,15 +384,7 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,  	buf_tmp = slot->buf;  	buf_tmp_dma = slot->buf_dma; -#if _MV_DUMP -	buf_cmd = buf_tmp; -	hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); -	buf_tmp += req_len; -	buf_tmp_dma += req_len; -	slot->cmd_size = req_len; -#else  	hdr->cmd_tbl = cpu_to_le64(sg_dma_address(sg_req)); -#endif  	/* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */  	buf_oaf = buf_tmp; @@ -553,12 +433,6 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,  	/* fill in PRD (scatter/gather) table, if any */  	MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd); -#if _MV_DUMP -	/* copy cmd table */ -	from = kmap_atomic(sg_page(sg_req), KM_IRQ0); -	memcpy(buf_cmd, from + sg_req->offset, req_len); -	kunmap_atomic(from, KM_IRQ0); -#endif  	return 0;  err_out_2: @@ -616,14 +490,11 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,  		(mvi_dev->taskfileset << TXQ_SRS_SHIFT);  	mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q); -#ifndef DISABLE_HOTPLUG_DMA_FIX  	if (task->data_dir == DMA_FROM_DEVICE)  		flags = (MVS_CHIP_DISP->prd_count() << MCH_PRD_LEN_SHIFT);  	else  		flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); -#else -	flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); -#endif +  	if (task->ata_task.use_ncq)  		flags |= MCH_FPDMA;  	if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) { @@ -631,11 +502,8 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,  			flags |= MCH_ATAPI;  	} -	/* FIXME: fill in port multiplier number */ -  	hdr->flags = cpu_to_le32(flags); -	/* FIXME: the low order order 5 bits for the TAG if enable NCQ */  	if (task->ata_task.use_ncq && mvs_get_ncq_tag(task, &hdr_tag))  		task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);  	else @@ -657,9 +525,6 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,  	buf_tmp += MVS_ATA_CMD_SZ;  	buf_tmp_dma += MVS_ATA_CMD_SZ; -#if _MV_DUMP -	slot->cmd_size = MVS_ATA_CMD_SZ; -#endif  	/* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */  	/* used for STP.  unused for SATA? */ @@ -682,9 +547,6 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,  	buf_tmp_dma += i;  	/* region 4: status buffer (larger the PRD, smaller this buf) ****** */ -	/* FIXME: probably unused, for SATA.  kept here just in case -	 * we get a STP/SATA error information record -	 */  	slot->response = buf_tmp;  	hdr->status_buf = cpu_to_le64(buf_tmp_dma);  	if (mvi->flags & MVF_FLAG_SOC) @@ -715,11 +577,11 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,  	/* fill in PRD (scatter/gather) table, if any */  	MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd); -#ifndef DISABLE_HOTPLUG_DMA_FIX +  	if (task->data_dir == DMA_FROM_DEVICE) -		MVS_CHIP_DISP->dma_fix(mvi->bulk_buffer_dma, +		MVS_CHIP_DISP->dma_fix(mvi, sas_port->phy_mask,  				TRASH_BUCKET_SIZE, tei->n_elem, buf_prd); -#endif +  	return 0;  } @@ -761,6 +623,9 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,  	}  	if (is_tmf)  		flags |= (MCH_SSP_FR_TASK << MCH_SSP_FR_TYPE_SHIFT); +	else +		flags |= (MCH_SSP_FR_CMD << MCH_SSP_FR_TYPE_SHIFT); +  	hdr->flags = cpu_to_le32(flags | (tei->n_elem << MCH_PRD_LEN_SHIFT));  	hdr->tags = cpu_to_le32(tag);  	hdr->data_len = cpu_to_le32(task->total_xfer_len); @@ -777,9 +642,6 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,  	buf_tmp += MVS_SSP_CMD_SZ;  	buf_tmp_dma += MVS_SSP_CMD_SZ; -#if _MV_DUMP -	slot->cmd_size = MVS_SSP_CMD_SZ; -#endif  	/* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */  	buf_oaf = buf_tmp; @@ -986,7 +848,6 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf  	task->task_state_flags |= SAS_TASK_AT_INITIATOR;  	spin_unlock(&task->task_state_lock); -	mvs_hba_memory_dump(mvi, tag, task->task_proto);  	mvi_dev->running_req++;  	++(*pass);  	mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); @@ -1189,9 +1050,9 @@ static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,  	mvs_slot_free(mvi, slot_idx);  } -static void mvs_update_wideport(struct mvs_info *mvi, int i) +static void mvs_update_wideport(struct mvs_info *mvi, int phy_no)  { -	struct mvs_phy *phy = &mvi->phy[i]; +	struct mvs_phy *phy = &mvi->phy[phy_no];  	struct mvs_port *port = phy->port;  	int j, no; @@ -1246,18 +1107,17 @@ static void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf)  		return NULL;  	MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG3); -	s[3] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); +	s[3] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));  	MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG2); -	s[2] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); +	s[2] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));  	MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG1); -	s[1] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); +	s[1] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));  	MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG0); -	s[0] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); +	s[0] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i)); -	/* Workaround: take some ATAPI devices for ATA */  	if (((s[1] & 0x00FFFFFF) == 0x00EB1401) && (*(u8 *)&s[3] == 0x01))  		s[1] = 0x00EB1401 | (*((u8 *)&s[1] + 3) & 0x10); @@ -1269,6 +1129,13 @@ static u32 mvs_is_sig_fis_received(u32 irq_status)  	return irq_status & PHYEV_SIG_FIS;  } +static void mvs_sig_remove_timer(struct mvs_phy *phy) +{ +	if (phy->timer.function) +		del_timer(&phy->timer); +	phy->timer.function = NULL; +} +  void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)  {  	struct mvs_phy *phy = &mvi->phy[i]; @@ -1291,6 +1158,7 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)  		if (phy->phy_type & PORT_TYPE_SATA) {  			phy->identify.target_port_protocols = SAS_PROTOCOL_STP;  			if (mvs_is_sig_fis_received(phy->irq_status)) { +				mvs_sig_remove_timer(phy);  				phy->phy_attached = 1;  				phy->att_dev_sas_addr =  					i + mvi->id * mvi->chip->n_phy; @@ -1308,7 +1176,6 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)  						tmp | PHYEV_SIG_FIS);  				phy->phy_attached = 0;  				phy->phy_type &= ~PORT_TYPE_SATA; -				MVS_CHIP_DISP->phy_reset(mvi, i, 0);  				goto out_done;  			}  		}	else if (phy->phy_type & PORT_TYPE_SAS @@ -1334,9 +1201,9 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)  		if (MVS_CHIP_DISP->phy_work_around)  			MVS_CHIP_DISP->phy_work_around(mvi, i);  	} -	mv_dprintk("port %d attach dev info is %x\n", +	mv_dprintk("phy %d attach dev info is %x\n",  		i + mvi->id * mvi->chip->n_phy, phy->att_dev_info); -	mv_dprintk("port %d attach sas addr is %llx\n", +	mv_dprintk("phy %d attach sas addr is %llx\n",  		i + mvi->id * mvi->chip->n_phy, phy->att_dev_sas_addr);  out_done:  	if (get_st) @@ -1361,10 +1228,10 @@ static void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock)  	}  	hi = i/((struct mvs_prv_info *)sas_ha->lldd_ha)->n_phy;  	mvi = ((struct mvs_prv_info *)sas_ha->lldd_ha)->mvi[hi]; -	if (sas_port->id >= mvi->chip->n_phy) -		port = &mvi->port[sas_port->id - mvi->chip->n_phy]; +	if (i >= mvi->chip->n_phy) +		port = &mvi->port[i - mvi->chip->n_phy];  	else -		port = &mvi->port[sas_port->id]; +		port = &mvi->port[i];  	if (lock)  		spin_lock_irqsave(&mvi->lock, flags);  	port->port_attached = 1; @@ -1393,7 +1260,7 @@ static void mvs_port_notify_deformed(struct asd_sas_phy *sas_phy, int lock)  			return;  	}  	list_for_each_entry(dev, &port->dev_list, dev_list_node) -		mvs_do_release_task(phy->mvi, phy_no, NULL); +		mvs_do_release_task(phy->mvi, phy_no, dev);  } @@ -1457,6 +1324,7 @@ int mvs_dev_found_notify(struct domain_device *dev, int lock)  	mvi_device->dev_status = MVS_DEV_NORMAL;  	mvi_device->dev_type = dev->dev_type;  	mvi_device->mvi_info = mvi; +	mvi_device->sas_device = dev;  	if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) {  		int phy_id;  		u8 phy_num = parent_dev->ex_dev.num_phys; @@ -1508,6 +1376,7 @@ void mvs_dev_gone_notify(struct domain_device *dev)  		mv_dprintk("found dev has gone.\n");  	}  	dev->lldd_dev = NULL; +	mvi_dev->sas_device = NULL;  	spin_unlock_irqrestore(&mvi->lock, flags);  } @@ -1555,7 +1424,6 @@ static void mvs_tmf_timedout(unsigned long data)  	complete(&task->completion);  } -/* XXX */  #define MVS_TASK_TIMEOUT 20  static int mvs_exec_internal_tmf_task(struct domain_device *dev,  			void *parameter, u32 para_len, struct mvs_tmf_task *tmf) @@ -1588,7 +1456,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,  		}  		wait_for_completion(&task->completion); -		res = -TMF_RESP_FUNC_FAILED; +		res = TMF_RESP_FUNC_FAILED;  		/* Even TMF timed out, return direct. */  		if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {  			if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { @@ -1638,11 +1506,10 @@ static int mvs_debug_issue_ssp_tmf(struct domain_device *dev,  				u8 *lun, struct mvs_tmf_task *tmf)  {  	struct sas_ssp_task ssp_task; -	DECLARE_COMPLETION_ONSTACK(completion);  	if (!(dev->tproto & SAS_PROTOCOL_SSP))  		return TMF_RESP_FUNC_ESUPP; -	strncpy((u8 *)&ssp_task.LUN, lun, 8); +	memcpy(ssp_task.LUN, lun, 8);  	return mvs_exec_internal_tmf_task(dev, &ssp_task,  				sizeof(ssp_task), tmf); @@ -1666,7 +1533,7 @@ static int mvs_debug_I_T_nexus_reset(struct domain_device *dev)  int mvs_lu_reset(struct domain_device *dev, u8 *lun)  {  	unsigned long flags; -	int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED; +	int rc = TMF_RESP_FUNC_FAILED;  	struct mvs_tmf_task tmf_task;  	struct mvs_device * mvi_dev = dev->lldd_dev;  	struct mvs_info *mvi = mvi_dev->mvi_info; @@ -1675,10 +1542,8 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun)  	mvi_dev->dev_status = MVS_DEV_EH;  	rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task);  	if (rc == TMF_RESP_FUNC_COMPLETE) { -		num = mvs_find_dev_phyno(dev, phyno);  		spin_lock_irqsave(&mvi->lock, flags); -		for (i = 0; i < num; i++) -			mvs_release_task(mvi, dev); +		mvs_release_task(mvi, dev);  		spin_unlock_irqrestore(&mvi->lock, flags);  	}  	/* If failed, fall-through I_T_Nexus reset */ @@ -1696,11 +1561,12 @@ int mvs_I_T_nexus_reset(struct domain_device *dev)  	if (mvi_dev->dev_status != MVS_DEV_EH)  		return TMF_RESP_FUNC_COMPLETE; +	else +		mvi_dev->dev_status = MVS_DEV_NORMAL;  	rc = mvs_debug_I_T_nexus_reset(dev);  	mv_printk("%s for device[%x]:rc= %d\n",  		__func__, mvi_dev->device_id, rc); -	/* housekeeper */  	spin_lock_irqsave(&mvi->lock, flags);  	mvs_release_task(mvi, dev);  	spin_unlock_irqrestore(&mvi->lock, flags); @@ -1739,9 +1605,6 @@ int mvs_query_task(struct sas_task *task)  		case TMF_RESP_FUNC_FAILED:  		case TMF_RESP_FUNC_COMPLETE:  			break; -		default: -			rc = TMF_RESP_FUNC_COMPLETE; -			break;  		}  	}  	mv_printk("%s:rc= %d\n", __func__, rc); @@ -1761,8 +1624,8 @@ int mvs_abort_task(struct sas_task *task)  	u32 tag;  	if (!mvi_dev) { -		mv_printk("%s:%d TMF_RESP_FUNC_FAILED\n", __func__, __LINE__); -		rc = TMF_RESP_FUNC_FAILED; +		mv_printk("Device has removed\n"); +		return TMF_RESP_FUNC_FAILED;  	}  	mvi = mvi_dev->mvi_info; @@ -1807,25 +1670,17 @@ int mvs_abort_task(struct sas_task *task)  	} else if (task->task_proto & SAS_PROTOCOL_SATA ||  		task->task_proto & SAS_PROTOCOL_STP) { -		/* to do free register_set */  		if (SATA_DEV == dev->dev_type) {  			struct mvs_slot_info *slot = task->lldd_task; -			struct task_status_struct *tstat;  			u32 slot_idx = (u32)(slot - mvi->slot_info); -			tstat = &task->task_status; -			mv_dprintk(KERN_DEBUG "mv_abort_task() mvi=%p task=%p " +			mv_dprintk("mvs_abort_task() mvi=%p task=%p "  				   "slot=%p slot_idx=x%x\n",  				   mvi, task, slot, slot_idx); -			tstat->stat = SAS_ABORTED_TASK; -			if (mvi_dev && mvi_dev->running_req) -				mvi_dev->running_req--; -			if (sas_protocol_ata(task->task_proto)) -				mvs_free_reg_set(mvi, mvi_dev); +			mvs_tmf_timedout((unsigned long)task);  			mvs_slot_task_free(mvi, task, slot, slot_idx); -			return -1; +			rc = TMF_RESP_FUNC_COMPLETE; +			goto out;  		} -	} else { -		/* SMP */  	}  out: @@ -1891,12 +1746,63 @@ static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task,  	return stat;  } +void mvs_set_sense(u8 *buffer, int len, int d_sense, +		int key, int asc, int ascq) +{ +	memset(buffer, 0, len); + +	if (d_sense) { +		/* Descriptor format */ +		if (len < 4) { +			mv_printk("Length %d of sense buffer too small to " +				"fit sense %x:%x:%x", len, key, asc, ascq); +		} + +		buffer[0] = 0x72;		/* Response Code	*/ +		if (len > 1) +			buffer[1] = key;	/* Sense Key */ +		if (len > 2) +			buffer[2] = asc;	/* ASC	*/ +		if (len > 3) +			buffer[3] = ascq;	/* ASCQ	*/ +	} else { +		if (len < 14) { +			mv_printk("Length %d of sense buffer too small to " +				"fit sense %x:%x:%x", len, key, asc, ascq); +		} + +		buffer[0] = 0x70;		/* Response Code	*/ +		if (len > 2) +			buffer[2] = key;	/* Sense Key */ +		if (len > 7) +			buffer[7] = 0x0a;	/* Additional Sense Length */ +		if (len > 12) +			buffer[12] = asc;	/* ASC */ +		if (len > 13) +			buffer[13] = ascq; /* ASCQ */ +	} + +	return; +} + +void mvs_fill_ssp_resp_iu(struct ssp_response_iu *iu, +				u8 key, u8 asc, u8 asc_q) +{ +	iu->datapres = 2; +	iu->response_data_len = 0; +	iu->sense_data_len = 17; +	iu->status = 02; +	mvs_set_sense(iu->sense_data, 17, 0, +			key, asc, asc_q); +} +  static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,  			 u32 slot_idx)  {  	struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];  	int stat; -	u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response)); +	u32 err_dw0 = le32_to_cpu(*(u32 *)slot->response); +	u32 err_dw1 = le32_to_cpu(*((u32 *)slot->response + 1));  	u32 tfs = 0;  	enum mvs_port_type type = PORT_TYPE_SAS; @@ -1908,8 +1814,19 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,  	stat = SAM_STAT_CHECK_CONDITION;  	switch (task->task_proto) {  	case SAS_PROTOCOL_SSP: +	{  		stat = SAS_ABORTED_TASK; +		if ((err_dw0 & NO_DEST) || err_dw1 & bit(31)) { +			struct ssp_response_iu *iu = slot->response + +				sizeof(struct mvs_err_info); +			mvs_fill_ssp_resp_iu(iu, NOT_READY, 0x04, 01); +			sas_ssp_task_response(mvi->dev, task, iu); +			stat = SAM_STAT_CHECK_CONDITION; +		} +		if (err_dw1 & bit(31)) +			mv_printk("reuse same slot, retry command.\n");  		break; +	}  	case SAS_PROTOCOL_SMP:  		stat = SAM_STAT_CHECK_CONDITION;  		break; @@ -1918,10 +1835,8 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,  	case SAS_PROTOCOL_STP:  	case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:  	{ -		if (err_dw0 == 0x80400002) -			mv_printk("find reserved error, why?\n"); -  		task->ata_task.use_ncq = 0; +		stat = SAS_PROTO_RESPONSE;  		mvs_sata_done(mvi, task, slot_idx, err_dw0);  	}  		break; @@ -1945,8 +1860,6 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)  	void *to;  	enum exec_status sts; -	if (mvi->exp_req) -		mvi->exp_req--;  	if (unlikely(!task || !task->lldd_task || !task->dev))  		return -1; @@ -1954,8 +1867,6 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)  	dev = task->dev;  	mvi_dev = dev->lldd_dev; -	mvs_hba_cq_dump(mvi); -  	spin_lock(&task->task_state_lock);  	task->task_state_flags &=  		~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR); @@ -1978,6 +1889,7 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)  		return -1;  	} +	/* when no device attaching, go ahead and complete by error handling*/  	if (unlikely(!mvi_dev || flags)) {  		if (!mvi_dev)  			mv_dprintk("port has not device.\n"); @@ -1987,6 +1899,9 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)  	/* error info record present */  	if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) { +		mv_dprintk("port %d slot %d rx_desc %X has error info" +			"%016llX.\n", slot->port->sas_port.id, slot_idx, +			 rx_desc, (u64)(*(u64 *)slot->response));  		tstat->stat = mvs_slot_err(mvi, task, slot_idx);  		tstat->resp = SAS_TASK_COMPLETE;  		goto out; @@ -2048,8 +1963,7 @@ out:  	spin_unlock(&mvi->lock);  	if (task->task_done)  		task->task_done(task); -	else -		mv_dprintk("why has not task_done.\n"); +  	spin_lock(&mvi->lock);  	return sts; @@ -2092,7 +2006,6 @@ void mvs_release_task(struct mvs_info *mvi,  		      struct domain_device *dev)  {  	int i, phyno[WIDE_PORT_MAX_PHY], num; -	/* housekeeper */  	num = mvs_find_dev_phyno(dev, phyno);  	for (i = 0; i < num; i++)  		mvs_do_release_task(mvi, phyno[i], dev); @@ -2111,13 +2024,13 @@ static void mvs_work_queue(struct work_struct *work)  	struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q);  	struct mvs_info *mvi = mwq->mvi;  	unsigned long flags; +	u32 phy_no = (unsigned long) mwq->data; +	struct sas_ha_struct *sas_ha = mvi->sas; +	struct mvs_phy *phy = &mvi->phy[phy_no]; +	struct asd_sas_phy *sas_phy = &phy->sas_phy;  	spin_lock_irqsave(&mvi->lock, flags);  	if (mwq->handler & PHY_PLUG_EVENT) { -		u32 phy_no = (unsigned long) mwq->data; -		struct sas_ha_struct *sas_ha = mvi->sas; -		struct mvs_phy *phy = &mvi->phy[phy_no]; -		struct asd_sas_phy *sas_phy = &phy->sas_phy;  		if (phy->phy_event & PHY_PLUG_OUT) {  			u32 tmp; @@ -2139,6 +2052,11 @@ static void mvs_work_queue(struct work_struct *work)  				mv_dprintk("phy%d Attached Device\n", phy_no);  			}  		} +	} else if (mwq->handler & EXP_BRCT_CHG) { +		phy->phy_event &= ~EXP_BRCT_CHG; +		sas_ha->notify_port_event(sas_phy, +				PORTE_BROADCAST_RCVD); +		mv_dprintk("phy%d Got Broadcast Change\n", phy_no);  	}  	list_del(&mwq->entry);  	spin_unlock_irqrestore(&mvi->lock, flags); @@ -2174,29 +2092,21 @@ static void mvs_sig_time_out(unsigned long tphy)  		if (&mvi->phy[phy_no] == phy) {  			mv_dprintk("Get signature time out, reset phy %d\n",  				phy_no+mvi->id*mvi->chip->n_phy); -			MVS_CHIP_DISP->phy_reset(mvi, phy_no, 1); +			MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_HARD_RESET);  		}  	}  } -static void mvs_sig_remove_timer(struct mvs_phy *phy) -{ -	if (phy->timer.function) -		del_timer(&phy->timer); -	phy->timer.function = NULL; -} -  void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)  {  	u32 tmp; -	struct sas_ha_struct *sas_ha = mvi->sas;  	struct mvs_phy *phy = &mvi->phy[phy_no]; -	struct asd_sas_phy *sas_phy = &phy->sas_phy;  	phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no); -	mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy, +	MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status); +	mv_dprintk("phy %d ctrl sts=0x%08X.\n", phy_no+mvi->id*mvi->chip->n_phy,  		MVS_CHIP_DISP->read_phy_ctl(mvi, phy_no)); -	mv_dprintk("Port %d irq sts = 0x%X\n", phy_no+mvi->id*mvi->chip->n_phy, +	mv_dprintk("phy %d irq sts = 0x%08X\n", phy_no+mvi->id*mvi->chip->n_phy,  		phy->irq_status);  	/* @@ -2205,11 +2115,12 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)  	*/  	if (phy->irq_status & PHYEV_DCDR_ERR) { -		mv_dprintk("port %d STP decoding error.\n", +		mv_dprintk("phy %d STP decoding error.\n",  		phy_no + mvi->id*mvi->chip->n_phy);  	}  	if (phy->irq_status & PHYEV_POOF) { +		mdelay(500);  		if (!(phy->phy_event & PHY_PLUG_OUT)) {  			int dev_sata = phy->phy_type & PORT_TYPE_SATA;  			int ready; @@ -2220,17 +2131,13 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)  				(void *)(unsigned long)phy_no,  				PHY_PLUG_EVENT);  			ready = mvs_is_phy_ready(mvi, phy_no); -			if (!ready) -				mv_dprintk("phy%d Unplug Notice\n", -					phy_no + -					mvi->id * mvi->chip->n_phy);  			if (ready || dev_sata) {  				if (MVS_CHIP_DISP->stp_reset)  					MVS_CHIP_DISP->stp_reset(mvi,  							phy_no);  				else  					MVS_CHIP_DISP->phy_reset(mvi, -							phy_no, 0); +							phy_no, MVS_SOFT_RESET);  				return;  			}  		} @@ -2243,13 +2150,12 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)  		if (phy->timer.function == NULL) {  			phy->timer.data = (unsigned long)phy;  			phy->timer.function = mvs_sig_time_out; -			phy->timer.expires = jiffies + 10*HZ; +			phy->timer.expires = jiffies + 5*HZ;  			add_timer(&phy->timer);  		}  	}  	if (phy->irq_status & (PHYEV_SIG_FIS | PHYEV_ID_DONE)) {  		phy->phy_status = mvs_is_phy_ready(mvi, phy_no); -		mvs_sig_remove_timer(phy);  		mv_dprintk("notify plug in on phy[%d]\n", phy_no);  		if (phy->phy_status) {  			mdelay(10); @@ -2263,14 +2169,14 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)  			}  			mvs_update_phyinfo(mvi, phy_no, 0);  			if (phy->phy_type & PORT_TYPE_SAS) { -				MVS_CHIP_DISP->phy_reset(mvi, phy_no, 2); +				MVS_CHIP_DISP->phy_reset(mvi, phy_no, MVS_PHY_TUNE);  				mdelay(10);  			}  			mvs_bytes_dmaed(mvi, phy_no);  			/* whether driver is going to handle hot plug */  			if (phy->phy_event & PHY_PLUG_OUT) { -				mvs_port_notify_formed(sas_phy, 0); +				mvs_port_notify_formed(&phy->sas_phy, 0);  				phy->phy_event &= ~PHY_PLUG_OUT;  			}  		} else { @@ -2278,13 +2184,11 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)  				phy_no + mvi->id*mvi->chip->n_phy);  		}  	} else if (phy->irq_status & PHYEV_BROAD_CH) { -		mv_dprintk("port %d broadcast change.\n", +		mv_dprintk("phy %d broadcast change.\n",  			phy_no + mvi->id*mvi->chip->n_phy); -		/* exception for Samsung disk drive*/ -		mdelay(1000); -		sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); +		mvs_handle_event(mvi, (void *)(unsigned long)phy_no, +				EXP_BRCT_CHG);  	} -	MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status);  }  int mvs_int_rx(struct mvs_info *mvi, bool self_clear)  |