diff options
author | Arvind Kumar <arvindkumar@vmware.com> | 2012-03-08 05:18:53 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-03-27 03:26:36 -0400 |
commit | a93107355d2d4557e7e19ea1724bdb710268cd34 (patch) | |
tree | 8a0d1280bac8f3ae53d92da2491d40ee5d649fc1 /drivers | |
parent | 3f0bc3b331a371392bb64c5b211b60ec84d5a444 (diff) |
[SCSI] vmw_pvscsi: Try setting host->max_id as suggested by the device.
Fetch the config page from the device to learn max target id to set
host->max_id.
Also, fix some indentation issues and update the 'Maintained by' field.
Signed-off-by: Arvind Kumar <arvindkumar@vmware.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/vmw_pvscsi.c | 65 | ||||
-rw-r--r-- | drivers/scsi/vmw_pvscsi.h | 109 |
2 files changed, 149 insertions, 25 deletions
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index 7264116185d5..4411d4224401 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c | |||
@@ -17,7 +17,7 @@ | |||
17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | * | 19 | * |
20 | * Maintained by: Alok N Kataria <akataria@vmware.com> | 20 | * Maintained by: Arvind Kumar <arvindkumar@vmware.com> |
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
@@ -1178,11 +1178,67 @@ static int __devinit pvscsi_allocate_sg(struct pvscsi_adapter *adapter) | |||
1178 | return 0; | 1178 | return 0; |
1179 | } | 1179 | } |
1180 | 1180 | ||
1181 | /* | ||
1182 | * Query the device, fetch the config info and return the | ||
1183 | * maximum number of targets on the adapter. In case of | ||
1184 | * failure due to any reason return default i.e. 16. | ||
1185 | */ | ||
1186 | static u32 pvscsi_get_max_targets(struct pvscsi_adapter *adapter) | ||
1187 | { | ||
1188 | struct PVSCSICmdDescConfigCmd cmd; | ||
1189 | struct PVSCSIConfigPageHeader *header; | ||
1190 | struct device *dev; | ||
1191 | dma_addr_t configPagePA; | ||
1192 | void *config_page; | ||
1193 | u32 numPhys = 16; | ||
1194 | |||
1195 | dev = pvscsi_dev(adapter); | ||
1196 | config_page = pci_alloc_consistent(adapter->dev, PAGE_SIZE, | ||
1197 | &configPagePA); | ||
1198 | if (!config_page) { | ||
1199 | dev_warn(dev, "vmw_pvscsi: failed to allocate memory for config page\n"); | ||
1200 | goto exit; | ||
1201 | } | ||
1202 | BUG_ON(configPagePA & ~PAGE_MASK); | ||
1203 | |||
1204 | /* Fetch config info from the device. */ | ||
1205 | cmd.configPageAddress = ((u64)PVSCSI_CONFIG_CONTROLLER_ADDRESS) << 32; | ||
1206 | cmd.configPageNum = PVSCSI_CONFIG_PAGE_CONTROLLER; | ||
1207 | cmd.cmpAddr = configPagePA; | ||
1208 | cmd._pad = 0; | ||
1209 | |||
1210 | /* | ||
1211 | * Mark the completion page header with error values. If the device | ||
1212 | * completes the command successfully, it sets the status values to | ||
1213 | * indicate success. | ||
1214 | */ | ||
1215 | header = config_page; | ||
1216 | memset(header, 0, sizeof *header); | ||
1217 | header->hostStatus = BTSTAT_INVPARAM; | ||
1218 | header->scsiStatus = SDSTAT_CHECK; | ||
1219 | |||
1220 | pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_CONFIG, &cmd, sizeof cmd); | ||
1221 | |||
1222 | if (header->hostStatus == BTSTAT_SUCCESS && | ||
1223 | header->scsiStatus == SDSTAT_GOOD) { | ||
1224 | struct PVSCSIConfigPageController *config; | ||
1225 | |||
1226 | config = config_page; | ||
1227 | numPhys = config->numPhys; | ||
1228 | } else | ||
1229 | dev_warn(dev, "vmw_pvscsi: PVSCSI_CMD_CONFIG failed. hostStatus = 0x%x, scsiStatus = 0x%x\n", | ||
1230 | header->hostStatus, header->scsiStatus); | ||
1231 | pci_free_consistent(adapter->dev, PAGE_SIZE, config_page, configPagePA); | ||
1232 | exit: | ||
1233 | return numPhys; | ||
1234 | } | ||
1235 | |||
1181 | static int __devinit pvscsi_probe(struct pci_dev *pdev, | 1236 | static int __devinit pvscsi_probe(struct pci_dev *pdev, |
1182 | const struct pci_device_id *id) | 1237 | const struct pci_device_id *id) |
1183 | { | 1238 | { |
1184 | struct pvscsi_adapter *adapter; | 1239 | struct pvscsi_adapter *adapter; |
1185 | struct Scsi_Host *host; | 1240 | struct Scsi_Host *host; |
1241 | struct device *dev; | ||
1186 | unsigned int i; | 1242 | unsigned int i; |
1187 | unsigned long flags = 0; | 1243 | unsigned long flags = 0; |
1188 | int error; | 1244 | int error; |
@@ -1272,6 +1328,13 @@ static int __devinit pvscsi_probe(struct pci_dev *pdev, | |||
1272 | } | 1328 | } |
1273 | 1329 | ||
1274 | /* | 1330 | /* |
1331 | * Ask the device for max number of targets. | ||
1332 | */ | ||
1333 | host->max_id = pvscsi_get_max_targets(adapter); | ||
1334 | dev = pvscsi_dev(adapter); | ||
1335 | dev_info(dev, "vmw_pvscsi: host->max_id: %u\n", host->max_id); | ||
1336 | |||
1337 | /* | ||
1275 | * From this point on we should reset the adapter if anything goes | 1338 | * From this point on we should reset the adapter if anything goes |
1276 | * wrong. | 1339 | * wrong. |
1277 | */ | 1340 | */ |
diff --git a/drivers/scsi/vmw_pvscsi.h b/drivers/scsi/vmw_pvscsi.h index 62e36e75715e..3546e8662e30 100644 --- a/drivers/scsi/vmw_pvscsi.h +++ b/drivers/scsi/vmw_pvscsi.h | |||
@@ -17,7 +17,7 @@ | |||
17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | * | 19 | * |
20 | * Maintained by: Alok N Kataria <akataria@vmware.com> | 20 | * Maintained by: Arvind Kumar <arvindkumar@vmware.com> |
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | 28 | ||
29 | #define PVSCSI_DRIVER_VERSION_STRING "1.0.1.0-k" | 29 | #define PVSCSI_DRIVER_VERSION_STRING "1.0.2.0-k" |
30 | 30 | ||
31 | #define PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT 128 | 31 | #define PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT 128 |
32 | 32 | ||
@@ -39,28 +39,45 @@ | |||
39 | * host adapter status/error codes | 39 | * host adapter status/error codes |
40 | */ | 40 | */ |
41 | enum HostBusAdapterStatus { | 41 | enum HostBusAdapterStatus { |
42 | BTSTAT_SUCCESS = 0x00, /* CCB complete normally with no errors */ | 42 | BTSTAT_SUCCESS = 0x00, /* CCB complete normally with no errors */ |
43 | BTSTAT_LINKED_COMMAND_COMPLETED = 0x0a, | 43 | BTSTAT_LINKED_COMMAND_COMPLETED = 0x0a, |
44 | BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG = 0x0b, | 44 | BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG = 0x0b, |
45 | BTSTAT_DATA_UNDERRUN = 0x0c, | 45 | BTSTAT_DATA_UNDERRUN = 0x0c, |
46 | BTSTAT_SELTIMEO = 0x11, /* SCSI selection timeout */ | 46 | BTSTAT_SELTIMEO = 0x11, /* SCSI selection timeout */ |
47 | BTSTAT_DATARUN = 0x12, /* data overrun/underrun */ | 47 | BTSTAT_DATARUN = 0x12, /* data overrun/underrun */ |
48 | BTSTAT_BUSFREE = 0x13, /* unexpected bus free */ | 48 | BTSTAT_BUSFREE = 0x13, /* unexpected bus free */ |
49 | BTSTAT_INVPHASE = 0x14, /* invalid bus phase or sequence requested by target */ | 49 | BTSTAT_INVPHASE = 0x14, /* invalid bus phase or sequence |
50 | BTSTAT_LUNMISMATCH = 0x17, /* linked CCB has different LUN from first CCB */ | 50 | * requested by target */ |
51 | BTSTAT_SENSFAILED = 0x1b, /* auto request sense failed */ | 51 | BTSTAT_LUNMISMATCH = 0x17, /* linked CCB has different LUN from |
52 | BTSTAT_TAGREJECT = 0x1c, /* SCSI II tagged queueing message rejected by target */ | 52 | * first CCB */ |
53 | BTSTAT_BADMSG = 0x1d, /* unsupported message received by the host adapter */ | 53 | BTSTAT_INVPARAM = 0x1a, /* invalid parameter in CCB or segment |
54 | BTSTAT_HAHARDWARE = 0x20, /* host adapter hardware failed */ | 54 | * list */ |
55 | BTSTAT_NORESPONSE = 0x21, /* target did not respond to SCSI ATN, sent a SCSI RST */ | 55 | BTSTAT_SENSFAILED = 0x1b, /* auto request sense failed */ |
56 | BTSTAT_SENTRST = 0x22, /* host adapter asserted a SCSI RST */ | 56 | BTSTAT_TAGREJECT = 0x1c, /* SCSI II tagged queueing message |
57 | BTSTAT_RECVRST = 0x23, /* other SCSI devices asserted a SCSI RST */ | 57 | * rejected by target */ |
58 | BTSTAT_DISCONNECT = 0x24, /* target device reconnected improperly (w/o tag) */ | 58 | BTSTAT_BADMSG = 0x1d, /* unsupported message received by the |
59 | BTSTAT_BUSRESET = 0x25, /* host adapter issued BUS device reset */ | 59 | * host adapter */ |
60 | BTSTAT_ABORTQUEUE = 0x26, /* abort queue generated */ | 60 | BTSTAT_HAHARDWARE = 0x20, /* host adapter hardware failed */ |
61 | BTSTAT_HASOFTWARE = 0x27, /* host adapter software error */ | 61 | BTSTAT_NORESPONSE = 0x21, /* target did not respond to SCSI ATN, |
62 | BTSTAT_HATIMEOUT = 0x30, /* host adapter hardware timeout error */ | 62 | * sent a SCSI RST */ |
63 | BTSTAT_SCSIPARITY = 0x34, /* SCSI parity error detected */ | 63 | BTSTAT_SENTRST = 0x22, /* host adapter asserted a SCSI RST */ |
64 | BTSTAT_RECVRST = 0x23, /* other SCSI devices asserted a SCSI | ||
65 | * RST */ | ||
66 | BTSTAT_DISCONNECT = 0x24, /* target device reconnected improperly | ||
67 | * (w/o tag) */ | ||
68 | BTSTAT_BUSRESET = 0x25, /* host adapter issued BUS device reset */ | ||
69 | BTSTAT_ABORTQUEUE = 0x26, /* abort queue generated */ | ||
70 | BTSTAT_HASOFTWARE = 0x27, /* host adapter software error */ | ||
71 | BTSTAT_HATIMEOUT = 0x30, /* host adapter hardware timeout error */ | ||
72 | BTSTAT_SCSIPARITY = 0x34, /* SCSI parity error detected */ | ||
73 | }; | ||
74 | |||
75 | /* | ||
76 | * SCSI device status values. | ||
77 | */ | ||
78 | enum ScsiDeviceStatus { | ||
79 | SDSTAT_GOOD = 0x00, /* No errors. */ | ||
80 | SDSTAT_CHECK = 0x02, /* Check condition. */ | ||
64 | }; | 81 | }; |
65 | 82 | ||
66 | /* | 83 | /* |
@@ -114,6 +131,29 @@ struct PVSCSICmdDescResetDevice { | |||
114 | } __packed; | 131 | } __packed; |
115 | 132 | ||
116 | /* | 133 | /* |
134 | * Command descriptor for PVSCSI_CMD_CONFIG -- | ||
135 | */ | ||
136 | |||
137 | struct PVSCSICmdDescConfigCmd { | ||
138 | u64 cmpAddr; | ||
139 | u64 configPageAddress; | ||
140 | u32 configPageNum; | ||
141 | u32 _pad; | ||
142 | } __packed; | ||
143 | |||
144 | enum PVSCSIConfigPageType { | ||
145 | PVSCSI_CONFIG_PAGE_CONTROLLER = 0x1958, | ||
146 | PVSCSI_CONFIG_PAGE_PHY = 0x1959, | ||
147 | PVSCSI_CONFIG_PAGE_DEVICE = 0x195a, | ||
148 | }; | ||
149 | |||
150 | enum PVSCSIConfigPageAddressType { | ||
151 | PVSCSI_CONFIG_CONTROLLER_ADDRESS = 0x2120, | ||
152 | PVSCSI_CONFIG_BUSTARGET_ADDRESS = 0x2121, | ||
153 | PVSCSI_CONFIG_PHY_ADDRESS = 0x2122, | ||
154 | }; | ||
155 | |||
156 | /* | ||
117 | * Command descriptor for PVSCSI_CMD_ABORT_CMD -- | 157 | * Command descriptor for PVSCSI_CMD_ABORT_CMD -- |
118 | * | 158 | * |
119 | * - currently does not support specifying the LUN. | 159 | * - currently does not support specifying the LUN. |
@@ -332,6 +372,27 @@ struct PVSCSIRingCmpDesc { | |||
332 | u32 _pad[2]; | 372 | u32 _pad[2]; |
333 | } __packed; | 373 | } __packed; |
334 | 374 | ||
375 | struct PVSCSIConfigPageHeader { | ||
376 | u32 pageNum; | ||
377 | u16 numDwords; | ||
378 | u16 hostStatus; | ||
379 | u16 scsiStatus; | ||
380 | u16 reserved[3]; | ||
381 | } __packed; | ||
382 | |||
383 | struct PVSCSIConfigPageController { | ||
384 | struct PVSCSIConfigPageHeader header; | ||
385 | u64 nodeWWN; /* Device name as defined in the SAS spec. */ | ||
386 | u16 manufacturer[64]; | ||
387 | u16 serialNumber[64]; | ||
388 | u16 opromVersion[32]; | ||
389 | u16 hwVersion[32]; | ||
390 | u16 firmwareVersion[32]; | ||
391 | u32 numPhys; | ||
392 | u8 useConsecutivePhyWWNs; | ||
393 | u8 reserved[3]; | ||
394 | } __packed; | ||
395 | |||
335 | /* | 396 | /* |
336 | * Interrupt status / IRQ bits. | 397 | * Interrupt status / IRQ bits. |
337 | */ | 398 | */ |