Make use of PHY port numbers as targets for the drives instead of the internal PhysDriveNum. Also change ENXIO to EINVAL in one case.
--- mpii.c- Tue Feb 9 19:07:12 2010 +++ mpii.c Tue Feb 9 19:11:22 2010 @@ -1346,44 +1346,43 @@ struct mpii_cfg_raid_vol_pg1 { u_int32_t reserved2; u_int32_t reserved3; } __packed; #define MPII_CFG_RAID_PHYS_DISK_ADDR_NUMBER (1<<28) struct mpii_cfg_raid_physdisk_pg0 { struct mpii_cfg_hdr config_header; - u_int8_t phys_disk_id; - u_int8_t phys_disk_bus; - u_int8_t phys_disk_ioc; + u_int16_t dev_handle; + u_int8_t reserved1; u_int8_t phys_disk_num; u_int8_t enc_id; u_int8_t enc_bus; u_int8_t hot_spare_pool; u_int8_t enc_type; #define MPII_CFG_RAID_PHYDISK_0_ENCTYPE_NONE (0x0) #define MPII_CFG_RAID_PHYDISK_0_ENCTYPE_SAFTE (0x1) #define MPII_CFG_RAID_PHYDISK_0_ENCTYPE_SES (0x2) - u_int32_t reserved1; + u_int32_t reserved2; u_int8_t vendor_id[8]; u_int8_t product_id[16]; u_int8_t product_rev[4]; u_int8_t serial[32]; - u_int32_t reserved2; + u_int32_t reserved3; u_int8_t phys_disk_state; #define MPII_CFG_RAID_PHYDISK_0_STATE_NOTCONFIGURED (0x00) #define MPII_CFG_RAID_PHYDISK_0_STATE_NOTCOMPATIBLE (0x01) #define MPII_CFG_RAID_PHYDISK_0_STATE_OFFLINE (0x02) #define MPII_CFG_RAID_PHYDISK_0_STATE_ONLINE (0x03) #define MPII_CFG_RAID_PHYDISK_0_STATE_HOTSPARE (0x04) #define MPII_CFG_RAID_PHYDISK_0_STATE_DEGRADED (0x05) #define MPII_CFG_RAID_PHYDISK_0_STATE_REBUILDING (0x06) #define MPII_CFG_RAID_PHYDISK_0_STATE_OPTIMAL (0x07) @@ -1402,23 +1401,23 @@ struct mpii_cfg_raid_physdisk_pg0 { #define MPII_CFG_RAID_PHYDISK_0_STATUS_OUTOFSYNC (1<<0) #define MPII_CFG_RAID_PHYDISK_0_STATUS_QUIESCED (1<<1) u_int64_t dev_max_lba; u_int64_t host_max_lba; u_int64_t coerced_max_lba; u_int16_t block_size; - u_int16_t reserved3; + u_int16_t reserved4; - u_int32_t reserved4; + u_int32_t reserved5; } __packed; struct mpii_cfg_raid_physdisk_pg1 { struct mpii_cfg_hdr config_header; u_int8_t num_phys_disk_paths; u_int8_t phys_disk_num; u_int16_t reserved1; u_int32_t reserved2; @@ -2188,20 +2186,21 @@ void mpii_reorder_boot_device(struct mpii_softc *); #if NBIO > 0 int mpii_ioctl(struct device *, u_long, caddr_t); int mpii_ioctl_inq(struct mpii_softc *, struct bioc_inq *); int mpii_ioctl_vol(struct mpii_softc *, struct bioc_vol *); int mpii_ioctl_disk(struct mpii_softc *, struct bioc_disk *); int mpii_bio_hs(struct mpii_softc *, struct bioc_disk *, int, u_int8_t, int *); int mpii_bio_disk(struct mpii_softc *, struct bioc_disk *, u_int8_t); +int mpii_bio_getphy(struct mpii_softc *, u_int16_t, u_int16_t *); #ifndef SMALL_KERNEL int mpii_bio_volstate(struct mpii_softc *, struct bioc_vol *); int mpii_create_sensors(struct mpii_softc *); void mpii_refresh_sensors(void *); #endif /* SMALL_KERNEL */ #endif /* NBIO > 0 */ #define DEVNAME(s) ((s)->sc_dev.dv_xname) #define dwordsof(s) (sizeof(s) / sizeof(u_int32_t)) @@ -5351,21 +5350,21 @@ mpii_bio_hs(struct mpii_softc *sc, struct bioc_disk *b printf("%s: unable to allocate space for raid config page 0\n", DEVNAME(sc)); return (ENOMEM); } if (mpii_req_cfg_page(sc, MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG, MPII_PG_EXTENDED, &ehdr, 1, cpg, pagelen) != 0) { printf("%s: unable to fetch raid config page 0\n", DEVNAME(sc)); free(cpg, M_TEMP); - return (ENXIO); + return (EINVAL); } el = (struct mpii_raid_config_element *)(cpg + 1); for (i = 0; i < cpg->num_elements; i++, el++) { if (ISSET(el->element_flags, MPII_RAID_CONFIG_ELEMENT_FLAG_HSP_PHYS_DISK) && el->hot_spare_pool == hsmap) { /* * diskid comparison is based on the idea that all * disks are counted by the bio(4) in sequence, thus @@ -5406,22 +5405,22 @@ mpii_bio_disk(struct mpii_softc *sc, struct bioc_disk hdr.page_number = 0; hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_RAID_PD; if (mpii_req_cfg_page(sc, MPII_CFG_RAID_PHYS_DISK_ADDR_NUMBER | dn, 0, &hdr, 1, &ppg, sizeof(ppg)) != 0) { printf("%s: unable to fetch raid drive page 0\n", DEVNAME(sc)); return (EINVAL); } - bd->bd_channel = ppg.phys_disk_bus; - bd->bd_target = ppg.phys_disk_num; + if (mpii_bio_getphy(sc, ppg.dev_handle, &bd->bd_target)) + bd->bd_target = ppg.phys_disk_num; switch (ppg.phys_disk_state) { case MPII_CFG_RAID_PHYDISK_0_STATE_ONLINE: case MPII_CFG_RAID_PHYDISK_0_STATE_OPTIMAL: bd->bd_status = BIOC_SDONLINE; break; case MPII_CFG_RAID_PHYDISK_0_STATE_OFFLINE: bd->bd_status = BIOC_SDOFFLINE; break; case MPII_CFG_RAID_PHYDISK_0_STATE_DEGRADED: @@ -5438,20 +5437,46 @@ mpii_bio_disk(struct mpii_softc *sc, struct bioc_disk break; case MPII_CFG_RAID_PHYDISK_0_STATE_NOTCOMPATIBLE: bd->bd_status = BIOC_SDINVALID; break; } bd->bd_size = letoh64(ppg.dev_max_lba) * letoh16(ppg.block_size); scsi_strvis(bd->bd_vendor, ppg.product_id, sizeof(ppg.product_id)); scsi_strvis(bd->bd_serial, ppg.serial, sizeof(ppg.serial)); + + return (0); +} + +int +mpii_bio_getphy(struct mpii_softc *sc, u_int16_t dh, u_int16_t *port) +{ + struct mpii_cfg_sas_dev_pg0 spg; + struct mpii_ecfg_hdr ehdr; + + if (!port) + return (EINVAL); + + bzero(&ehdr, sizeof(ehdr)); + ehdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_EXTENDED; + ehdr.ext_page_length = sizeof(spg) / 4; + ehdr.ext_page_type = MPII_CONFIG_REQ_PAGE_TYPE_SAS_DEVICE; + + if (mpii_req_cfg_page(sc, MPII_CFG_SAS_DEV_ADDR_HANDLE | dh, + MPII_PG_EXTENDED, &ehdr, 1, &spg, sizeof(spg)) != 0) { + printf("%s: unable to fetch sas device page 0\n", + DEVNAME(sc)); + return (EINVAL); + } + + *port = spg.phy_num; return (0); } #ifndef SMALL_KERNEL int mpii_bio_volstate(struct mpii_softc *sc, struct bioc_vol *bv) { struct mpii_cfg_raid_vol_pg0 *vpg; struct mpii_cfg_hdr hdr;