Skip to content

Commit

Permalink
[SCSI] hpsa: Add hba mode to the hpsa driver
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stephen M. Cameron authored and James Bottomley committed Mar 15, 2014
1 parent c14c589 commit 316b221
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 4 deletions.
93 changes: 89 additions & 4 deletions drivers/scsi/hpsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -2128,6 +2128,37 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr,
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,
u8 reset_type)
{
Expand Down Expand Up @@ -2929,6 +2960,24 @@ u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position, int i,
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)
{
/* the idea here is we could get notified
Expand All @@ -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 i, n_ext_target_devs, ndevs_to_allocate;
int raid_ctlr_position;
u8 rescan_hba_mode;
DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS);

currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL);
Expand All @@ -2965,6 +3015,15 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
}
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,
(struct ReportLUNdata *) physdev_list, &nphysicals,
&physical_mode, logdev_list, &nlogicals))
Expand Down Expand Up @@ -3048,7 +3107,19 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
ncurrent++;
break;
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++;
break;
}
Expand Down Expand Up @@ -4116,7 +4187,10 @@ static int hpsa_register_scsi(struct ctlr_info *h)
sh->max_lun = HPSA_MAX_LUN;
sh->max_id = HPSA_MAX_LUN;
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;
h->scsi_host = sh;
sh->hostdata[0] = (unsigned long) h;
Expand Down Expand Up @@ -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[9] = size & 0xFF;
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:
dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd);
BUG();
Expand Down Expand Up @@ -6885,6 +6969,7 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)

pci_set_drvdata(pdev, h);
h->ndevices = 0;
h->hba_mode_enabled = 0;
h->scsi_host = NULL;
spin_lock_init(&h->devlock);
hpsa_put_ctlr_into_performant_mode(h);
Expand Down Expand Up @@ -6944,8 +7029,8 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto reinit_after_soft_reset;
}

/* Enable Accelerated IO path at driver layer */
h->acciopath_status = 1;
/* Enable Accelerated IO path at driver layer */
h->acciopath_status = 1;

h->drv_req_rescan = 0;

Expand Down
41 changes: 41 additions & 0 deletions drivers/scsi/hpsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,46 @@ struct reply_pool {
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 {
int ctlr;
char devname[8];
Expand All @@ -89,6 +129,7 @@ struct ctlr_info {
unsigned int msi_vector;
int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
struct access_method access;
char hba_mode_enabled;

/* queue and queue Info */
struct list_head reqQ;
Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/hpsa_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ struct SenseSubsystem_info {
#define BMIC_CACHE_FLUSH 0xc2
#define HPSA_CACHE_FLUSH 0x01 /* C2 was already being used by HPSA */
#define BMIC_FLASH_FIRMWARE 0xF7
#define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64

/* Command List Structure */
union SCSI3Addr {
Expand Down

0 comments on commit 316b221

Please sign in to comment.