pm8001_pci_probe函数分析之scsi_scan_host(一)

本文主要探讨了在pm8001_pci_probe函数中调用的scsi_scan_host函数。文章详细分析了scsi_scan_host内部的工作流程,包括PM8001_CHIP_DISP的使用,以及如何通过pm8001_chip_get_controller_config_req和pm8001_chip_phy_start_req来配置控制器并执行link reset sequence。最后,提到了scsi_host_template结构体与pm8001_scan_finished函数的关系,并预告了后续将要分析的中断处理和发现过程。
摘要由CSDN通过智能技术生成

接着分析pm8001_pci_probe中调用到的scsi_scan_host函数下面是scsi_scan_host的代码

/**
 * scsi_scan_host - scan the given adapter
 * @shost:	adapter to scan
 **/
void scsi_scan_host(struct Scsi_Host *shost)
{
	struct task_struct *p;
	struct async_scan_data *data;

	if (strncmp(scsi_scan_type, "none", 4) == 0)
		return;

	data = scsi_prep_async_scan(shost);
	if (!data) {
		do_scsi_scan_host(shost);
		return;
	}

	p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
	if (IS_ERR(p))
		do_scan_async(data);
}
下面看一下scsi_scan_type是什么,显然它的值是字符串 "async"或者"sync

#ifdef CONFIG_SCSI_SCAN_ASYNC
#define SCSI_SCAN_TYPE_DEFAULT "async"
#else
#define SCSI_SCAN_TYPE_DEFAULT "sync"
#endif
scsi_scan_type[6]=SCSI_SCAN_TYPE_DEFAULT;
如果是异步扫描,那么scsi_prep_async_scan的返回值为TRUE,!data为FALSE,接着用kthread_run执行一个线程。如果是同步扫描,!data为TRUE,直接调用do_scsi_scan_host。结合pm8001的代码我们分别来看一下。首先,我们看一下异步扫描:

p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
在线程环境中调用do_scan_async函数:

static int do_scan_async(void *_data)
{
	struct async_scan_data *data = _data;
	do_scsi_scan_host(data->shost);
	scsi_finish_async_scan(data);
	return 0;
}
下面是do_scsi_scan_host函数:

static void do_scsi_scan_host(struct Scsi_Host *shost)
{
    if (shost->hostt->scan_finished) {
        unsigned long start = jiffies;
        if (shost->hostt->scan_start)
            shost->hostt->scan_start(shost);

        while (!shost->hostt->scan_finished(shost, jiffies - start))
            msleep(10);
    } else {
        scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD,
                SCAN_WILD_CARD, 0);
    }
}

在pm8001_pci_probe中已经调用过shost = scsi_host_alloc(&pm8001_sht, sizeof(void *));它完成的功能是分配scsi_host的内存并以pm8001_sht为模板初始化

/**
 * scsi_host_alloc - register a scsi host adapter instance.
 * @sht:	pointer to scsi host template
 * @privsize:	extra bytes to allocate for driver
 *
 * Note:
 * 	Allocate a new Scsi_Host and perform basic initialization.
 * 	The host is not published to the scsi midlayer until scsi_add_host
 * 	is called.
 *
 * Return value:
 * 	Pointer to a new Scsi_Host
 **/
struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
{
	struct Scsi_Host *shost;
	gfp_t gfp_mask = GFP_KERNEL;
	int rval;

	if (sht->unchecked_isa_dma && privsize)
		gfp_mask |= __GFP_DMA;

	shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
	if (!shost)
		return NULL;

	shost->host_lock = &shost->default_lock;
	spin_lock_init(shost->host_lock);
	shost->shost_state = SHOST_CREATED;
	INIT_LIST_HEAD(&shost->__devices);
	INIT_LIST_HEAD(&shost->__targets);
	INIT_LIST_HEAD(&shost->eh_cmd_q);
	INIT_LIST_HEAD(&shost->starved_list);
	init_waitqueue_head(&shost->host_wait);

	mutex_init(&shost->scan_mutex);

	/*
	 * subtract one because we increment first then return, but we need to
	 * know what the next host number was before increment
	 */
	shost->host_no = atomic_inc_return(&scsi_host_next_hn) - 1;
	shost->dma_channel = 0xff;

	/* These three are default values which can be overridden */
	shost->max_channel = 0;
	shost->max_id = 8;
	shost->max_lun = 8;

	/* Give each shost a default transportt */
	shost->transportt = &blank_transport_template;

	/*
	 * All drivers right now should be able to handle 12 byte
	 * commands.  Every so often there are requests for 16 byte
	 * commands, but individual low-level drivers need to certify that
	 * they actually do something sensible with such commands.
	 */
	shost->max_cmd_len = 12;
	shost->hostt = sht;
	shost->this_id = sht->this_id;
	shost->can_queue = sht->can_queue;
	shost->sg_tablesize = sht->sg_tablesize;
	shost->cmd_per_lun = sht->cmd_per_lun;
	shost->unchecked_isa_dma = sht->unchecked_isa_dma;
	shost->use_clustering = sht->use_clustering;
	shost->ordered_tag = sht->ordered_tag;

	if (sht-&g
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值