Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 235bfc7f authored by Xiang Chen's avatar Xiang Chen Committed by Martin K. Petersen
Browse files

scsi: hisi_sas: Create a scsi_host_template per HW module



When a SCSI host is registered, the SCSI mid-layer takes a reference to a
module in Scsi_host.hostt.module. In doing this, we are prevented from
removing the driver module for the host in dangerous scenario, like when a
disk is mounted.

Currently there is only one scsi_host_template (sht) for all HW versions,
and this is the main.c module. So this means that we can possibly remove
the HW module in this dangerous scenario, as SCSI mid-layer is only
referencing the main.c module.

To fix this, create a sht per module, referencing that same module to
create the Scsi host.

Signed-off-by: default avatarXiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: default avatarJohn Garry <john.garry@huawei.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent d5a60dfd
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -248,6 +248,7 @@ struct hisi_sas_hw {
				u8 reg_index, u8 reg_count, u8 *write_data);
	int max_command_entries;
	int complete_hdr_size;
	struct scsi_host_template *sht;
};

struct hisi_hba {
@@ -440,8 +441,6 @@ struct hisi_sas_slot_buf_table {
};

extern struct scsi_transport_template *hisi_sas_stt;
extern struct scsi_host_template *hisi_sas_sht;

extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba);
extern int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost);
extern void hisi_sas_free(struct hisi_hba *hisi_hba);
@@ -456,6 +455,11 @@ extern int hisi_sas_probe(struct platform_device *pdev,
			  const struct hisi_sas_hw *ops);
extern int hisi_sas_remove(struct platform_device *pdev);

extern int hisi_sas_slave_configure(struct scsi_device *sdev);
extern int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time);
extern void hisi_sas_scan_start(struct Scsi_Host *shost);
extern struct device_attribute *host_attrs[];
extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type);
extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy);
extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
				    struct sas_task *task,
+10 −30
Original line number Diff line number Diff line
@@ -719,7 +719,7 @@ static int hisi_sas_dev_found(struct domain_device *device)
	return rc;
}

static int hisi_sas_slave_configure(struct scsi_device *sdev)
int hisi_sas_slave_configure(struct scsi_device *sdev)
{
	struct domain_device *dev = sdev_to_domain_dev(sdev);
	int ret = sas_slave_configure(sdev);
@@ -731,15 +731,17 @@ static int hisi_sas_slave_configure(struct scsi_device *sdev)

	return 0;
}
EXPORT_SYMBOL_GPL(hisi_sas_slave_configure);

static void hisi_sas_scan_start(struct Scsi_Host *shost)
void hisi_sas_scan_start(struct Scsi_Host *shost)
{
	struct hisi_hba *hisi_hba = shost_priv(shost);

	hisi_hba->hw->phys_init(hisi_hba);
}
EXPORT_SYMBOL_GPL(hisi_sas_scan_start);

static int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
{
	struct hisi_hba *hisi_hba = shost_priv(shost);
	struct sas_ha_struct *sha = &hisi_hba->sha;
@@ -751,6 +753,7 @@ static int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
	sas_drain_work(sha);
	return 1;
}
EXPORT_SYMBOL_GPL(hisi_sas_scan_finished);

static void hisi_sas_phyup_work(struct work_struct *work)
{
@@ -1824,34 +1827,11 @@ EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets);
struct scsi_transport_template *hisi_sas_stt;
EXPORT_SYMBOL_GPL(hisi_sas_stt);

static struct device_attribute *host_attrs[] = {
struct device_attribute *host_attrs[] = {
	&dev_attr_phy_event_threshold,
	NULL,
};

static struct scsi_host_template _hisi_sas_sht = {
	.module			= THIS_MODULE,
	.name			= DRV_NAME,
	.queuecommand		= sas_queuecommand,
	.target_alloc		= sas_target_alloc,
	.slave_configure	= hisi_sas_slave_configure,
	.scan_finished		= hisi_sas_scan_finished,
	.scan_start		= hisi_sas_scan_start,
	.change_queue_depth	= sas_change_queue_depth,
	.bios_param		= sas_bios_param,
	.can_queue		= 1,
	.this_id		= -1,
	.sg_tablesize		= SG_ALL,
	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
	.use_clustering		= ENABLE_CLUSTERING,
	.eh_device_reset_handler = sas_eh_device_reset_handler,
	.eh_target_reset_handler = sas_eh_target_reset_handler,
	.target_destroy		= sas_target_destroy,
	.ioctl			= sas_ioctl,
	.shost_attrs		= host_attrs,
};
struct scsi_host_template *hisi_sas_sht = &_hisi_sas_sht;
EXPORT_SYMBOL_GPL(hisi_sas_sht);
EXPORT_SYMBOL_GPL(host_attrs);

static struct sas_domain_function_template hisi_sas_transport_ops = {
	.lldd_dev_found		= hisi_sas_dev_found,
@@ -2161,7 +2141,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
	struct hisi_hba *hisi_hba;
	struct device *dev = &pdev->dev;

