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

📄 ipr.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	{ "VSBPD1H   U3SCSI", "XXXXXXX*XXXXXXXX", 160 }};/* *  Function Prototypes */static int ipr_reset_alert(struct ipr_cmnd *);static void ipr_process_ccn(struct ipr_cmnd *);static void ipr_process_error(struct ipr_cmnd *);static void ipr_reset_ioa_job(struct ipr_cmnd *);static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *,				   enum ipr_shutdown_type);#ifdef CONFIG_SCSI_IPR_TRACE/** * ipr_trc_hook - Add a trace entry to the driver trace * @ipr_cmd:	ipr command struct * @type:		trace type * @add_data:	additional data * * Return value: * 	none **/static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd,			 u8 type, u32 add_data){	struct ipr_trace_entry *trace_entry;	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;	trace_entry = &ioa_cfg->trace[ioa_cfg->trace_index++];	trace_entry->time = jiffies;	trace_entry->op_code = ipr_cmd->ioarcb.cmd_pkt.cdb[0];	trace_entry->type = type;	trace_entry->ata_op_code = ipr_cmd->ioarcb.add_data.u.regs.command;	trace_entry->cmd_index = ipr_cmd->cmd_index & 0xff;	trace_entry->res_handle = ipr_cmd->ioarcb.res_handle;	trace_entry->u.add_data = add_data;}#else#define ipr_trc_hook(ipr_cmd, type, add_data) do { } while(0)#endif/** * ipr_reinit_ipr_cmnd - Re-initialize an IPR Cmnd block for reuse * @ipr_cmd:	ipr command struct * * Return value: * 	none **/static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd){	struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;	struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;	dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr);	memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));	ioarcb->write_data_transfer_length = 0;	ioarcb->read_data_transfer_length = 0;	ioarcb->write_ioadl_len = 0;	ioarcb->read_ioadl_len = 0;	ioarcb->write_ioadl_addr =		cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl));	ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;	ioasa->ioasc = 0;	ioasa->residual_data_len = 0;	ioasa->u.gata.status = 0;	ipr_cmd->scsi_cmd = NULL;	ipr_cmd->qc = NULL;	ipr_cmd->sense_buffer[0] = 0;	ipr_cmd->dma_use_sg = 0;}/** * ipr_init_ipr_cmnd - Initialize an IPR Cmnd block * @ipr_cmd:	ipr command struct * * Return value: * 	none **/static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd){	ipr_reinit_ipr_cmnd(ipr_cmd);	ipr_cmd->u.scratch = 0;	ipr_cmd->sibling = NULL;	init_timer(&ipr_cmd->timer);}/** * ipr_get_free_ipr_cmnd - Get a free IPR Cmnd block * @ioa_cfg:	ioa config struct * * Return value: * 	pointer to ipr command struct **/staticstruct ipr_cmnd *ipr_get_free_ipr_cmnd(struct ipr_ioa_cfg *ioa_cfg){	struct ipr_cmnd *ipr_cmd;	ipr_cmd = list_entry(ioa_cfg->free_q.next, struct ipr_cmnd, queue);	list_del(&ipr_cmd->queue);	ipr_init_ipr_cmnd(ipr_cmd);	return ipr_cmd;}/** * ipr_mask_and_clear_interrupts - Mask all and clear specified interrupts * @ioa_cfg:	ioa config struct * @clr_ints:     interrupts to clear * * This function masks all interrupts on the adapter, then clears the * interrupts specified in the mask * * Return value: * 	none **/static void ipr_mask_and_clear_interrupts(struct ipr_ioa_cfg *ioa_cfg,					  u32 clr_ints){	volatile u32 int_reg;	/* Stop new interrupts */	ioa_cfg->allow_interrupts = 0;	/* Set interrupt mask to stop all new interrupts */	writel(~0, ioa_cfg->regs.set_interrupt_mask_reg);	/* Clear any pending interrupts */	writel(clr_ints, ioa_cfg->regs.clr_interrupt_reg);	int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);}/** * ipr_save_pcix_cmd_reg - Save PCI-X command register * @ioa_cfg:	ioa config struct * * Return value: * 	0 on success / -EIO on failure **/static int ipr_save_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg){	int pcix_cmd_reg = pci_find_capability(ioa_cfg->pdev, PCI_CAP_ID_PCIX);	if (pcix_cmd_reg == 0)		return 0;	if (pci_read_config_word(ioa_cfg->pdev, pcix_cmd_reg + PCI_X_CMD,				 &ioa_cfg->saved_pcix_cmd_reg) != PCIBIOS_SUCCESSFUL) {		dev_err(&ioa_cfg->pdev->dev, "Failed to save PCI-X command register\n");		return -EIO;	}	ioa_cfg->saved_pcix_cmd_reg |= PCI_X_CMD_DPERR_E | PCI_X_CMD_ERO;	return 0;}/** * ipr_set_pcix_cmd_reg - Setup PCI-X command register * @ioa_cfg:	ioa config struct * * Return value: * 	0 on success / -EIO on failure **/static int ipr_set_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg){	int pcix_cmd_reg = pci_find_capability(ioa_cfg->pdev, PCI_CAP_ID_PCIX);	if (pcix_cmd_reg) {		if (pci_write_config_word(ioa_cfg->pdev, pcix_cmd_reg + PCI_X_CMD,					  ioa_cfg->saved_pcix_cmd_reg) != PCIBIOS_SUCCESSFUL) {			dev_err(&ioa_cfg->pdev->dev, "Failed to setup PCI-X command register\n");			return -EIO;		}	}	return 0;}/** * ipr_sata_eh_done - done function for aborted SATA commands * @ipr_cmd:	ipr command struct * * This function is invoked for ops generated to SATA * devices which are being aborted. * * Return value: * 	none **/static void ipr_sata_eh_done(struct ipr_cmnd *ipr_cmd){	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;	struct ata_queued_cmd *qc = ipr_cmd->qc;	struct ipr_sata_port *sata_port = qc->ap->private_data;	qc->err_mask |= AC_ERR_OTHER;	sata_port->ioasa.status |= ATA_BUSY;	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);	ata_qc_complete(qc);}/** * ipr_scsi_eh_done - mid-layer done function for aborted ops * @ipr_cmd:	ipr command struct * * This function is invoked by the interrupt handler for * ops generated by the SCSI mid-layer which are being aborted. * * Return value: * 	none **/static void ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd){	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;	struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;	scsi_cmd->result |= (DID_ERROR << 16);	scsi_dma_unmap(ipr_cmd->scsi_cmd);	scsi_cmd->scsi_done(scsi_cmd);	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);}/** * ipr_fail_all_ops - Fails all outstanding ops. * @ioa_cfg:	ioa config struct * * This function fails all outstanding ops. * * Return value: * 	none **/static void ipr_fail_all_ops(struct ipr_ioa_cfg *ioa_cfg){	struct ipr_cmnd *ipr_cmd, *temp;	ENTER;	list_for_each_entry_safe(ipr_cmd, temp, &ioa_cfg->pending_q, queue) {		list_del(&ipr_cmd->queue);		ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_IOA_WAS_RESET);		ipr_cmd->ioasa.ilid = cpu_to_be32(IPR_DRIVER_ILID);		if (ipr_cmd->scsi_cmd)			ipr_cmd->done = ipr_scsi_eh_done;		else if (ipr_cmd->qc)			ipr_cmd->done = ipr_sata_eh_done;		ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, IPR_IOASC_IOA_WAS_RESET);		del_timer(&ipr_cmd->timer);		ipr_cmd->done(ipr_cmd);	}	LEAVE;}/** * ipr_do_req -  Send driver initiated requests. * @ipr_cmd:		ipr command struct * @done:			done function * @timeout_func:	timeout function * @timeout:		timeout value * * This function sends the specified command to the adapter with the * timeout given. The done function is invoked on command completion. * * Return value: * 	none **/static void ipr_do_req(struct ipr_cmnd *ipr_cmd,		       void (*done) (struct ipr_cmnd *),		       void (*timeout_func) (struct ipr_cmnd *), u32 timeout){	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;	list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);	ipr_cmd->done = done;	ipr_cmd->timer.data = (unsigned long) ipr_cmd;	ipr_cmd->timer.expires = jiffies + timeout;	ipr_cmd->timer.function = (void (*)(unsigned long))timeout_func;	add_timer(&ipr_cmd->timer);	ipr_trc_hook(ipr_cmd, IPR_TRACE_START, 0);	mb();	writel(be32_to_cpu(ipr_cmd->ioarcb.ioarcb_host_pci_addr),	       ioa_cfg->regs.ioarrin_reg);}/** * ipr_internal_cmd_done - Op done function for an internally generated op. * @ipr_cmd:	ipr command struct * * This function is the op done function for an internally generated, * blocking op. It simply wakes the sleeping thread. * * Return value: * 	none **/static void ipr_internal_cmd_done(struct ipr_cmnd *ipr_cmd){	if (ipr_cmd->sibling)		ipr_cmd->sibling = NULL;	else		complete(&ipr_cmd->completion);}/** * ipr_send_blocking_cmd - Send command and sleep on its completion. * @ipr_cmd:	ipr command struct * @timeout_func:	function to invoke if command times out * @timeout:	timeout * * Return value: * 	none **/static void ipr_send_blocking_cmd(struct ipr_cmnd *ipr_cmd,				  void (*timeout_func) (struct ipr_cmnd *ipr_cmd),				  u32 timeout){	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;	init_completion(&ipr_cmd->completion);	ipr_do_req(ipr_cmd, ipr_internal_cmd_done, timeout_func, timeout);	spin_unlock_irq(ioa_cfg->host->host_lock);	wait_for_completion(&ipr_cmd->completion);	spin_lock_irq(ioa_cfg->host->host_lock);}/** * ipr_send_hcam - Send an HCAM to the adapter. * @ioa_cfg:	ioa config struct * @type:		HCAM type * @hostrcb:	hostrcb struct * * This function will send a Host Controlled Async command to the adapter. * If HCAMs are currently not allowed to be issued to the adapter, it will * place the hostrcb on the free queue. * * Return value: * 	none **/static void ipr_send_hcam(struct ipr_ioa_cfg *ioa_cfg, u8 type,			  struct ipr_hostrcb *hostrcb){	struct ipr_cmnd *ipr_cmd;	struct ipr_ioarcb *ioarcb;	if (ioa_cfg->allow_cmds) {		ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);		list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);		list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_pending_q);		ipr_cmd->u.hostrcb = hostrcb;		ioarcb = &ipr_cmd->ioarcb;		ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE);		ioarcb->cmd_pkt.request_type = IPR_RQTYPE_HCAM;		ioarcb->cmd_pkt.cdb[0] = IPR_HOST_CONTROLLED_ASYNC;		ioarcb->cmd_pkt.cdb[1] = type;		ioarcb->cmd_pkt.cdb[7] = (sizeof(hostrcb->hcam) >> 8) & 0xff;		ioarcb->cmd_pkt.cdb[8] = sizeof(hostrcb->hcam) & 0xff;		ioarcb->read_data_transfer_length = cpu_to_be32(sizeof(hostrcb->hcam));		ioarcb->read_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));		ipr_cmd->ioadl[0].flags_and_data_len =			cpu_to_be32(IPR_IOADL_FLAGS_READ_LAST | sizeof(hostrcb->hcam));		ipr_cmd->ioadl[0].address = cpu_to_be32(hostrcb->hostrcb_dma);		if (type == IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE)			ipr_cmd->done = ipr_process_ccn;		else			ipr_cmd->done = ipr_process_error;		ipr_trc_hook(ipr_cmd, IPR_TRACE_START, IPR_IOA_RES_ADDR);		mb();		writel(be32_to_cpu(ipr_cmd->ioarcb.ioarcb_host_pci_addr),		       ioa_cfg->regs.ioarrin_reg);	} else {		list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_free_q);	}}/** * ipr_init_res_entry - Initialize a resource entry struct. * @res:	resource entry struct * * Return value: * 	none **/static void ipr_init_res_entry(struct ipr_resource_entry *res){	res->needs_sync_complete = 0;	res->in_erp = 0;	res->add_to_ml = 0;	res->del_from_ml = 0;	res->resetting_device = 0;	res->sdev = NULL;	res->sata_port = NULL;}/** * ipr_handle_config_change - Handle a config change from the adapter * @ioa_cfg:	ioa config struct * @hostrcb:	hostrcb * * Return value: * 	none **/static void ipr_handle_config_change(struct ipr_ioa_cfg *ioa_cfg,			      struct ipr_hostrcb *hostrcb){	struct ipr_resource_entry *res = NULL;	struct ipr_config_table_entry *cfgte;	u32 is_ndn = 1;	cfgte = &hostrcb->hcam.u.ccn.cfgte;	list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {		if (!memcmp(&res->cfgte.res_addr, &cfgte->res_addr,			    sizeof(cfgte->res_addr))) {			is_ndn = 0;			break;		}	}	if (is_ndn) {		if (list_empty(&ioa_cfg->free_res_q)) {

⌨️ 快捷键说明

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