summaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/hpsa.c93
-rw-r--r--drivers/scsi/hpsa.h41
-rw-r--r--drivers/scsi/hpsa_cmd.h1
3 files changed, 131 insertions, 4 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 388e229cdcec..eb23eeacf592 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2128,6 +2128,37 @@ out:
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)
{
@@ -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
@@ -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);
@@ -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))
@@ -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;
}
@@ -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;
@@ -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();
@@ -6885,6 +6969,7 @@ reinit_after_soft_reset:
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);
@@ -6944,8 +7029,8 @@ reinit_after_soft_reset:
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;
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index ae8c592df8d3..44235a27e1b6 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -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];
@@ -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;
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 50388f133ac9..b5cc7052339f 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -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 {