	shost = scsi_host_alloc(hisi_sas_sht, sizeof(*hisi_hba));
	shost = scsi_host_alloc(hw->sht, sizeof(*hisi_hba));
	if (!shost) {
		dev_err(dev, "scsi host alloc failed\n");
		return NULL;
+23 −0
Original line number Diff line number Diff line
@@ -1788,6 +1788,28 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba)
	return 0;
}

static struct scsi_host_template sht_v1_hw = {
	.name			= DRV_NAME,
	.module			= THIS_MODULE,
	.queuecommand		= sas_queuecommand,
	.target_alloc		= sas_target_alloc,
	.slave_configure	= hisi_sas_slave_configure,
	.scan_finished		= hisi_sas_scan_finished,
	.scan_start		= hisi_sas_scan_start,
	.change_queue_depth	= sas_change_queue_depth,
	.bios_param		= sas_bios_param,
	.can_queue		= 1,
	.this_id		= -1,
	.sg_tablesize		= SG_ALL,
	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
	.use_clustering		= ENABLE_CLUSTERING,
	.eh_device_reset_handler = sas_eh_device_reset_handler,
	.eh_target_reset_handler = sas_eh_target_reset_handler,
	.target_destroy		= sas_target_destroy,
	.ioctl			= sas_ioctl,
	.shost_attrs		= host_attrs,
};

static const struct hisi_sas_hw hisi_sas_v1_hw = {
	.hw_init = hisi_sas_v1_init,
	.setup_itct = setup_itct_v1_hw,
@@ -1807,6 +1829,7 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = {
	.get_wideport_bitmap = get_wideport_bitmap_v1_hw,
	.max_command_entries = HISI_SAS_COMMAND_ENTRIES_V1_HW,
	.complete_hdr_size = sizeof(struct hisi_sas_complete_v1_hdr),
	.sht = &sht_v1_hw,
};

static int hisi_sas_v1_probe(struct platform_device *pdev)
+24 −0
Original line number Diff line number Diff line
@@ -3501,6 +3501,29 @@ static int write_gpio_v2_hw(struct hisi_hba *hisi_hba, u8 reg_type,
	return 0;
}


static struct scsi_host_template sht_v2_hw = {
	.name			= DRV_NAME,
	.module			= THIS_MODULE,
	.queuecommand		= sas_queuecommand,
	.target_alloc		= sas_target_alloc,
	.slave_configure	= hisi_sas_slave_configure,
	.scan_finished		= hisi_sas_scan_finished,
	.scan_start		= hisi_sas_scan_start,
	.change_queue_depth	= sas_change_queue_depth,
	.bios_param		= sas_bios_param,
	.can_queue		= 1,
	.this_id		= -1,
	.sg_tablesize		= SG_ALL,
	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
	.use_clustering		= ENABLE_CLUSTERING,
	.eh_device_reset_handler = sas_eh_device_reset_handler,
	.eh_target_reset_handler = sas_eh_target_reset_handler,
	.target_destroy		= sas_target_destroy,
	.ioctl			= sas_ioctl,
	.shost_attrs		= host_attrs,
};

static const struct hisi_sas_hw hisi_sas_v2_hw = {
	.hw_init = hisi_sas_v2_init,
	.setup_itct = setup_itct_v2_hw,
@@ -3529,6 +3552,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
	.soft_reset = soft_reset_v2_hw,
	.get_phys_state = get_phys_state_v2_hw,
	.write_gpio = write_gpio_v2_hw,
	.sht = &sht_v2_hw,
};

static int hisi_sas_v2_probe(struct platform_device *pdev)
+23 −1
Original line number Diff line number Diff line
@@ -2015,6 +2015,28 @@ static int write_gpio_v3_hw(struct hisi_hba *hisi_hba, u8 reg_type,
	return 0;
}

static struct scsi_host_template sht_v3_hw = {
	.name			= DRV_NAME,
	.module			= THIS_MODULE,
	.queuecommand		= sas_queuecommand,
	.target_alloc		= sas_target_alloc,
	.slave_configure	= hisi_sas_slave_configure,
	.scan_finished		= hisi_sas_scan_finished,
	.scan_start		= hisi_sas_scan_start,
	.change_queue_depth	= sas_change_queue_depth,
	.bios_param		= sas_bios_param,
	.can_queue		= 1,
	.this_id		= -1,
	.sg_tablesize		= SG_ALL,
	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
	.use_clustering		= ENABLE_CLUSTERING,
	.eh_device_reset_handler = sas_eh_device_reset_handler,
	.eh_target_reset_handler = sas_eh_target_reset_handler,
	.target_destroy		= sas_target_destroy,
	.ioctl			= sas_ioctl,
	.shost_attrs		= host_attrs,
};

static const struct hisi_sas_hw hisi_sas_v3_hw = {
	.hw_init = hisi_sas_v3_init,
	.setup_itct = setup_itct_v3_hw,
@@ -2050,7 +2072,7 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
	struct hisi_hba *hisi_hba;
	struct device *dev = &pdev->dev;

	shost = scsi_host_alloc(hisi_sas_sht, sizeof(*hisi_hba));
	shost = scsi_host_alloc(&sht_v3_hw, sizeof(*hisi_hba));
	if (!shost) {
		dev_err(dev, "shost alloc failed\n");
		return NULL;