⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sbp2.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	return 0;}/* * This function is called to delete a pool of command orbs. */static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id){	struct hpsb_host *host = scsi_id->hi->host;	struct list_head *lh, *next;	struct sbp2_command_info *command;	unsigned long flags;	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);	if (!list_empty(&scsi_id->sbp2_command_orb_completed)) {		list_for_each_safe(lh, next, &scsi_id->sbp2_command_orb_completed) {			command = list_entry(lh, struct sbp2_command_info, list);			/* Release our generic DMA's */			pci_unmap_single(host->pdev, command->command_orb_dma,					 sizeof(struct sbp2_command_orb),					 PCI_DMA_BIDIRECTIONAL);			SBP2_DMA_FREE("single command orb DMA");			pci_unmap_single(host->pdev, command->sge_dma,					 sizeof(command->scatter_gather_element),					 PCI_DMA_BIDIRECTIONAL);			SBP2_DMA_FREE("scatter_gather_element");			kfree(command);		}	}	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	return;}/* * This function finds the sbp2_command for a given outstanding command * orb.Only looks at the inuse list. */static struct sbp2_command_info *sbp2util_find_command_for_orb(		struct scsi_id_instance_data *scsi_id, dma_addr_t orb){	struct sbp2_command_info *command;	unsigned long flags;	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {			if (command->command_orb_dma == orb) {				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);				return (command);			}		}	}	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	SBP2_ORB_DEBUG("could not match command orb %x", (unsigned int)orb);	return(NULL);}/* * This function finds the sbp2_command for a given outstanding SCpnt. * Only looks at the inuse list. */static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt){	struct sbp2_command_info *command;	unsigned long flags;	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {			if (command->Current_SCpnt == SCpnt) {				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);				return (command);			}		}	}	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	return(NULL);}/* * This function allocates a command orb used to send a scsi command. */static struct sbp2_command_info *sbp2util_allocate_command_orb(		struct scsi_id_instance_data *scsi_id,		Scsi_Cmnd *Current_SCpnt,		void (*Current_done)(Scsi_Cmnd *)){	struct list_head *lh;	struct sbp2_command_info *command = NULL;	unsigned long flags;	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);	if (!list_empty(&scsi_id->sbp2_command_orb_completed)) {		lh = scsi_id->sbp2_command_orb_completed.next;		list_del(lh);		command = list_entry(lh, struct sbp2_command_info, list);		command->Current_done = Current_done;		command->Current_SCpnt = Current_SCpnt;		list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse);	} else {		SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");	}	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	return (command);}/* Free our DMA's */static void sbp2util_free_command_dma(struct sbp2_command_info *command){	struct scsi_id_instance_data *scsi_id =		(struct scsi_id_instance_data *)command->Current_SCpnt->device->host->hostdata[0];	struct hpsb_host *host;	if (!scsi_id) {		printk(KERN_ERR "%s: scsi_id == NULL\n", __FUNCTION__);		return;	}	host = scsi_id->ud->ne->host;	if (command->cmd_dma) {		if (command->dma_type == CMD_DMA_SINGLE) {			pci_unmap_single(host->pdev, command->cmd_dma,					 command->dma_size, command->dma_dir);			SBP2_DMA_FREE("single bulk");		} else if (command->dma_type == CMD_DMA_PAGE) {			pci_unmap_page(host->pdev, command->cmd_dma,				       command->dma_size, command->dma_dir);			SBP2_DMA_FREE("single page");		} /* XXX: Check for CMD_DMA_NONE bug */		command->dma_type = CMD_DMA_NONE;		command->cmd_dma = 0;	}	if (command->sge_buffer) {		pci_unmap_sg(host->pdev, command->sge_buffer,			     command->dma_size, command->dma_dir);		SBP2_DMA_FREE("scatter list");		command->sge_buffer = NULL;	}}/* * This function moves a command to the completed orb list. */static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command){	unsigned long flags;	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);	list_del(&command->list);	sbp2util_free_command_dma(command);	list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);}/********************************************* * IEEE-1394 core driver stack related section *********************************************/static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud);static int sbp2_probe(struct device *dev){	struct unit_directory *ud;	struct scsi_id_instance_data *scsi_id;	SBP2_DEBUG("sbp2_probe");	ud = container_of(dev, struct unit_directory, device);	/* Don't probe UD's that have the LUN flag. We'll probe the LUN(s)	 * instead. */	if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)		return -ENODEV;        scsi_id = sbp2_alloc_device(ud);        if (!scsi_id)                return -ENOMEM;        sbp2_parse_unit_directory(scsi_id, ud);        return sbp2_start_device(scsi_id);}static int sbp2_remove(struct device *dev){	struct unit_directory *ud;	struct scsi_id_instance_data *scsi_id;	SBP2_DEBUG("sbp2_remove");	ud = container_of(dev, struct unit_directory, device);	scsi_id = ud->device.driver_data;	sbp2_logout_device(scsi_id);	sbp2_remove_device(scsi_id);	return 0;}static int sbp2_update(struct unit_directory *ud){	struct scsi_id_instance_data *scsi_id = ud->device.driver_data;	SBP2_DEBUG("sbp2_update");	if (sbp2_reconnect_device(scsi_id)) {		/*		 * Ok, reconnect has failed. Perhaps we didn't		 * reconnect fast enough. Try doing a regular login, but		 * first do a logout just in case of any weirdness.		 */		sbp2_logout_device(scsi_id);		if (sbp2_login_device(scsi_id)) {			/* Login failed too, just fail, and the backend			 * will call our sbp2_remove for us */			SBP2_ERR("Failed to reconnect to sbp2 device!");			return -EBUSY;		}	}	/* Set max retries to something large on the device. */	sbp2_set_busy_timeout(scsi_id);	/* Do a SBP-2 fetch agent reset. */	sbp2_agent_reset(scsi_id, 1);	/* Get the max speed and packet size that we can use. */	sbp2_max_speed_and_size(scsi_id);	/* Complete any pending commands with busy (so they get	 * retried) and remove them from our queue	 */	sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);	/* Make sure we unblock requests (since this is likely after a bus	 * reset). */	scsi_unblock_requests(scsi_id->scsi_host);	return 0;}/* This functions is called by the sbp2_probe, for each new device. We now * allocate one scsi host for each scsi_id (unit directory). */static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud){	struct sbp2scsi_host_info *hi;	struct Scsi_Host *scsi_host = NULL;	struct scsi_id_instance_data *scsi_id = NULL;	SBP2_DEBUG("sbp2_alloc_device");	scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);	if (!scsi_id) {		SBP2_ERR("failed to create scsi_id");		goto failed_alloc;	}	memset(scsi_id, 0, sizeof(*scsi_id));	scsi_id->ne = ud->ne;	scsi_id->ud = ud;	scsi_id->speed_code = IEEE1394_SPEED_100;	scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];	atomic_set(&scsi_id->sbp2_login_complete, 0);	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);	INIT_LIST_HEAD(&scsi_id->scsi_list);	scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED;	scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;	ud->device.driver_data = scsi_id;	hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host);	if (!hi) {		hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host, sizeof(*hi));		if (!hi) {			SBP2_ERR("failed to allocate hostinfo");			goto failed_alloc;		}		SBP2_DEBUG("sbp2_alloc_device: allocated hostinfo");		hi->host = ud->ne->host;		INIT_LIST_HEAD(&hi->scsi_ids);		/* Register our sbp2 status address space... */		hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_ops,					SBP2_STATUS_FIFO_ADDRESS,					SBP2_STATUS_FIFO_ADDRESS +					SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2_MAX_UDS_PER_NODE+1));#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA		/* Handle data movement if physical dma is not		 * enabled/supportedon host controller */		hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_physdma_ops,					0x0ULL, 0xfffffffcULL);#endif	}	scsi_id->hi = hi;	list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);	/* Register our host with the SCSI stack. */	scsi_host = scsi_host_alloc(&scsi_driver_template, 0);	if (!scsi_host) {		SBP2_ERR("failed to register scsi host");		goto failed_alloc;	}	scsi_host->hostdata[0] = (unsigned long)scsi_id;	if (!scsi_add_host(scsi_host, &ud->device)) {		scsi_id->scsi_host = scsi_host;		return scsi_id;	}	SBP2_ERR("failed to add scsi host");	scsi_host_put(scsi_host);failed_alloc:	sbp2_remove_device(scsi_id);	return NULL;}static void sbp2_host_reset(struct hpsb_host *host){	struct sbp2scsi_host_info *hi;	struct scsi_id_instance_data *scsi_id;	hi = hpsb_get_hostinfo(&sbp2_highlevel, host);	if (hi) {		list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list)			scsi_block_requests(scsi_id->scsi_host);	}}/* * This function is where we first pull the node unique ids, and then * allocate memory and register a SBP-2 device. */static int sbp2_start_device(struct scsi_id_instance_data *scsi_id){	struct sbp2scsi_host_info *hi = scsi_id->hi;	struct scsi_device *sdev;	SBP2_DEBUG("sbp2_start_device");	/* Login FIFO DMA */	scsi_id->login_response =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_response),				     &scsi_id->login_response_dma);	if (!scsi_id->login_response)		goto alloc_fail;	SBP2_DMA_ALLOC("consistent DMA region for login FIFO");	/* Query logins ORB DMA */	scsi_id->query_logins_orb =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_orb),				     &scsi_id->query_logins_orb_dma);	if (!scsi_id->query_logins_orb)		goto alloc_fail;	SBP2_DMA_ALLOC("consistent DMA region for query logins ORB");	/* Query logins response DMA */	scsi_id->query_logins_response =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_response),				     &scsi_id->query_logins_response_dma);	if (!scsi_id->query_logins_response)		goto alloc_fail;	SBP2_DMA_ALLOC("consistent DMA region for query logins response");	/* Reconnect ORB DMA */	scsi_id->reconnect_orb =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_reconnect_orb),				     &scsi_id->reconnect_orb_dma);	if (!scsi_id->reconnect_orb)		goto alloc_fail;	SBP2_DMA_ALLOC("consistent DMA region for reconnect ORB");	/* Logout ORB DMA */	scsi_id->logout_orb =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_logout_orb),				     &scsi_id->logout_orb_dma);	if (!scsi_id->logout_orb)		goto alloc_fail;	SBP2_DMA_ALLOC("consistent DMA region for logout ORB");	/* Login ORB DMA */	scsi_id->login_orb =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_orb),				     &scsi_id->login_orb_dma);	if (!scsi_id->login_orb) {alloc_fail:		if (scsi_id->query_logins_response) {			pci_free_consistent(hi->host->pdev,					    sizeof(struct sbp2_query_logins_response),					    scsi_id->query_logins_response,					    scsi_id->query_logins_response_dma);			SBP2_DMA_FREE("query logins response DMA");		}		if (scsi_id->query_logins_orb) {			pci_free_consistent(hi->host->pdev,					    sizeof(struct sbp2_query_logins_orb),					    scsi_id->query_logins_orb,					    scsi_id->query_logins_orb_dma);			SBP2_DMA_FREE("query logins ORB DMA");		}		if (scsi_id->logout_orb) {			pci_free_consistent(hi->host->pdev,					sizeof(struct sbp2_logout_orb),					scsi_id->logout_orb,					scsi_id->logout_orb_dma);			SBP2_DMA_FREE("logout ORB DMA");		}		if (scsi_id->reconnect_orb) {			pci_free_consistent(hi->host->pdev,					sizeof(struct sbp2_reconnect_orb),					scsi_id->reconnect_orb,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -