Merge pull request #289 from maluueu/dev

Patch hpsa to support HBA/IT mode

Signed-off-by: AuxXxilium <info@auxxxilium.tech>
This commit is contained in:
AuxXxilium 2024-08-21 18:41:14 +02:00
parent be63d62534
commit c3a2e6440b
3 changed files with 232 additions and 7 deletions

View File

@ -90,6 +90,11 @@ module_param(hpsa_simple_mode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(hpsa_simple_mode, MODULE_PARM_DESC(hpsa_simple_mode,
"Use 'simple mode' rather than 'performant mode'"); "Use 'simple mode' rather than 'performant mode'");
static bool hpsa_use_nvram_hba_flag;
module_param(hpsa_use_nvram_hba_flag, bool, 0444);
MODULE_PARM_DESC(hpsa_use_nvram_hba_flag,
"Use flag from NVRAM to enable HBA mode");
/* define the PCI info for the cards we can control */ /* define the PCI info for the cards we can control */
static const struct pci_device_id hpsa_pci_device_id[] = { static const struct pci_device_id hpsa_pci_device_id[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241},
@ -1454,6 +1459,14 @@ static inline int device_updated(struct hpsa_scsi_dev_t *dev1,
return 0; return 0;
} }
static inline bool device_expose_changed(struct hpsa_scsi_dev_t *dev1,
struct hpsa_scsi_dev_t *dev2)
{
if (dev1->expose_device != dev2->expose_device)
return true;
return false;
}
/* Find needle in haystack. If exact match found, return DEVICE_SAME, /* Find needle in haystack. If exact match found, return DEVICE_SAME,
* and return needle location in *index. If scsi3addr matches, but not * and return needle location in *index. If scsi3addr matches, but not
* vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle * vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle
@ -1480,6 +1493,8 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,
if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) { if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) {
*index = i; *index = i;
if (device_is_the_same(needle, haystack[i])) { if (device_is_the_same(needle, haystack[i])) {
if (device_expose_changed(needle, haystack[i]))
return DEVICE_CHANGED;
if (device_updated(needle, haystack[i])) if (device_updated(needle, haystack[i]))
return DEVICE_UPDATED; return DEVICE_UPDATED;
return DEVICE_SAME; return DEVICE_SAME;
@ -2815,6 +2830,37 @@ out:
return rc; return rc;
} }
static int hpsa_bmic_ctrl_mode_sense(struct ctlr_info *h,
struct bmic_controller_parameters *buf)
{
int rc = IO_OK;
struct CommandList *c;
struct ErrorInfo *ei;
c = cmd_alloc(h);
if (fill_cmd(c, BMIC_SENSE_CONTROLLER_PARAMETERS, h, buf, sizeof(*buf),
0, RAID_CTLR_LUNID, TYPE_CMD)) {
rc = -1;
goto out;
}
rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE,
NO_TIMEOUT);
if (rc)
goto out;
ei = c->err_info;
if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
hpsa_scsi_interpret_error(h, c);
rc = -1;
}
out:
cmd_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, int reply_queue) u8 reset_type, int reply_queue)
{ {
@ -3992,6 +4038,66 @@ static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes,
return false; return false;
} }
static bool is_hba_supported(const struct bmic_identify_controller *id_ctlr)
{
return le32_to_cpu(id_ctlr->yet_more_controller_flags) &
YET_MORE_CTLR_FLAG_HBA_MODE_SUPP;
}
static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled)
{
int rc;
struct bmic_controller_parameters *ctlr_params;
ctlr_params = kzalloc(sizeof(*ctlr_params), GFP_KERNEL);
if (!ctlr_params) {
rc = -ENOMEM;
goto out;
}
rc = hpsa_bmic_ctrl_mode_sense(h, ctlr_params);
if (rc)
goto out;
*flag_enabled = ctlr_params->nvram_flags & HPSA_NVRAM_FLAG_HBA;
out:
kfree(ctlr_params);
return rc;
}
static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals,
const struct bmic_identify_controller *id_ctlr)
{
int rc;
bool flag_enabled;
bool ignore;
if (!hpsa_use_nvram_hba_flag)
return 0;
if (!is_hba_supported(id_ctlr)) {
dev_info(&h->pdev->dev, "NVRAM HBA flag: not supported\n");
return 0;
}
rc = hpsa_nvram_hba_flag_enabled(h, &flag_enabled);
if (rc == -ENOMEM)
dev_warn(&h->pdev->dev, "Out of memory.\n");
if (rc)
return rc;
ignore = flag_enabled && nlogicals;
dev_info(&h->pdev->dev, "NVRAM HBA flag: %s%s\n",
flag_enabled ? "enabled" : "disabled",
ignore ? " (ignored because of existing logical devices)" : "");
h->nvram_hba_mode_enabled = flag_enabled && !ignore;
return 0;
}
static void hpsa_update_scsi_devices(struct ctlr_info *h) static void hpsa_update_scsi_devices(struct ctlr_info *h)
{ {
/* the idea here is we could get notified /* the idea here is we could get notified
@ -4048,6 +4154,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
__func__); __func__);
} }
if (hpsa_update_nvram_hba_mode(h, nlogicals, id_ctlr)) {
h->drv_req_rescan = 1;
goto out;
}
/* We might see up to the maximum number of logical and physical disks /* We might see up to the maximum number of logical and physical disks
* plus external target devices, and a device for the local RAID * plus external target devices, and a device for the local RAID
* controller. * controller.
@ -4144,11 +4255,15 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
* Expose all devices except for physical devices that * Expose all devices except for physical devices that
* are masked. * are masked.
*/ */
if (MASKED_DEVICE(lunaddrbytes) && this_device->physical_device) if (MASKED_DEVICE(lunaddrbytes) &&
this_device->expose_device = 0; this_device->physical_device) {
else if (h->nvram_hba_mode_enabled)
this_device->expose_device = 1; this_device->expose_device = 1;
else
this_device->expose_device = 0;
} else {
this_device->expose_device = 1;
}
/* /*
* Get the SAS address for physical devices that are exposed. * Get the SAS address for physical devices that are exposed.
*/ */

View File

@ -153,6 +153,8 @@ struct bmic_controller_parameters {
}; };
#pragma pack() #pragma pack()
#define HPSA_NVRAM_FLAG_HBA (1 << 3)
struct ctlr_info { struct ctlr_info {
int ctlr; int ctlr;
char devname[8]; char devname[8];
@ -178,6 +180,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;
bool nvram_hba_mode_enabled;
/* queue and queue Info */ /* queue and queue Info */
unsigned int Qdepth; unsigned int Qdepth;

View File

@ -687,13 +687,120 @@ struct hpsa_pci_info {
struct bmic_identify_controller { struct bmic_identify_controller {
u8 configured_logical_drive_count; /* offset 0 */ u8 configured_logical_drive_count; /* offset 0 */
u8 pad1[153]; __le32 signature;
char running_firm_rev[4];
char rom_firm_rev[4];
u8 hardware_rev;
u8 reserved_1[4];
__le32 drive_present_bit_map;
__le32 external_drive_bit_map;
__le32 board_id;
u8 reserved_2;
__le32 non_disk_map;
u8 reserved_3[5];
u8 marketing_revision;
u8 controller_flags;
u8 host_flags;
u8 expand_disable_code;
u8 scsi_chip_count;
u8 reserved_4[4];
__le32 ctlr_clock;
u8 drives_per_scsi_bus;
__le16 big_drive_present_map[8];
__le16 big_ext_drive_map[8];
__le16 big_non_disk_map[8];
/* used for FW debugging */
__le16 task_flags;
/* Bitmap used for ICL between controllers */
u8 icl_bus_map;
/* See REDUNDANT MODE VALUES */
u8 redund_ctlr_modes_support;
/* See REDUNDANT MODE VALUES */
u8 curr_redund_ctlr_mode;
/* See REDUNDANT STATUS FLAG */
u8 redund_ctlr_status;
/* See REDUNDANT FAILURE VALUES */
u8 redund_op_failure_code;
u8 unsupported_nile_bus;
u8 host_i2c_autorev;
u8 cpld_revision;
u8 fibre_chip_count;
u8 daughterboard_type;
u8 reserved_5[2];
u8 access_module_status;
u8 features_supported[12];
/* Recovery ROM inactive f/w revision */
char rec_rom_inactive_rev[4];
/* Recovery ROM flags */
u8 rec_rom_flags;
u8 pci_to_pci_bridge_status;
/* Reserved for future use */
u8 reserved_6[4];
/* Percent of memory allocated to write cache */
u8 percent_write_cache;
/* Total cache board size */
__le16 daughter_board_cache_size;
/* Number of cache batteries */
u8 cache_battery_count;
/* Total size (MB) of atttached memory */
__le16 total_memory_size;
/* Additional controller flags byte */
u8 more_controller_flags;
/* 2nd byte of 3 byte autorev field */
u8 x_board_host_i2c_autorev;
/* BBWC PIC revision */
u8 battery_pic_rev;
/* DDFF update engine version */
u8 ddff_version[4];
/* Maximum logical units supported */
__le16 max_logical_units;
/* Big num configured logical units */
__le16 extended_logical_unit_count; /* offset 154 */ __le16 extended_logical_unit_count; /* offset 154 */
u8 pad2[136]; /* Maximum physical devices supported */
__le16 max_physical_devices;
/* Max physical drive per logical unit */
__le16 max_phy_drv_per_logical_unit;
/* Number of attached enclosures */
u8 enclosure_count;
/* Number of expanders detected */
u8 expander_count;
/* Offset to extended drive present map*/
__le16 offset_to_edp_bitmap;
/* Offset to extended external drive present map */
__le16 offset_to_eedp_bitmap;
/* Offset to extended non-disk map */
__le16 offset_to_end_bitmap;
/* Internal port status bytes */
u8 internal_port_status[8];
/* External port status bytes */
u8 external_port_status[8];
/* Yet More Controller flags */
__le32 yet_more_controller_flags;
/* Last lockup code */
u8 last_lockup;
/* PCI slot according to option ROM*/
u8 pci_slot;
/* Build number */
__le16 build_num;
/* Maximum safe full stripe size */
__le32 max_safe_full_stripe_size;
/* Total structure length */
__le32 total_length;
/* Vendor ID */
char vendor_id[8];
/* Product ID */
char product_id[16];
u8 reserved_7[68];
u8 controller_mode; /* offset 292 */ u8 controller_mode; /* offset 292 */
u8 pad3[32]; u8 reserved_8[32];
}; };
/* ssacli calls this bit "Hba Mode Supported". */
#define YET_MORE_CTLR_FLAG_HBA_MODE_SUPP (1 << 25)
struct bmic_identify_physical_device { struct bmic_identify_physical_device {
u8 scsi_bus; /* SCSI Bus number on controller */ u8 scsi_bus; /* SCSI Bus number on controller */
u8 scsi_id; /* SCSI ID on this bus */ u8 scsi_id; /* SCSI ID on this bus */