Commit 316b221a authored by Stephen M. Cameron's avatar Stephen M. Cameron Committed by James Bottomley

[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: default avatarJoe Handzik <joseph.t.handzik@hp.com>
Signed-off-by: default avatarStephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent c14c5891
...@@ -2128,6 +2128,37 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, ...@@ -2128,6 +2128,37 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr,
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, ...@@ -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) ...@@ -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) ...@@ -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,10 +3107,22 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) ...@@ -3048,10 +3107,22 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
ncurrent++; ncurrent++;
break; break;
case TYPE_DISK: case TYPE_DISK:
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) { if (i >= nphysicals) {
ncurrent++; ncurrent++;
break; break;
} }
} else {
if (i < nphysicals)
break;
ncurrent++;
break;
}
if (physical_mode == HPSA_REPORT_PHYS_EXTENDED) { if (physical_mode == HPSA_REPORT_PHYS_EXTENDED) {
memcpy(&this_device->ioaccel_handle, memcpy(&this_device->ioaccel_handle,
&lunaddrbytes[20], &lunaddrbytes[20],
...@@ -4116,6 +4187,9 @@ static int hpsa_register_scsi(struct ctlr_info *h) ...@@ -4116,6 +4187,9 @@ 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;
if (h->hba_mode_enabled)
sh->cmd_per_lun = 7;
else
sh->cmd_per_lun = h->nr_cmds; 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;
...@@ -5261,6 +5335,16 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *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 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -6885,6 +6969,7 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
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);
......
...@@ -64,6 +64,46 @@ struct reply_pool { ...@@ -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 { ...@@ -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 { ...@@ -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 {
......
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