Commit 6c005216 authored by Stephen Rothwell's avatar Stephen Rothwell

Merge remote-tracking branch 'scsi-mkp/for-next'

parents 14d1524d 326a859b
......@@ -1196,8 +1196,6 @@ config SCSI_AM53C974
PCscsi/PCnet (Am53/79C974) solutions.
This is a new implementation base on the generic esp_scsi driver.
Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
Note that this driver does NOT support Tekram DC390W/U/F, which are
based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
......
......@@ -614,7 +614,14 @@ int sas_smp_phy_control(struct domain_device *dev, int phy_id,
}
res = smp_execute_task(dev, pc_req, PC_REQ_SIZE, pc_resp,PC_RESP_SIZE);
if (res) {
pr_err("ex %016llx phy%02d PHY control failed: %d\n",
SAS_ADDR(dev->sas_addr), phy_id, res);
} else if (pc_resp[2] != SMP_RESP_FUNC_ACC) {
pr_err("ex %016llx phy%02d PHY control failed: function result 0x%x\n",
SAS_ADDR(dev->sas_addr), phy_id, pc_resp[2]);
res = pc_resp[2];
}
kfree(pc_resp);
kfree(pc_req);
return res;
......@@ -817,6 +824,26 @@ static struct domain_device *sas_ex_discover_end_dev(
#ifdef CONFIG_SCSI_SAS_ATA
if ((phy->attached_tproto & SAS_PROTOCOL_STP) || phy->attached_sata_dev) {
if (child->linkrate > parent->min_linkrate) {
struct sas_phy_linkrates rates = {
.maximum_linkrate = parent->min_linkrate,
.minimum_linkrate = parent->min_linkrate,
};
int ret;
pr_notice("ex %016llx phy%02d SATA device linkrate > min pathway connection rate, attempting to lower device linkrate\n",
SAS_ADDR(child->sas_addr), phy_id);
ret = sas_smp_phy_control(parent, phy_id,
PHY_FUNC_LINK_RESET, &rates);
if (ret) {
pr_err("ex %016llx phy%02d SATA device could not set linkrate (%d)\n",
SAS_ADDR(child->sas_addr), phy_id, ret);
goto out_free;
}
pr_notice("ex %016llx phy%02d SATA device set linkrate successfully\n",
SAS_ADDR(child->sas_addr), phy_id);
child->linkrate = child->min_linkrate;
}
res = sas_get_ata_info(child, phy);
if (res)
goto out_free;
......
......@@ -1002,7 +1002,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon)
/* Scsi_Host attributes. */
static ssize_t
qla2x00_drvr_version_show(struct device *dev,
qla2x00_driver_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
......@@ -2059,7 +2059,21 @@ ql2xiniexchg_store(struct device *dev, struct device_attribute *attr,
return strlen(buf);
}
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
static ssize_t
qla2x00_dif_bundle_statistics_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
return scnprintf(buf, PAGE_SIZE,
"cross=%llu read=%llu write=%llu kalloc=%llu dma_alloc=%llu unusable=%u\n",
ha->dif_bundle_crossed_pages, ha->dif_bundle_reads,
ha->dif_bundle_writes, ha->dif_bundle_kallocs,
ha->dif_bundle_dma_allocs, ha->pool.unusable.count);
}
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_driver_version_show, NULL);
static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
static DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
......@@ -2112,6 +2126,8 @@ static DEVICE_ATTR(zio_threshold, 0644,
static DEVICE_ATTR_RW(qlini_mode);
static DEVICE_ATTR_RW(ql2xexchoffld);
static DEVICE_ATTR_RW(ql2xiniexchg);
static DEVICE_ATTR(dif_bundle_statistics, 0444,
qla2x00_dif_bundle_statistics_show, NULL);
struct device_attribute *qla2x00_host_attrs[] = {
......@@ -2150,6 +2166,7 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_min_link_speed,
&dev_attr_max_speed_sup,
&dev_attr_zio_threshold,
&dev_attr_dif_bundle_statistics,
NULL, /* reserve for qlini_mode */
NULL, /* reserve for ql2xiniexchg */
NULL, /* reserve for ql2xexchoffld */
......
......@@ -314,6 +314,7 @@ struct srb_cmd {
#define SRB_CRC_PROT_DMA_VALID BIT_4 /* DIF: prot DMA valid */
#define SRB_CRC_CTX_DSD_VALID BIT_5 /* DIF: dsd_list valid */
#define SRB_WAKEUP_ON_COMP BIT_6
#define SRB_DIF_BUNDL_DMA_VALID BIT_7 /* DIF: DMA list valid */
/* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */
#define IS_PROT_IO(sp) (sp->flags & SRB_CRC_CTX_DSD_VALID)
......@@ -1892,6 +1893,13 @@ struct crc_context {
/* List of DMA context transfers */
struct list_head dsd_list;
/* List of DIF Bundling context DMA address */
struct list_head ldif_dsd_list;
u8 no_ldif_dsd;
struct list_head ldif_dma_hndl_list;
u32 dif_bundl_len;
u8 no_dif_bundl;
/* This structure should not exceed 512 bytes */
};
......@@ -4184,6 +4192,26 @@ struct qla_hw_data {
uint16_t min_link_speed;
uint16_t max_speed_sup;
/* DMA pool for the DIF bundling buffers */
struct dma_pool *dif_bundl_pool;
#define DIF_BUNDLING_DMA_POOL_SIZE 1024
struct {
struct {
struct list_head head;
uint count;
} good;
struct {
struct list_head head;
uint count;
} unusable;
} pool;
unsigned long long dif_bundle_crossed_pages;
unsigned long long dif_bundle_reads;
unsigned long long dif_bundle_writes;
unsigned long long dif_bundle_kallocs;
unsigned long long dif_bundle_dma_allocs;
atomic_t nvme_active_aen_cnt;
uint16_t nvme_last_rptd_aen; /* Last recorded aen count */
......
......@@ -160,6 +160,7 @@ extern int ql2xautodetectsfp;
extern int ql2xenablemsix;
extern int qla2xuseresexchforels;
extern int ql2xexlogins;
extern int ql2xdifbundlinginternalbuffers;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
......@@ -285,7 +286,7 @@ extern int qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *, srb_t *,
extern int qla24xx_walk_and_build_sglist(struct qla_hw_data *, srb_t *,
uint32_t *, uint16_t, struct qla_tc_param *);
extern int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *, srb_t *,
uint32_t *, uint16_t, struct qla_tc_param *);
uint32_t *, uint16_t, struct qla_tgt_cmd *);
extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *);
extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *,
......
This diff is collapsed.
......@@ -2725,6 +2725,17 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
cp->device->vendor);
break;
case CS_DMA:
ql_log(ql_log_info, fcport->vha, 0x3022,
"CS_DMA error: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%06x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
comp_status, scsi_status, res, vha->host_no,
cp->device->id, cp->device->lun, fcport->d_id.b24,
ox_id, cp->cmnd, scsi_bufflen(cp), rsp_info_len,
resid_len, fw_resid_len, sp, cp);
ql_dump_buffer(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe0ee,
pkt, sizeof(*sts24));
res = DID_ERROR << 16;
break;
default:
res = DID_ERROR << 16;
break;
......
......@@ -285,6 +285,27 @@ MODULE_PARM_DESC(qla2xuseresexchforels,
"Reserve 1/2 of emergency exchanges for ELS.\n"
" 0 (default): disabled");
int ql2xprotmask;
module_param(ql2xprotmask, int, 0644);
MODULE_PARM_DESC(ql2xprotmask,
"Override DIF/DIX protection capabilities mask\n"
"Default is 0 which sets protection mask based on "
"capabilities reported by HBA firmware.\n");
int ql2xprotguard;
module_param(ql2xprotguard, int, 0644);
MODULE_PARM_DESC(ql2xprotguard, "Override choice of DIX checksum\n"
" 0 -- Let HBA firmware decide\n"
" 1 -- Force T10 CRC\n"
" 2 -- Force IP checksum\n");
int ql2xdifbundlinginternalbuffers;
module_param(ql2xdifbundlinginternalbuffers, int, 0644);
MODULE_PARM_DESC(ql2xdifbundlinginternalbuffers,
"Force using internal buffers for DIF information\n"
"0 (Default). Based on check.\n"
"1 Force using internal buffers\n");
/*
* SCSI host template entry points
*/
......@@ -804,7 +825,44 @@ qla2xxx_qpair_sp_free_dma(void *ptr)
ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt;
ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
mempool_free(ctx1, ha->ctx_mempool);
sp->flags &= ~SRB_FCP_CMND_DMA_VALID;
}
if (sp->flags & SRB_DIF_BUNDL_DMA_VALID) {
struct crc_context *difctx = sp->u.scmd.ctx;
struct dsd_dma *dif_dsd, *nxt_dsd;
list_for_each_entry_safe(dif_dsd, nxt_dsd,
&difctx->ldif_dma_hndl_list, list) {
list_del(&dif_dsd->list);
dma_pool_free(ha->dif_bundl_pool, dif_dsd->dsd_addr,
dif_dsd->dsd_list_dma);
kfree(dif_dsd);
difctx->no_dif_bundl--;
}
list_for_each_entry_safe(dif_dsd, nxt_dsd,
&difctx->ldif_dsd_list, list) {
list_del(&dif_dsd->list);
dma_pool_free(ha->dl_dma_pool, dif_dsd->dsd_addr,
dif_dsd->dsd_list_dma);
kfree(dif_dsd);
difctx->no_ldif_dsd--;
}
if (difctx->no_ldif_dsd) {
ql_dbg(ql_dbg_tgt+ql_dbg_verbose, sp->vha, 0xe022,
"%s: difctx->no_ldif_dsd=%x\n",
__func__, difctx->no_ldif_dsd);
}
if (difctx->no_dif_bundl) {
ql_dbg(ql_dbg_tgt+ql_dbg_verbose, sp->vha, 0xe022,
"%s: difctx->no_dif_bundl=%x\n",
__func__, difctx->no_dif_bundl);
}
sp->flags &= ~SRB_DIF_BUNDL_DMA_VALID;
}
end:
CMD_SP(cmd) = NULL;
qla2xxx_rel_qpair_sp(sp->qpair, sp);
......@@ -3342,13 +3400,16 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
"Registering for DIF/DIX type 1 and 3 protection.\n");
if (ql2xenabledif == 1)
prot = SHOST_DIX_TYPE0_PROTECTION;
scsi_host_set_prot(host,
prot | SHOST_DIF_TYPE1_PROTECTION
| SHOST_DIF_TYPE2_PROTECTION
| SHOST_DIF_TYPE3_PROTECTION
| SHOST_DIX_TYPE1_PROTECTION
| SHOST_DIX_TYPE2_PROTECTION
| SHOST_DIX_TYPE3_PROTECTION);
if (ql2xprotmask)
scsi_host_set_prot(host, ql2xprotmask);
else
scsi_host_set_prot(host,
prot | SHOST_DIF_TYPE1_PROTECTION
| SHOST_DIF_TYPE2_PROTECTION
| SHOST_DIF_TYPE3_PROTECTION
| SHOST_DIX_TYPE1_PROTECTION
| SHOST_DIX_TYPE2_PROTECTION
| SHOST_DIX_TYPE3_PROTECTION);
guard = SHOST_DIX_GUARD_CRC;
......@@ -3356,7 +3417,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
(ql2xenabledif > 1 || IS_PI_DIFB_DIX0_CAPABLE(ha)))
guard |= SHOST_DIX_GUARD_IP;
scsi_host_set_guard(host, guard);
if (ql2xprotguard)
scsi_host_set_guard(host, ql2xprotguard);
else
scsi_host_set_guard(host, guard);
} else
base_vha->flags.difdix_supported = 0;
}
......@@ -3997,9 +4061,86 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
"Failed to allocate memory for fcp_cmnd_dma_pool.\n");
goto fail_dl_dma_pool;
}
if (ql2xenabledif) {
u64 bufsize = DIF_BUNDLING_DMA_POOL_SIZE;
struct dsd_dma *dsd, *nxt;
uint i;
/* Creata a DMA pool of buffers for DIF bundling */
ha->dif_bundl_pool = dma_pool_create(name,
&ha->pdev->dev, DIF_BUNDLING_DMA_POOL_SIZE, 8, 0);
if (!ha->dif_bundl_pool) {
ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0024,
"%s: failed create dif_bundl_pool\n",
__func__);
goto fail_dif_bundl_dma_pool;
}
INIT_LIST_HEAD(&ha->pool.good.head);
INIT_LIST_HEAD(&ha->pool.unusable.head);
ha->pool.good.count = 0;
ha->pool.unusable.count = 0;
for (i = 0; i < 128; i++) {
dsd = kzalloc(sizeof(*dsd), GFP_ATOMIC);
if (!dsd) {
ql_dbg_pci(ql_dbg_init, ha->pdev,
0xe0ee, "%s: failed alloc dsd\n",
__func__);
return 1;
}
ha->dif_bundle_kallocs++;
dsd->dsd_addr = dma_pool_alloc(
ha->dif_bundl_pool, GFP_ATOMIC,
&dsd->dsd_list_dma);
if (!dsd->dsd_addr) {
ql_dbg_pci(ql_dbg_init, ha->pdev,
0xe0ee,
"%s: failed alloc ->dsd_addr\n",
__func__);
kfree(dsd);
ha->dif_bundle_kallocs--;
continue;
}
ha->dif_bundle_dma_allocs++;
/*
* if DMA buffer crosses 4G boundary,
* put it on bad list
*/
if (MSD(dsd->dsd_list_dma) ^
MSD(dsd->dsd_list_dma + bufsize)) {
list_add_tail(&dsd->list,
&ha->pool.unusable.head);
ha->pool.unusable.count++;
} else {
list_add_tail(&dsd->list,
&ha->pool.good.head);
ha->pool.good.count++;
}
}
/* return the good ones back to the pool */
list_for_each_entry_safe(dsd, nxt,
&ha->pool.good.head, list) {
list_del(&dsd->list);
dma_pool_free(ha->dif_bundl_pool,
dsd->dsd_addr, dsd->dsd_list_dma);
ha->dif_bundle_dma_allocs--;
kfree(dsd);
ha->dif_bundle_kallocs--;
}
ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0024,
"%s: dif dma pool (good=%u unusable=%u)\n",
__func__, ha->pool.good.count,
ha->pool.unusable.count);
}
ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0025,
"dl_dma_pool=%p fcp_cmnd_dma_pool=%p.\n",
ha->dl_dma_pool, ha->fcp_cmnd_dma_pool);
"dl_dma_pool=%p fcp_cmnd_dma_pool=%p dif_bundl_pool=%p.\n",
ha->dl_dma_pool, ha->fcp_cmnd_dma_pool,
ha->dif_bundl_pool);
}
/* Allocate memory for SNS commands */
......@@ -4164,6 +4305,24 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
ha->sns_cmd, ha->sns_cmd_dma);
fail_dma_pool:
if (ql2xenabledif) {
struct dsd_dma *dsd, *nxt;
list_for_each_entry_safe(dsd, nxt, &ha->pool.unusable.head,
list) {
list_del(&dsd->list);
dma_pool_free(ha->dif_bundl_pool, dsd->dsd_addr,
dsd->dsd_list_dma);
ha->dif_bundle_dma_allocs--;
kfree(dsd);
ha->dif_bundle_kallocs--;
ha->pool.unusable.count--;
}
dma_pool_destroy(ha->dif_bundl_pool);
ha->dif_bundl_pool = NULL;
}
fail_dif_bundl_dma_pool:
if (IS_QLA82XX(ha) || ql2xenabledif) {
dma_pool_destroy(ha->fcp_cmnd_dma_pool);
ha->fcp_cmnd_dma_pool = NULL;
......@@ -4544,6 +4703,32 @@ qla2x00_mem_free(struct qla_hw_data *ha)
mempool_destroy(ha->ctx_mempool);
if (ql2xenabledif) {
struct dsd_dma *dsd, *nxt;
list_for_each_entry_safe(dsd, nxt, &ha->pool.unusable.head,
list) {
list_del(&dsd->list);
dma_pool_free(ha->dif_bundl_pool, dsd->dsd_addr,
dsd->dsd_list_dma);
ha->dif_bundle_dma_allocs--;
kfree(dsd);
ha->dif_bundle_kallocs--;
ha->pool.unusable.count--;
}
list_for_each_entry_safe(dsd, nxt, &ha->pool.good.head, list) {
list_del(&dsd->list);
dma_pool_free(ha->dif_bundl_pool, dsd->dsd_addr,
dsd->dsd_list_dma);
ha->dif_bundle_dma_allocs--;
kfree(dsd);
ha->dif_bundle_kallocs--;
}
}
if (ha->dif_bundl_pool)
dma_pool_destroy(ha->dif_bundl_pool);
qlt_mem_free(ha);
if (ha->init_cb)
......
......@@ -3230,7 +3230,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm)
cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address;
if (qla24xx_walk_and_build_prot_sglist(ha, NULL, cur_dsd,
prm->prot_seg_cnt, &tc))
prm->prot_seg_cnt, cmd))
goto crc_queuing_error;
}
return QLA_SUCCESS;
......
......@@ -928,6 +928,8 @@ struct qla_tgt_cmd {
uint64_t lba;
uint16_t a_guard, e_guard, a_app_tag, e_app_tag;
uint32_t a_ref_tag, e_ref_tag;
#define DIF_BUNDL_DMA_VALID 1
uint16_t prot_flags;
uint64_t jiffies_at_alloc;
uint64_t jiffies_at_free;
......
......@@ -99,7 +99,6 @@ config SCSI_UFS_DWC_TC_PLATFORM
config SCSI_UFS_QCOM
tristate "QCOM specific hooks to UFS controller platform driver"
depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM
select PHY_QCOM_UFS
help
This selects the QCOM specific additions to UFSHCD platform driver.
UFS host on QCOM needs some vendor specific configuration before
......
......@@ -52,8 +52,8 @@ enum sas_phy_role {
};
enum sas_phy_type {
PHY_TYPE_PHYSICAL,
PHY_TYPE_VIRTUAL
PHY_TYPE_PHYSICAL,
PHY_TYPE_VIRTUAL
};
/* The events are mnemonically described in sas_dump.c
......@@ -91,7 +91,7 @@ enum discover_event {
#define to_dom_device(_obj) container_of(_obj, struct domain_device, dev_obj)
#define to_dev_attr(_attr) container_of(_attr, struct domain_dev_attribute,\
attr)
attr)
enum routing_attribute {
DIRECT_ROUTING,
......@@ -184,37 +184,37 @@ struct domain_device {
spinlock_t done_lock;
enum sas_device_type dev_type;
enum sas_linkrate linkrate;
enum sas_linkrate min_linkrate;
enum sas_linkrate max_linkrate;
enum sas_linkrate linkrate;
enum sas_linkrate min_linkrate;
enum sas_linkrate max_linkrate;
int pathways;
int pathways;
struct domain_device *parent;
struct list_head siblings; /* devices on the same level */
struct asd_sas_port *port; /* shortcut to root of the tree */
struct domain_device *parent;
struct list_head siblings; /* devices on the same level */
struct asd_sas_port *port; /* shortcut to root of the tree */
struct sas_phy *phy;
struct list_head dev_list_node;
struct list_head dev_list_node;
struct list_head disco_list_node; /* awaiting probe or destruct */
enum sas_protocol iproto;
enum sas_protocol tproto;
enum sas_protocol iproto;
enum sas_protocol tproto;
struct sas_rphy *rphy;
struct sas_rphy *rphy;
u8 sas_addr[SAS_ADDR_SIZE];
u8 hashed_sas_addr[HASHED_SAS_ADDR_SIZE];
u8 sas_addr[SAS_ADDR_SIZE];
u8 hashed_sas_addr[HASHED_SAS_ADDR_SIZE];
u8 frame_rcvd[32];
u8 frame_rcvd[32];
union {
struct expander_device ex_dev;
struct sata_device sata_dev; /* STP & directly attached */
union {
struct expander_device ex_dev;
struct sata_device sata_dev; /* STP & directly attached */
struct ssp_device ssp_dev;
};
};
void *lldd_dev;
void *lldd_dev;
unsigned long state;
struct kref kref;
};
......@@ -512,10 +512,10 @@ enum exec_status {
/* When a task finishes with a response, the LLDD examines the
* response:
* - For an ATA task task_status_struct::stat is set to
* - For an ATA task task_status_struct::stat is set to
* SAS_PROTO_RESPONSE, and the task_status_struct::buf is set to the
* contents of struct ata_task_resp.
* - For SSP tasks, if no data is present or status/TMF response
* - For SSP tasks, if no data is present or status/TMF response
* is valid, task_status_struct::stat is set. If data is present
* (SENSE data), the LLDD copies up to SAS_STATUS_BUF_SIZE, sets
* task_status_struct::buf_valid_size, and task_status_struct::stat is
......@@ -671,15 +671,13 @@ extern void sas_prep_resume_ha(struct sas_ha_struct *sas_ha);
extern void sas_resume_ha(struct sas_ha_struct *sas_ha);
extern void sas_suspend_ha(struct sas_ha_struct *sas_ha);
int sas_set_phy_speed(struct sas_phy *phy,
struct sas_phy_linkrates *rates);
int sas_set_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates);
int sas_phy_reset(struct sas_phy *phy, int hard_reset);
extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *);
extern int sas_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
extern int sas_target_alloc(struct scsi_target *);
extern int sas_slave_configure(struct scsi_device *);
extern int sas_change_queue_depth(struct scsi_device *, int new_depth);
extern int sas_bios_param(struct scsi_device *,
struct block_device *,
extern int sas_bios_param(struct scsi_device *, struct block_device *,
sector_t capacity, int *hsc);
extern struct scsi_transport_template *
sas_domain_attach_transport(struct sas_domain_function_template *);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment