[SCSI] hpsa: Add hba mode to the hpsa driver
This allows exposing physical disks behind Smart Array controllers to the OS (if the controller has the right firmware and is in "hba" mode) Signed-off-by: Joe Handzik <joseph.t.handzik@hp.com> Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
c14c5891dd
commit
316b221a37
|
@ -2128,6 +2128,37 @@ out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hpsa_bmic_ctrl_mode_sense(struct ctlr_info *h,
|
||||||
|
unsigned char *scsi3addr, unsigned char page,
|
||||||
|
struct bmic_controller_parameters *buf, size_t bufsize)
|
||||||
|
{
|
||||||
|
int rc = IO_OK;
|
||||||
|
struct CommandList *c;
|
||||||
|
struct ErrorInfo *ei;
|
||||||
|
|
||||||
|
c = cmd_special_alloc(h);
|
||||||
|
|
||||||
|
if (c == NULL) { /* trouble... */
|
||||||
|
dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fill_cmd(c, BMIC_SENSE_CONTROLLER_PARAMETERS, h, buf, bufsize,
|
||||||
|
page, scsi3addr, TYPE_CMD)) {
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE);
|
||||||
|
ei = c->err_info;
|
||||||
|
if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
|
||||||
|
hpsa_scsi_interpret_error(h, c);
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
cmd_special_free(h, c);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr,
|
static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr,
|
||||||
u8 reset_type)
|
u8 reset_type)
|
||||||
{
|
{
|
||||||
|
@ -2929,6 +2960,24 @@ u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position, int i,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hpsa_hba_mode_enabled(struct ctlr_info *h)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct bmic_controller_parameters *ctlr_params;
|
||||||
|
ctlr_params = kzalloc(sizeof(struct bmic_controller_parameters),
|
||||||
|
GFP_KERNEL);
|
||||||
|
|
||||||
|
if (!ctlr_params)
|
||||||
|
return 0;
|
||||||
|
rc = hpsa_bmic_ctrl_mode_sense(h, RAID_CTLR_LUNID, 0, ctlr_params,
|
||||||
|
sizeof(struct bmic_controller_parameters));
|
||||||
|
if (rc != 0) {
|
||||||
|
kfree(ctlr_params);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ctlr_params->nvram_flags & (1 << 3) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
|
static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
|
||||||
{
|
{
|
||||||
/* the idea here is we could get notified
|
/* the idea here is we could get notified
|
||||||
|
@ -2952,6 +3001,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
|
||||||
int reportlunsize = sizeof(*physdev_list) + HPSA_MAX_PHYS_LUN * 24;
|
int reportlunsize = sizeof(*physdev_list) + HPSA_MAX_PHYS_LUN * 24;
|
||||||
int i, n_ext_target_devs, ndevs_to_allocate;
|
int i, n_ext_target_devs, ndevs_to_allocate;
|
||||||
int raid_ctlr_position;
|
int raid_ctlr_position;
|
||||||
|
u8 rescan_hba_mode;
|
||||||
DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS);
|
DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS);
|
||||||
|
|
||||||
currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL);
|
currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL);
|
||||||
|
@ -2965,6 +3015,15 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
|
||||||
}
|
}
|
||||||
memset(lunzerobits, 0, sizeof(lunzerobits));
|
memset(lunzerobits, 0, sizeof(lunzerobits));
|
||||||
|
|
||||||
|
rescan_hba_mode = hpsa_hba_mode_enabled(h);
|
||||||
|
|
||||||
|
if (!h->hba_mode_enabled && rescan_hba_mode)
|
||||||
|
dev_warn(&h->pdev->dev, "HBA mode enabled\n");
|
||||||
|
else if (h->hba_mode_enabled && !rescan_hba_mode)
|
||||||
|
dev_warn(&h->pdev->dev, "HBA mode disabled\n");
|
||||||
|
|
||||||
|
h->hba_mode_enabled = rescan_hba_mode;
|
||||||
|
|
||||||
if (hpsa_gather_lun_info(h, reportlunsize,
|
if (hpsa_gather_lun_info(h, reportlunsize,
|
||||||
(struct ReportLUNdata *) physdev_list, &nphysicals,
|
(struct ReportLUNdata *) physdev_list, &nphysicals,
|
||||||
&physical_mode, logdev_list, &nlogicals))
|
&physical_mode, logdev_list, &nlogicals))
|
||||||
|
@ -3048,7 +3107,19 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
|
||||||
ncurrent++;
|
ncurrent++;
|
||||||
break;
|
break;
|
||||||
case TYPE_DISK:
|
case TYPE_DISK:
|
||||||
if (i >= nphysicals) {
|
if (h->hba_mode_enabled) {
|
||||||
|
/* never use raid mapper in HBA mode */
|
||||||
|
this_device->offload_enabled = 0;
|
||||||
|
ncurrent++;
|
||||||
|
break;
|
||||||
|
} else if (h->acciopath_status) {
|
||||||
|
if (i >= nphysicals) {
|
||||||
|
ncurrent++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (i < nphysicals)
|
||||||
|
break;
|
||||||
ncurrent++;
|
ncurrent++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4116,7 +4187,10 @@ static int hpsa_register_scsi(struct ctlr_info *h)
|
||||||
sh->max_lun = HPSA_MAX_LUN;
|
sh->max_lun = HPSA_MAX_LUN;
|
||||||
sh->max_id = HPSA_MAX_LUN;
|
sh->max_id = HPSA_MAX_LUN;
|
||||||
sh->can_queue = h->nr_cmds;
|
sh->can_queue = h->nr_cmds;
|
||||||
sh->cmd_per_lun = h->nr_cmds;
|
if (h->hba_mode_enabled)
|
||||||
|
sh->cmd_per_lun = 7;
|
||||||
|
else
|
||||||
|
sh->cmd_per_lun = h->nr_cmds;
|
||||||
sh->sg_tablesize = h->maxsgentries;
|
sh->sg_tablesize = h->maxsgentries;
|
||||||
h->scsi_host = sh;
|
h->scsi_host = sh;
|
||||||
sh->hostdata[0] = (unsigned long) h;
|
sh->hostdata[0] = (unsigned long) h;
|
||||||
|
@ -5261,6 +5335,16 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
|
||||||
c->Request.CDB[8] = (size >> 8) & 0xFF;
|
c->Request.CDB[8] = (size >> 8) & 0xFF;
|
||||||
c->Request.CDB[9] = size & 0xFF;
|
c->Request.CDB[9] = size & 0xFF;
|
||||||
break;
|
break;
|
||||||
|
case BMIC_SENSE_CONTROLLER_PARAMETERS:
|
||||||
|
c->Request.CDBLen = 10;
|
||||||
|
c->Request.Type.Attribute = ATTR_SIMPLE;
|
||||||
|
c->Request.Type.Direction = XFER_READ;
|
||||||
|
c->Request.Timeout = 0;
|
||||||
|
c->Request.CDB[0] = BMIC_READ;
|
||||||
|
c->Request.CDB[6] = BMIC_SENSE_CONTROLLER_PARAMETERS;
|
||||||
|
c->Request.CDB[7] = (size >> 16) & 0xFF;
|
||||||
|
c->Request.CDB[8] = (size >> 8) & 0xFF;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd);
|
dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd);
|
||||||
BUG();
|
BUG();
|
||||||
|
@ -6885,6 +6969,7 @@ reinit_after_soft_reset:
|
||||||
|
|
||||||
pci_set_drvdata(pdev, h);
|
pci_set_drvdata(pdev, h);
|
||||||
h->ndevices = 0;
|
h->ndevices = 0;
|
||||||
|
h->hba_mode_enabled = 0;
|
||||||
h->scsi_host = NULL;
|
h->scsi_host = NULL;
|
||||||
spin_lock_init(&h->devlock);
|
spin_lock_init(&h->devlock);
|
||||||
hpsa_put_ctlr_into_performant_mode(h);
|
hpsa_put_ctlr_into_performant_mode(h);
|
||||||
|
@ -6944,8 +7029,8 @@ reinit_after_soft_reset:
|
||||||
goto reinit_after_soft_reset;
|
goto reinit_after_soft_reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable Accelerated IO path at driver layer */
|
/* Enable Accelerated IO path at driver layer */
|
||||||
h->acciopath_status = 1;
|
h->acciopath_status = 1;
|
||||||
|
|
||||||
h->drv_req_rescan = 0;
|
h->drv_req_rescan = 0;
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,46 @@ struct reply_pool {
|
||||||
u32 current_entry;
|
u32 current_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
|
struct bmic_controller_parameters {
|
||||||
|
u8 led_flags;
|
||||||
|
u8 enable_command_list_verification;
|
||||||
|
u8 backed_out_write_drives;
|
||||||
|
u16 stripes_for_parity;
|
||||||
|
u8 parity_distribution_mode_flags;
|
||||||
|
u16 max_driver_requests;
|
||||||
|
u16 elevator_trend_count;
|
||||||
|
u8 disable_elevator;
|
||||||
|
u8 force_scan_complete;
|
||||||
|
u8 scsi_transfer_mode;
|
||||||
|
u8 force_narrow;
|
||||||
|
u8 rebuild_priority;
|
||||||
|
u8 expand_priority;
|
||||||
|
u8 host_sdb_asic_fix;
|
||||||
|
u8 pdpi_burst_from_host_disabled;
|
||||||
|
char software_name[64];
|
||||||
|
char hardware_name[32];
|
||||||
|
u8 bridge_revision;
|
||||||
|
u8 snapshot_priority;
|
||||||
|
u32 os_specific;
|
||||||
|
u8 post_prompt_timeout;
|
||||||
|
u8 automatic_drive_slamming;
|
||||||
|
u8 reserved1;
|
||||||
|
u8 nvram_flags;
|
||||||
|
u8 cache_nvram_flags;
|
||||||
|
u8 drive_config_flags;
|
||||||
|
u16 reserved2;
|
||||||
|
u8 temp_warning_level;
|
||||||
|
u8 temp_shutdown_level;
|
||||||
|
u8 temp_condition_reset;
|
||||||
|
u8 max_coalesce_commands;
|
||||||
|
u32 max_coalesce_delay;
|
||||||
|
u8 orca_password[4];
|
||||||
|
u8 access_id[16];
|
||||||
|
u8 reserved[356];
|
||||||
|
};
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
struct ctlr_info {
|
struct ctlr_info {
|
||||||
int ctlr;
|
int ctlr;
|
||||||
char devname[8];
|
char devname[8];
|
||||||
|
@ -89,6 +129,7 @@ struct ctlr_info {
|
||||||
unsigned int msi_vector;
|
unsigned int msi_vector;
|
||||||
int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
|
int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
|
||||||
struct access_method access;
|
struct access_method access;
|
||||||
|
char hba_mode_enabled;
|
||||||
|
|
||||||
/* queue and queue Info */
|
/* queue and queue Info */
|
||||||
struct list_head reqQ;
|
struct list_head reqQ;
|
||||||
|
|
|
@ -257,6 +257,7 @@ struct SenseSubsystem_info {
|
||||||
#define BMIC_CACHE_FLUSH 0xc2
|
#define BMIC_CACHE_FLUSH 0xc2
|
||||||
#define HPSA_CACHE_FLUSH 0x01 /* C2 was already being used by HPSA */
|
#define HPSA_CACHE_FLUSH 0x01 /* C2 was already being used by HPSA */
|
||||||
#define BMIC_FLASH_FIRMWARE 0xF7
|
#define BMIC_FLASH_FIRMWARE 0xF7
|
||||||
|
#define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64
|
||||||
|
|
||||||
/* Command List Structure */
|
/* Command List Structure */
|
||||||
union SCSI3Addr {
|
union SCSI3Addr {
|
||||||
|
|
Loading…
Reference in a new issue