blob: 3dbb5659f61588e74175c12466399f5cbad31a96 [file] [log] [blame]
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001/*
2 * linux/drivers/message/fusion/mptsas.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
Eric Moore9f4203b2007-01-04 20:47:47 -07006 * Copyright (c) 1999-2007 LSI Logic Corporation
Christoph Hellwig0c33b272005-09-09 16:27:19 +02007 * (mailto:mpt_linux_developer@lsil.com)
Eric Moore9f4203b2007-01-04 20:47:47 -07008 * Copyright (c) 2005-2007 Dell
Christoph Hellwig0c33b272005-09-09 16:27:19 +02009 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47#include <linux/module.h>
48#include <linux/kernel.h>
49#include <linux/init.h>
50#include <linux/errno.h>
51#include <linux/sched.h>
52#include <linux/workqueue.h>
Eric Moore547f9a22006-06-27 14:42:12 -060053#include <linux/delay.h> /* for mdelay */
Christoph Hellwig0c33b272005-09-09 16:27:19 +020054
Eric Moore547f9a22006-06-27 14:42:12 -060055#include <scsi/scsi.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020056#include <scsi/scsi_cmnd.h>
57#include <scsi/scsi_device.h>
58#include <scsi/scsi_host.h>
59#include <scsi/scsi_transport_sas.h>
Eric Moore547f9a22006-06-27 14:42:12 -060060#include <scsi/scsi_dbg.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020061
62#include "mptbase.h"
63#include "mptscsih.h"
64
65
66#define my_NAME "Fusion MPT SAS Host driver"
67#define my_VERSION MPT_LINUX_VERSION_COMMON
68#define MYNAM "mptsas"
69
James Bottomleye8bf3942006-07-11 17:49:34 -040070/*
71 * Reserved channel for integrated raid
72 */
73#define MPTSAS_RAID_CHANNEL 1
74
Christoph Hellwig0c33b272005-09-09 16:27:19 +020075MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
Eric Moore9f4203b2007-01-04 20:47:47 -070078MODULE_VERSION(my_VERSION);
Christoph Hellwig0c33b272005-09-09 16:27:19 +020079
Christoph Hellwig0c33b272005-09-09 16:27:19 +020080static int mpt_pt_clear;
81module_param(mpt_pt_clear, int, 0);
82MODULE_PARM_DESC(mpt_pt_clear,
Eric Mooreba856d32006-07-11 17:34:01 -060083 " Clear persistency table: enable=1 "
Christoph Hellwig0c33b272005-09-09 16:27:19 +020084 "(default=MPTSCSIH_PT_CLEAR=0)");
85
Eric Moore793955f2007-01-29 09:42:20 -070086/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
87#define MPTSAS_MAX_LUN (16895)
88static int max_lun = MPTSAS_MAX_LUN;
89module_param(max_lun, int, 0);
90MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
91
Christoph Hellwig0c33b272005-09-09 16:27:19 +020092static int mptsasDoneCtx = -1;
93static int mptsasTaskCtx = -1;
94static int mptsasInternalCtx = -1; /* Used only for internal commands */
Christoph Hellwigda4fa652005-10-19 20:01:42 +020095static int mptsasMgmtCtx = -1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020096
Eric Mooreb506ade2007-01-29 09:45:37 -070097static void mptsas_hotplug_work(struct work_struct *work);
Christoph Hellwig0c33b272005-09-09 16:27:19 +020098
Eric Mooredf9e0622007-01-29 09:46:21 -070099struct mptsas_target_reset_event {
100 struct list_head list;
101 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
102 u8 target_reset_issued;
103};
104
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100105enum mptsas_hotplug_action {
106 MPTSAS_ADD_DEVICE,
107 MPTSAS_DEL_DEVICE,
Moore, Ericc73787ee2006-01-26 16:20:06 -0700108 MPTSAS_ADD_RAID,
109 MPTSAS_DEL_RAID,
Eric Mooreb506ade2007-01-29 09:45:37 -0700110 MPTSAS_ADD_INACTIVE_VOLUME,
Moore, Ericbd23e942006-04-17 12:43:04 -0600111 MPTSAS_IGNORE_EVENT,
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100112};
113
114struct mptsas_hotplug_event {
115 struct work_struct work;
116 MPT_ADAPTER *ioc;
117 enum mptsas_hotplug_action event_type;
118 u64 sas_address;
Eric Mooreb506ade2007-01-29 09:45:37 -0700119 u8 channel;
120 u8 id;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100121 u32 device_info;
122 u16 handle;
123 u16 parent_handle;
124 u8 phy_id;
Eric Mooreb506ade2007-01-29 09:45:37 -0700125 u8 phys_disk_num_valid; /* hrc (hidden raid component) */
126 u8 phys_disk_num; /* hrc - unique index*/
127 u8 hidden_raid_component; /* hrc - don't expose*/
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100128};
129
Moore, Erice6b2d762006-03-14 09:14:24 -0700130struct mptsas_discovery_event {
131 struct work_struct work;
132 MPT_ADAPTER *ioc;
133};
134
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200135/*
136 * SAS topology structures
137 *
138 * The MPT Fusion firmware interface spreads information about the
139 * SAS topology over many manufacture pages, thus we need some data
140 * structure to collect it and process it for the SAS transport class.
141 */
142
143struct mptsas_devinfo {
144 u16 handle; /* unique id to address this device */
Moore, Ericc73787ee2006-01-26 16:20:06 -0700145 u16 handle_parent; /* unique id to address parent device */
Christoph Hellwige3094442006-02-16 13:25:36 +0100146 u16 handle_enclosure; /* enclosure identifier of the enclosure */
147 u16 slot; /* physical slot in enclosure */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200148 u8 phy_id; /* phy number of parent device */
149 u8 port_id; /* sas physical port this device
150 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100151 u8 id; /* logical target id of this device */
Eric Mooreb506ade2007-01-29 09:45:37 -0700152 u32 phys_disk_num; /* phys disk id, for csmi-ioctls */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100153 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200154 u64 sas_address; /* WWN of this device,
155 SATA is assigned by HBA,expander */
156 u32 device_info; /* bitfield detailed info about this device */
157};
158
Eric Moore547f9a22006-06-27 14:42:12 -0600159/*
160 * Specific details on ports, wide/narrow
161 */
162struct mptsas_portinfo_details{
Eric Moore547f9a22006-06-27 14:42:12 -0600163 u16 num_phys; /* number of phys belong to this port */
164 u64 phy_bitmask; /* TODO, extend support for 255 phys */
165 struct sas_rphy *rphy; /* transport layer rphy object */
166 struct sas_port *port; /* transport layer port object */
167 struct scsi_target *starget;
168 struct mptsas_portinfo *port_info;
169};
170
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200171struct mptsas_phyinfo {
172 u8 phy_id; /* phy index */
Eric Moore547f9a22006-06-27 14:42:12 -0600173 u8 port_id; /* firmware port identifier */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200174 u8 negotiated_link_rate; /* nego'd link rate for this phy */
175 u8 hw_link_rate; /* hardware max/min phys link rate */
176 u8 programmed_link_rate; /* programmed max/min phy link rate */
Eric Moore547f9a22006-06-27 14:42:12 -0600177 u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200178 struct mptsas_devinfo identify; /* point to phy device info */
179 struct mptsas_devinfo attached; /* point to attached device info */
Eric Moore547f9a22006-06-27 14:42:12 -0600180 struct sas_phy *phy; /* transport layer phy object */
181 struct mptsas_portinfo *portinfo;
182 struct mptsas_portinfo_details * port_details;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200183};
184
185struct mptsas_portinfo {
186 struct list_head list;
187 u16 handle; /* unique id to address this */
Eric Moore547f9a22006-06-27 14:42:12 -0600188 u16 num_phys; /* number of phys */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200189 struct mptsas_phyinfo *phy_info;
190};
191
Christoph Hellwige3094442006-02-16 13:25:36 +0100192struct mptsas_enclosure {
193 u64 enclosure_logical_id; /* The WWN for the enclosure */
194 u16 enclosure_handle; /* unique id to address this */
195 u16 flags; /* details enclosure management */
196 u16 num_slot; /* num slots */
197 u16 start_slot; /* first slot */
198 u8 start_id; /* starting logical target id */
199 u8 start_channel; /* starting logical channel id */
200 u8 sep_id; /* SEP device logical target id */
201 u8 sep_channel; /* SEP channel logical channel id */
202};
203
Eric Moore547f9a22006-06-27 14:42:12 -0600204#ifdef MPT_DEBUG_SAS
Christoph Hellwigb5141122005-10-28 22:07:41 +0200205static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
206{
207 printk("---- IO UNIT PAGE 0 ------------\n");
208 printk("Handle=0x%X\n",
209 le16_to_cpu(phy_data->AttachedDeviceHandle));
210 printk("Controller Handle=0x%X\n",
211 le16_to_cpu(phy_data->ControllerDevHandle));
212 printk("Port=0x%X\n", phy_data->Port);
213 printk("Port Flags=0x%X\n", phy_data->PortFlags);
214 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
215 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
216 printk("Controller PHY Device Info=0x%X\n",
217 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
218 printk("DiscoveryStatus=0x%X\n",
219 le32_to_cpu(phy_data->DiscoveryStatus));
220 printk("\n");
221}
222
223static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
224{
225 __le64 sas_address;
226
227 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
228
229 printk("---- SAS PHY PAGE 0 ------------\n");
230 printk("Attached Device Handle=0x%X\n",
231 le16_to_cpu(pg0->AttachedDevHandle));
232 printk("SAS Address=0x%llX\n",
233 (unsigned long long)le64_to_cpu(sas_address));
234 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
235 printk("Attached Device Info=0x%X\n",
236 le32_to_cpu(pg0->AttachedDeviceInfo));
237 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
238 printk("Change Count=0x%X\n", pg0->ChangeCount);
239 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
240 printk("\n");
241}
242
243static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
244{
245 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200246 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
247 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200248 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200249 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
250 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
251 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200252}
253
254static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
255{
256 __le64 sas_address;
257
258 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
259
260 printk("---- SAS DEVICE PAGE 0 ---------\n");
261 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
Christoph Hellwige3094442006-02-16 13:25:36 +0100262 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200263 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
264 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
Eric Mooref99be432007-01-04 20:46:54 -0700265 printk("SAS Address=0x%llX\n", (unsigned long long)
266 le64_to_cpu(sas_address));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200267 printk("Target ID=0x%X\n", pg0->TargetID);
268 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200269 /* The PhyNum field specifies the PHY number of the parent
270 * device this device is linked to
271 */
272 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
273 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200274 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
275 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
276 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
277 printk("\n");
278}
279
280static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
281{
282 printk("---- SAS EXPANDER PAGE 1 ------------\n");
283
284 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200285 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200286 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
287 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
288 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
289 printk("Owner Device Handle=0x%X\n",
290 le16_to_cpu(pg1->OwnerDevHandle));
291 printk("Attached Device Handle=0x%X\n",
292 le16_to_cpu(pg1->AttachedDevHandle));
293}
294#else
295#define mptsas_print_phy_data(phy_data) do { } while (0)
296#define mptsas_print_phy_pg0(pg0) do { } while (0)
297#define mptsas_print_phy_pg1(pg1) do { } while (0)
298#define mptsas_print_device_pg0(pg0) do { } while (0)
299#define mptsas_print_expander_pg1(pg1) do { } while (0)
300#endif
301
Christoph Hellwige3094442006-02-16 13:25:36 +0100302static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
303{
304 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
305 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
306}
307
308static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
309{
310 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
311 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
312}
313
Moore, Erice6b2d762006-03-14 09:14:24 -0700314/*
315 * mptsas_find_portinfo_by_handle
316 *
317 * This function should be called with the sas_topology_mutex already held
318 */
319static struct mptsas_portinfo *
320mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
321{
322 struct mptsas_portinfo *port_info, *rc=NULL;
323 int i;
324
325 list_for_each_entry(port_info, &ioc->sas_topology, list)
326 for (i = 0; i < port_info->num_phys; i++)
327 if (port_info->phy_info[i].identify.handle == handle) {
328 rc = port_info;
329 goto out;
330 }
331 out:
332 return rc;
333}
334
Moore, Ericbd23e942006-04-17 12:43:04 -0600335/*
336 * Returns true if there is a scsi end device
337 */
338static inline int
339mptsas_is_end_device(struct mptsas_devinfo * attached)
340{
Eric Moore547f9a22006-06-27 14:42:12 -0600341 if ((attached->sas_address) &&
Moore, Ericbd23e942006-04-17 12:43:04 -0600342 (attached->device_info &
343 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
344 ((attached->device_info &
345 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
346 (attached->device_info &
347 MPI_SAS_DEVICE_INFO_STP_TARGET) |
348 (attached->device_info &
349 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
350 return 1;
351 else
352 return 0;
353}
354
Eric Moore547f9a22006-06-27 14:42:12 -0600355/* no mutex */
Eric Moore376ac832006-06-29 17:36:26 -0600356static void
Eric Moore547f9a22006-06-27 14:42:12 -0600357mptsas_port_delete(struct mptsas_portinfo_details * port_details)
358{
359 struct mptsas_portinfo *port_info;
360 struct mptsas_phyinfo *phy_info;
361 u8 i;
362
363 if (!port_details)
364 return;
365
366 port_info = port_details->port_info;
367 phy_info = port_info->phy_info;
368
Eric Mooredc22f162006-07-06 11:23:14 -0600369 dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
Eric Mooref99be432007-01-04 20:46:54 -0700370 "bitmask=0x%016llX\n", __FUNCTION__, port_details,
371 port_details->num_phys, (unsigned long long)
372 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600373
374 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
375 if(phy_info->port_details != port_details)
376 continue;
377 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
378 phy_info->port_details = NULL;
379 }
380 kfree(port_details);
381}
382
383static inline struct sas_rphy *
384mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
385{
386 if (phy_info->port_details)
387 return phy_info->port_details->rphy;
388 else
389 return NULL;
390}
391
392static inline void
393mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
394{
395 if (phy_info->port_details) {
396 phy_info->port_details->rphy = rphy;
397 dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
398 }
399
400#ifdef MPT_DEBUG_SAS_WIDE
401 if (rphy) {
402 dev_printk(KERN_DEBUG, &rphy->dev, "add:");
403 printk("rphy=%p release=%p\n",
404 rphy, rphy->dev.release);
405 }
406#endif
407}
408
409static inline struct sas_port *
410mptsas_get_port(struct mptsas_phyinfo *phy_info)
411{
412 if (phy_info->port_details)
413 return phy_info->port_details->port;
414 else
415 return NULL;
416}
417
418static inline void
419mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port)
420{
421 if (phy_info->port_details)
422 phy_info->port_details->port = port;
423
424#ifdef MPT_DEBUG_SAS_WIDE
425 if (port) {
426 dev_printk(KERN_DEBUG, &port->dev, "add: ");
427 printk("port=%p release=%p\n",
428 port, port->dev.release);
429 }
430#endif
431}
432
433static inline struct scsi_target *
434mptsas_get_starget(struct mptsas_phyinfo *phy_info)
435{
436 if (phy_info->port_details)
437 return phy_info->port_details->starget;
438 else
439 return NULL;
440}
441
442static inline void
443mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
444starget)
445{
446 if (phy_info->port_details)
447 phy_info->port_details->starget = starget;
448}
449
450
451/*
452 * mptsas_setup_wide_ports
453 *
454 * Updates for new and existing narrow/wide port configuration
455 * in the sas_topology
456 */
Eric Moore376ac832006-06-29 17:36:26 -0600457static void
Eric Moore547f9a22006-06-27 14:42:12 -0600458mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
459{
460 struct mptsas_portinfo_details * port_details;
461 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
462 u64 sas_address;
463 int i, j;
464
465 mutex_lock(&ioc->sas_topology_mutex);
466
467 phy_info = port_info->phy_info;
468 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
469 if (phy_info->attached.handle)
470 continue;
471 port_details = phy_info->port_details;
472 if (!port_details)
473 continue;
474 if (port_details->num_phys < 2)
475 continue;
476 /*
477 * Removing a phy from a port, letting the last
478 * phy be removed by firmware events.
479 */
480 dsaswideprintk((KERN_DEBUG
Eric Mooredc22f162006-07-06 11:23:14 -0600481 "%s: [%p]: deleting phy = %d\n",
482 __FUNCTION__, port_details, i));
Eric Moore547f9a22006-06-27 14:42:12 -0600483 port_details->num_phys--;
484 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
485 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
486 sas_port_delete_phy(port_details->port, phy_info->phy);
487 phy_info->port_details = NULL;
488 }
489
490 /*
491 * Populate and refresh the tree
492 */
493 phy_info = port_info->phy_info;
494 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
495 sas_address = phy_info->attached.sas_address;
496 dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
Eric Mooref99be432007-01-04 20:46:54 -0700497 i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600498 if (!sas_address)
499 continue;
500 port_details = phy_info->port_details;
501 /*
502 * Forming a port
503 */
504 if (!port_details) {
505 port_details = kzalloc(sizeof(*port_details),
506 GFP_KERNEL);
507 if (!port_details)
508 goto out;
509 port_details->num_phys = 1;
510 port_details->port_info = port_info;
Eric Moore547f9a22006-06-27 14:42:12 -0600511 if (phy_info->phy_id < 64 )
512 port_details->phy_bitmask |=
513 (1 << phy_info->phy_id);
514 phy_info->sas_port_add_phy=1;
515 dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
Eric Mooref99be432007-01-04 20:46:54 -0700516 "phy_id=%d sas_address=0x%018llX\n",
517 i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600518 phy_info->port_details = port_details;
519 }
520
521 if (i == port_info->num_phys - 1)
522 continue;
523 phy_info_cmp = &port_info->phy_info[i + 1];
524 for (j = i + 1 ; j < port_info->num_phys ; j++,
525 phy_info_cmp++) {
526 if (!phy_info_cmp->attached.sas_address)
527 continue;
528 if (sas_address != phy_info_cmp->attached.sas_address)
529 continue;
530 if (phy_info_cmp->port_details == port_details )
531 continue;
532 dsaswideprintk((KERN_DEBUG
Eric Mooref99be432007-01-04 20:46:54 -0700533 "\t\tphy_id=%d sas_address=0x%018llX\n",
534 j, (unsigned long long)
535 phy_info_cmp->attached.sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600536 if (phy_info_cmp->port_details) {
537 port_details->rphy =
538 mptsas_get_rphy(phy_info_cmp);
539 port_details->port =
540 mptsas_get_port(phy_info_cmp);
541 port_details->starget =
542 mptsas_get_starget(phy_info_cmp);
Eric Moore547f9a22006-06-27 14:42:12 -0600543 port_details->num_phys =
544 phy_info_cmp->port_details->num_phys;
Eric Moore547f9a22006-06-27 14:42:12 -0600545 if (!phy_info_cmp->port_details->num_phys)
546 kfree(phy_info_cmp->port_details);
547 } else
548 phy_info_cmp->sas_port_add_phy=1;
549 /*
550 * Adding a phy to a port
551 */
552 phy_info_cmp->port_details = port_details;
553 if (phy_info_cmp->phy_id < 64 )
554 port_details->phy_bitmask |=
555 (1 << phy_info_cmp->phy_id);
556 port_details->num_phys++;
557 }
558 }
559
560 out:
561
562#ifdef MPT_DEBUG_SAS_WIDE
563 for (i = 0; i < port_info->num_phys; i++) {
564 port_details = port_info->phy_info[i].port_details;
565 if (!port_details)
566 continue;
567 dsaswideprintk((KERN_DEBUG
Eric Mooref99be432007-01-04 20:46:54 -0700568 "%s: [%p]: phy_id=%02d num_phys=%02d "
569 "bitmask=0x%016llX\n", __FUNCTION__,
570 port_details, i, port_details->num_phys,
571 (unsigned long long)port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600572 dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
573 port_details->port, port_details->rphy));
574 }
575 dsaswideprintk((KERN_DEBUG"\n"));
576#endif
577 mutex_unlock(&ioc->sas_topology_mutex);
578}
579
Eric Mooredf9e0622007-01-29 09:46:21 -0700580/**
581 * csmisas_find_vtarget
582 *
583 * @ioc
584 * @volume_id
585 * @volume_bus
586 *
587 **/
588static VirtTarget *
589mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
Eric Moore547f9a22006-06-27 14:42:12 -0600590{
Eric Mooredf9e0622007-01-29 09:46:21 -0700591 struct scsi_device *sdev;
592 VirtDevice *vdev;
593 VirtTarget *vtarget = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -0600594
Eric Mooredf9e0622007-01-29 09:46:21 -0700595 shost_for_each_device(sdev, ioc->sh) {
596 if ((vdev = sdev->hostdata) == NULL)
597 continue;
598 if (vdev->vtarget->id == id &&
599 vdev->vtarget->channel == channel)
600 vtarget = vdev->vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -0600601 }
Eric Mooredf9e0622007-01-29 09:46:21 -0700602 return vtarget;
603}
604
605/**
606 * mptsas_target_reset
607 *
608 * Issues TARGET_RESET to end device using handshaking method
609 *
610 * @ioc
611 * @channel
612 * @id
613 *
614 * Returns (1) success
615 * (0) failure
616 *
617 **/
618static int
619mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
620{
621 MPT_FRAME_HDR *mf;
622 SCSITaskMgmt_t *pScsiTm;
623
624 if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
625 dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
626 ioc->name,__FUNCTION__, __LINE__));
627 return 0;
628 }
629
630 /* Format the Request
631 */
632 pScsiTm = (SCSITaskMgmt_t *) mf;
633 memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
634 pScsiTm->TargetID = id;
635 pScsiTm->Bus = channel;
636 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
637 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
638 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
639
640 DBG_DUMP_TM_REQUEST_FRAME(mf);
641
642 if (mpt_send_handshake_request(ioc->TaskCtx, ioc,
643 sizeof(SCSITaskMgmt_t), (u32 *)mf, NO_SLEEP)) {
644 mpt_free_msg_frame(ioc, mf);
645 dfailprintk((MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n",
646 ioc->name,__FUNCTION__, __LINE__));
647 return 0;
648 }
649
650 return 1;
651}
652
653/**
654 * mptsas_target_reset_queue
655 *
656 * Receive request for TARGET_RESET after recieving an firmware
657 * event NOT_RESPONDING_EVENT, then put command in link list
658 * and queue if task_queue already in use.
659 *
660 * @ioc
661 * @sas_event_data
662 *
663 **/
664static void
665mptsas_target_reset_queue(MPT_ADAPTER *ioc,
666 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
667{
668 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
669 VirtTarget *vtarget = NULL;
670 struct mptsas_target_reset_event *target_reset_list;
671 u8 id, channel;
672
673 id = sas_event_data->TargetID;
674 channel = sas_event_data->Bus;
675
676 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
677 return;
678
679 vtarget->deleted = 1; /* block IO */
680
681 target_reset_list = kzalloc(sizeof(*target_reset_list),
682 GFP_ATOMIC);
683 if (!target_reset_list) {
684 dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
685 ioc->name,__FUNCTION__, __LINE__));
686 return;
687 }
688
689 memcpy(&target_reset_list->sas_event_data, sas_event_data,
690 sizeof(*sas_event_data));
691 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
692
693 if (hd->resetPending)
694 return;
695
696 if (mptsas_target_reset(ioc, channel, id)) {
697 target_reset_list->target_reset_issued = 1;
698 hd->resetPending = 1;
699 }
700}
701
702/**
703 * mptsas_dev_reset_complete
704 *
705 * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
706 * enable work queue to finish off removing device from upper layers.
707 * then send next TARGET_RESET in the queue.
708 *
709 * @ioc
710 *
711 **/
712static void
713mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
714{
715 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
716 struct list_head *head = &hd->target_reset_list;
717 struct mptsas_target_reset_event *target_reset_list;
718 struct mptsas_hotplug_event *ev;
719 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
720 u8 id, channel;
721 __le64 sas_address;
722
723 if (list_empty(head))
724 return;
725
726 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list);
727
728 sas_event_data = &target_reset_list->sas_event_data;
729 id = sas_event_data->TargetID;
730 channel = sas_event_data->Bus;
731 hd->resetPending = 0;
732
733 /*
734 * retry target reset
735 */
736 if (!target_reset_list->target_reset_issued) {
737 if (mptsas_target_reset(ioc, channel, id)) {
738 target_reset_list->target_reset_issued = 1;
739 hd->resetPending = 1;
740 }
741 return;
742 }
743
744 /*
745 * enable work queue to remove device from upper layers
746 */
747 list_del(&target_reset_list->list);
748
749 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
750 if (!ev) {
751 dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
752 ioc->name,__FUNCTION__, __LINE__));
753 return;
754 }
755
756 INIT_WORK(&ev->work, mptsas_hotplug_work);
757 ev->ioc = ioc;
758 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
759 ev->parent_handle =
760 le16_to_cpu(sas_event_data->ParentDevHandle);
761 ev->channel = channel;
762 ev->id =id;
763 ev->phy_id = sas_event_data->PhyNum;
764 memcpy(&sas_address, &sas_event_data->SASAddress,
765 sizeof(__le64));
766 ev->sas_address = le64_to_cpu(sas_address);
767 ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
768 ev->event_type = MPTSAS_DEL_DEVICE;
769 schedule_work(&ev->work);
770 kfree(target_reset_list);
771
772 /*
773 * issue target reset to next device in the queue
774 */
775
776 head = &hd->target_reset_list;
777 if (list_empty(head))
778 return;
779
780 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
781 list);
782
783 sas_event_data = &target_reset_list->sas_event_data;
784 id = sas_event_data->TargetID;
785 channel = sas_event_data->Bus;
786
787 if (mptsas_target_reset(ioc, channel, id)) {
788 target_reset_list->target_reset_issued = 1;
789 hd->resetPending = 1;
790 }
791}
792
793/**
794 * mptsas_taskmgmt_complete
795 *
796 * @ioc
797 * @mf
798 * @mr
799 *
800 **/
801static int
802mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
803{
804 mptsas_dev_reset_complete(ioc);
805 return mptscsih_taskmgmt_complete(ioc, mf, mr);
806}
807
808/**
809 * mptscsih_ioc_reset
810 *
811 * @ioc
812 * @reset_phase
813 *
814 **/
815static int
816mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
817{
818 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
819 struct mptsas_target_reset_event *target_reset_list, *n;
820 int rc;
821
822 rc = mptscsih_ioc_reset(ioc, reset_phase);
823
824 if (ioc->bus_type != SAS)
825 goto out;
826
827 if (reset_phase != MPT_IOC_POST_RESET)
828 goto out;
829
830 if (!hd || !hd->ioc)
831 goto out;
832
833 if (list_empty(&hd->target_reset_list))
834 goto out;
835
836 /* flush the target_reset_list */
837 list_for_each_entry_safe(target_reset_list, n,
838 &hd->target_reset_list, list) {
839 list_del(&target_reset_list->list);
840 kfree(target_reset_list);
841 }
842
843 out:
844 return rc;
Eric Moore547f9a22006-06-27 14:42:12 -0600845}
846
Christoph Hellwige3094442006-02-16 13:25:36 +0100847static int
Moore, Eric52435432006-03-14 09:14:15 -0700848mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
Christoph Hellwige3094442006-02-16 13:25:36 +0100849 u32 form, u32 form_specific)
850{
851 ConfigExtendedPageHeader_t hdr;
852 CONFIGPARMS cfg;
853 SasEnclosurePage0_t *buffer;
854 dma_addr_t dma_handle;
855 int error;
856 __le64 le_identifier;
857
858 memset(&hdr, 0, sizeof(hdr));
859 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
860 hdr.PageNumber = 0;
861 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
862 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
863
864 cfg.cfghdr.ehdr = &hdr;
865 cfg.physAddr = -1;
866 cfg.pageAddr = form + form_specific;
867 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
868 cfg.dir = 0; /* read */
869 cfg.timeout = 10;
870
871 error = mpt_config(ioc, &cfg);
872 if (error)
873 goto out;
874 if (!hdr.ExtPageLength) {
875 error = -ENXIO;
876 goto out;
877 }
878
879 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
880 &dma_handle);
881 if (!buffer) {
882 error = -ENOMEM;
883 goto out;
884 }
885
886 cfg.physAddr = dma_handle;
887 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
888
889 error = mpt_config(ioc, &cfg);
890 if (error)
891 goto out_free_consistent;
892
893 /* save config data */
894 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
895 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
896 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
897 enclosure->flags = le16_to_cpu(buffer->Flags);
898 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
899 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
900 enclosure->start_id = buffer->StartTargetID;
901 enclosure->start_channel = buffer->StartBus;
902 enclosure->sep_id = buffer->SEPTargetID;
903 enclosure->sep_channel = buffer->SEPBus;
904
905 out_free_consistent:
906 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
907 buffer, dma_handle);
908 out:
909 return error;
910}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200911
James Bottomleyf013db32006-03-18 14:54:36 -0600912static int
913mptsas_slave_configure(struct scsi_device *sdev)
914{
Moore, Eric3c0c25b2006-04-13 16:08:17 -0600915
James Bottomleye8bf3942006-07-11 17:49:34 -0400916 if (sdev->channel == MPTSAS_RAID_CHANNEL)
917 goto out;
James Bottomleyf013db32006-03-18 14:54:36 -0600918
James Bottomleye8bf3942006-07-11 17:49:34 -0400919 sas_read_port_mode_page(sdev);
920
921 out:
James Bottomleyf013db32006-03-18 14:54:36 -0600922 return mptscsih_slave_configure(sdev);
923}
924
Eric Moore547f9a22006-06-27 14:42:12 -0600925static int
926mptsas_target_alloc(struct scsi_target *starget)
927{
928 struct Scsi_Host *host = dev_to_shost(&starget->dev);
929 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
930 VirtTarget *vtarget;
Eric Moore793955f2007-01-29 09:42:20 -0700931 u8 id, channel;
Eric Moore547f9a22006-06-27 14:42:12 -0600932 struct sas_rphy *rphy;
933 struct mptsas_portinfo *p;
934 int i;
935
936 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
937 if (!vtarget)
938 return -ENOMEM;
939
940 vtarget->starget = starget;
941 vtarget->ioc_id = hd->ioc->id;
Eric Moore793955f2007-01-29 09:42:20 -0700942 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
943 id = starget->id;
Eric Moore547f9a22006-06-27 14:42:12 -0600944 channel = 0;
945
Eric Moore793955f2007-01-29 09:42:20 -0700946 /*
947 * RAID volumes placed beyond the last expected port.
948 */
949 if (starget->channel == MPTSAS_RAID_CHANNEL) {
950 for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
951 if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
952 channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
Eric Moore547f9a22006-06-27 14:42:12 -0600953 goto out;
Eric Moore793955f2007-01-29 09:42:20 -0700954 }
Eric Moore547f9a22006-06-27 14:42:12 -0600955
956 rphy = dev_to_rphy(starget->dev.parent);
957 mutex_lock(&hd->ioc->sas_topology_mutex);
958 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
959 for (i = 0; i < p->num_phys; i++) {
960 if (p->phy_info[i].attached.sas_address !=
961 rphy->identify.sas_address)
962 continue;
Eric Moore793955f2007-01-29 09:42:20 -0700963 id = p->phy_info[i].attached.id;
Eric Moore547f9a22006-06-27 14:42:12 -0600964 channel = p->phy_info[i].attached.channel;
965 mptsas_set_starget(&p->phy_info[i], starget);
966
967 /*
968 * Exposing hidden raid components
969 */
Eric Moore793955f2007-01-29 09:42:20 -0700970 if (mptscsih_is_phys_disk(hd->ioc, channel, id)) {
971 id = mptscsih_raid_id_to_num(hd->ioc,
972 channel, id);
Eric Moore547f9a22006-06-27 14:42:12 -0600973 vtarget->tflags |=
974 MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Mooreb506ade2007-01-29 09:45:37 -0700975 p->phy_info[i].attached.phys_disk_num = id;
Eric Moore547f9a22006-06-27 14:42:12 -0600976 }
977 mutex_unlock(&hd->ioc->sas_topology_mutex);
978 goto out;
979 }
980 }
981 mutex_unlock(&hd->ioc->sas_topology_mutex);
982
983 kfree(vtarget);
984 return -ENXIO;
985
986 out:
Eric Moore793955f2007-01-29 09:42:20 -0700987 vtarget->id = id;
988 vtarget->channel = channel;
Eric Moore547f9a22006-06-27 14:42:12 -0600989 starget->hostdata = vtarget;
990 return 0;
991}
992
993static void
994mptsas_target_destroy(struct scsi_target *starget)
995{
996 struct Scsi_Host *host = dev_to_shost(&starget->dev);
997 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
998 struct sas_rphy *rphy;
999 struct mptsas_portinfo *p;
1000 int i;
1001
1002 if (!starget->hostdata)
1003 return;
1004
James Bottomleye8bf3942006-07-11 17:49:34 -04001005 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -06001006 goto out;
1007
1008 rphy = dev_to_rphy(starget->dev.parent);
1009 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
1010 for (i = 0; i < p->num_phys; i++) {
1011 if (p->phy_info[i].attached.sas_address !=
1012 rphy->identify.sas_address)
1013 continue;
1014 mptsas_set_starget(&p->phy_info[i], NULL);
1015 goto out;
1016 }
1017 }
1018
1019 out:
1020 kfree(starget->hostdata);
1021 starget->hostdata = NULL;
1022}
1023
1024
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001025static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -07001026mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001027{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -07001028 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001029 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1030 struct sas_rphy *rphy;
1031 struct mptsas_portinfo *p;
1032 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -07001033 struct scsi_target *starget;
Eric Moore547f9a22006-06-27 14:42:12 -06001034 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001035
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001036 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001037 if (!vdev) {
Eric Moore547f9a22006-06-27 14:42:12 -06001038 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001039 hd->ioc->name, sizeof(VirtDevice));
1040 return -ENOMEM;
1041 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -07001042 starget = scsi_target(sdev);
Eric Moore547f9a22006-06-27 14:42:12 -06001043 vdev->vtarget = starget->hostdata;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001044
James Bottomleye8bf3942006-07-11 17:49:34 -04001045 if (sdev->channel == MPTSAS_RAID_CHANNEL)
Moore, Eric816aa902006-01-13 16:25:20 -07001046 goto out;
Moore, Eric816aa902006-01-13 16:25:20 -07001047
Moore, Eric Deanc7c82982005-11-16 18:54:25 -07001048 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001049 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001050 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
1051 for (i = 0; i < p->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06001052 if (p->phy_info[i].attached.sas_address !=
1053 rphy->identify.sas_address)
1054 continue;
1055 vdev->lun = sdev->lun;
1056 /*
1057 * Exposing hidden raid components
1058 */
1059 if (mptscsih_is_phys_disk(hd->ioc,
Eric Moore793955f2007-01-29 09:42:20 -07001060 p->phy_info[i].attached.channel,
1061 p->phy_info[i].attached.id))
Eric Moore547f9a22006-06-27 14:42:12 -06001062 sdev->no_uld_attach = 1;
1063 mutex_unlock(&hd->ioc->sas_topology_mutex);
1064 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001065 }
1066 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001067 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001068
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001069 kfree(vdev);
Christoph Hellwig23f236e2006-01-30 19:00:43 +01001070 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001071
1072 out:
Eric Moore547f9a22006-06-27 14:42:12 -06001073 vdev->vtarget->num_luns++;
1074 sdev->hostdata = vdev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001075 return 0;
1076}
1077
Eric Moore547f9a22006-06-27 14:42:12 -06001078static int
1079mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001080{
Eric Moore547f9a22006-06-27 14:42:12 -06001081 VirtDevice *vdev = SCpnt->device->hostdata;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001082
Eric Moore793955f2007-01-29 09:42:20 -07001083 if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) {
Eric Moore547f9a22006-06-27 14:42:12 -06001084 SCpnt->result = DID_NO_CONNECT << 16;
1085 done(SCpnt);
1086 return 0;
Moore, Eric7d3eecf2006-01-25 18:05:12 -07001087 }
Eric Moore547f9a22006-06-27 14:42:12 -06001088
Eric Moore793955f2007-01-29 09:42:20 -07001089// scsi_print_command(SCpnt);
1090
Eric Moore547f9a22006-06-27 14:42:12 -06001091 return mptscsih_qcmd(SCpnt,done);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001092}
1093
Eric Moore547f9a22006-06-27 14:42:12 -06001094
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001095static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -07001096 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001097 .proc_name = "mptsas",
1098 .proc_info = mptscsih_proc_info,
1099 .name = "MPT SPI Host",
1100 .info = mptscsih_info,
Eric Moore547f9a22006-06-27 14:42:12 -06001101 .queuecommand = mptsas_qcmd,
1102 .target_alloc = mptsas_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001103 .slave_alloc = mptsas_slave_alloc,
James Bottomleyf013db32006-03-18 14:54:36 -06001104 .slave_configure = mptsas_slave_configure,
Eric Moore547f9a22006-06-27 14:42:12 -06001105 .target_destroy = mptsas_target_destroy,
1106 .slave_destroy = mptscsih_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001107 .change_queue_depth = mptscsih_change_queue_depth,
1108 .eh_abort_handler = mptscsih_abort,
1109 .eh_device_reset_handler = mptscsih_dev_reset,
1110 .eh_bus_reset_handler = mptscsih_bus_reset,
1111 .eh_host_reset_handler = mptscsih_host_reset,
1112 .bios_param = mptscsih_bios_param,
1113 .can_queue = MPT_FC_CAN_QUEUE,
1114 .this_id = -1,
1115 .sg_tablesize = MPT_SCSI_SG_DEPTH,
1116 .max_sectors = 8192,
1117 .cmd_per_lun = 7,
1118 .use_clustering = ENABLE_CLUSTERING,
1119};
1120
Christoph Hellwigb5141122005-10-28 22:07:41 +02001121static int mptsas_get_linkerrors(struct sas_phy *phy)
1122{
1123 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1124 ConfigExtendedPageHeader_t hdr;
1125 CONFIGPARMS cfg;
1126 SasPhyPage1_t *buffer;
1127 dma_addr_t dma_handle;
1128 int error;
1129
James Bottomleyf4ad7b52006-08-25 13:48:18 -05001130 /* FIXME: only have link errors on local phys */
1131 if (!scsi_is_sas_phy_local(phy))
1132 return -EINVAL;
1133
Christoph Hellwigb5141122005-10-28 22:07:41 +02001134 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
1135 hdr.ExtPageLength = 0;
1136 hdr.PageNumber = 1 /* page number 1*/;
1137 hdr.Reserved1 = 0;
1138 hdr.Reserved2 = 0;
1139 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1140 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1141
1142 cfg.cfghdr.ehdr = &hdr;
1143 cfg.physAddr = -1;
1144 cfg.pageAddr = phy->identify.phy_identifier;
1145 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1146 cfg.dir = 0; /* read */
1147 cfg.timeout = 10;
1148
1149 error = mpt_config(ioc, &cfg);
1150 if (error)
1151 return error;
1152 if (!hdr.ExtPageLength)
1153 return -ENXIO;
1154
1155 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1156 &dma_handle);
1157 if (!buffer)
1158 return -ENOMEM;
1159
1160 cfg.physAddr = dma_handle;
1161 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1162
1163 error = mpt_config(ioc, &cfg);
1164 if (error)
1165 goto out_free_consistent;
1166
1167 mptsas_print_phy_pg1(buffer);
1168
1169 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
1170 phy->running_disparity_error_count =
1171 le32_to_cpu(buffer->RunningDisparityErrorCount);
1172 phy->loss_of_dword_sync_count =
1173 le32_to_cpu(buffer->LossDwordSynchCount);
1174 phy->phy_reset_problem_count =
1175 le32_to_cpu(buffer->PhyResetProblemCount);
1176
1177 out_free_consistent:
1178 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1179 buffer, dma_handle);
1180 return error;
1181}
1182
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001183static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
1184 MPT_FRAME_HDR *reply)
1185{
1186 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
1187 if (reply != NULL) {
1188 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
1189 memcpy(ioc->sas_mgmt.reply, reply,
1190 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
1191 }
1192 complete(&ioc->sas_mgmt.done);
1193 return 1;
1194}
1195
1196static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
1197{
1198 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1199 SasIoUnitControlRequest_t *req;
1200 SasIoUnitControlReply_t *reply;
1201 MPT_FRAME_HDR *mf;
1202 MPIHeader_t *hdr;
1203 unsigned long timeleft;
1204 int error = -ERESTARTSYS;
1205
James Bottomleyf4ad7b52006-08-25 13:48:18 -05001206 /* FIXME: fusion doesn't allow non-local phy reset */
1207 if (!scsi_is_sas_phy_local(phy))
1208 return -EINVAL;
1209
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001210 /* not implemented for expanders */
1211 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
1212 return -ENXIO;
1213
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001214 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001215 goto out;
1216
1217 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1218 if (!mf) {
1219 error = -ENOMEM;
1220 goto out_unlock;
1221 }
1222
1223 hdr = (MPIHeader_t *) mf;
1224 req = (SasIoUnitControlRequest_t *)mf;
1225 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
1226 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
1227 req->MsgContext = hdr->MsgContext;
1228 req->Operation = hard_reset ?
1229 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
1230 req->PhyNum = phy->identify.phy_identifier;
1231
1232 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1233
1234 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
1235 10 * HZ);
1236 if (!timeleft) {
1237 /* On timeout reset the board */
1238 mpt_free_msg_frame(ioc, mf);
1239 mpt_HardResetHandler(ioc, CAN_SLEEP);
1240 error = -ETIMEDOUT;
1241 goto out_unlock;
1242 }
1243
1244 /* a reply frame is expected */
1245 if ((ioc->sas_mgmt.status &
1246 MPT_IOCTL_STATUS_RF_VALID) == 0) {
1247 error = -ENXIO;
1248 goto out_unlock;
1249 }
1250
1251 /* process the completed Reply Message Frame */
1252 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
1253 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
1254 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
1255 __FUNCTION__,
1256 reply->IOCStatus,
1257 reply->IOCLogInfo);
1258 error = -ENXIO;
1259 goto out_unlock;
1260 }
1261
1262 error = 0;
1263
1264 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001265 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001266 out:
1267 return error;
1268}
Christoph Hellwigb5141122005-10-28 22:07:41 +02001269
Christoph Hellwige3094442006-02-16 13:25:36 +01001270static int
1271mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1272{
1273 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1274 int i, error;
1275 struct mptsas_portinfo *p;
1276 struct mptsas_enclosure enclosure_info;
1277 u64 enclosure_handle;
1278
1279 mutex_lock(&ioc->sas_topology_mutex);
1280 list_for_each_entry(p, &ioc->sas_topology, list) {
1281 for (i = 0; i < p->num_phys; i++) {
1282 if (p->phy_info[i].attached.sas_address ==
1283 rphy->identify.sas_address) {
1284 enclosure_handle = p->phy_info[i].
1285 attached.handle_enclosure;
1286 goto found_info;
1287 }
1288 }
1289 }
1290 mutex_unlock(&ioc->sas_topology_mutex);
1291 return -ENXIO;
1292
1293 found_info:
1294 mutex_unlock(&ioc->sas_topology_mutex);
1295 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -07001296 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +01001297 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1298 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1299 if (!error)
1300 *identifier = enclosure_info.enclosure_logical_id;
1301 return error;
1302}
1303
1304static int
1305mptsas_get_bay_identifier(struct sas_rphy *rphy)
1306{
1307 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1308 struct mptsas_portinfo *p;
1309 int i, rc;
1310
1311 mutex_lock(&ioc->sas_topology_mutex);
1312 list_for_each_entry(p, &ioc->sas_topology, list) {
1313 for (i = 0; i < p->num_phys; i++) {
1314 if (p->phy_info[i].attached.sas_address ==
1315 rphy->identify.sas_address) {
1316 rc = p->phy_info[i].attached.slot;
1317 goto out;
1318 }
1319 }
1320 }
1321 rc = -ENXIO;
1322 out:
1323 mutex_unlock(&ioc->sas_topology_mutex);
1324 return rc;
1325}
1326
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001327static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +02001328 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +01001329 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1330 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001331 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001332};
1333
1334static struct scsi_transport_template *mptsas_transport_template;
1335
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001336static int
1337mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1338{
1339 ConfigExtendedPageHeader_t hdr;
1340 CONFIGPARMS cfg;
1341 SasIOUnitPage0_t *buffer;
1342 dma_addr_t dma_handle;
1343 int error, i;
1344
1345 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1346 hdr.ExtPageLength = 0;
1347 hdr.PageNumber = 0;
1348 hdr.Reserved1 = 0;
1349 hdr.Reserved2 = 0;
1350 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1351 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1352
1353 cfg.cfghdr.ehdr = &hdr;
1354 cfg.physAddr = -1;
1355 cfg.pageAddr = 0;
1356 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1357 cfg.dir = 0; /* read */
1358 cfg.timeout = 10;
1359
1360 error = mpt_config(ioc, &cfg);
1361 if (error)
1362 goto out;
1363 if (!hdr.ExtPageLength) {
1364 error = -ENXIO;
1365 goto out;
1366 }
1367
1368 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1369 &dma_handle);
1370 if (!buffer) {
1371 error = -ENOMEM;
1372 goto out;
1373 }
1374
1375 cfg.physAddr = dma_handle;
1376 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1377
1378 error = mpt_config(ioc, &cfg);
1379 if (error)
1380 goto out_free_consistent;
1381
1382 port_info->num_phys = buffer->NumPhys;
1383 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001384 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001385 if (!port_info->phy_info) {
1386 error = -ENOMEM;
1387 goto out_free_consistent;
1388 }
1389
Moore, Ericdb9c9172006-03-14 09:14:18 -07001390 if (port_info->num_phys)
1391 port_info->handle =
1392 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001393 for (i = 0; i < port_info->num_phys; i++) {
1394 mptsas_print_phy_data(&buffer->PhyData[i]);
1395 port_info->phy_info[i].phy_id = i;
1396 port_info->phy_info[i].port_id =
1397 buffer->PhyData[i].Port;
1398 port_info->phy_info[i].negotiated_link_rate =
1399 buffer->PhyData[i].NegotiatedLinkRate;
Eric Moore547f9a22006-06-27 14:42:12 -06001400 port_info->phy_info[i].portinfo = port_info;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001401 }
1402
1403 out_free_consistent:
1404 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1405 buffer, dma_handle);
1406 out:
1407 return error;
1408}
1409
1410static int
1411mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1412 u32 form, u32 form_specific)
1413{
1414 ConfigExtendedPageHeader_t hdr;
1415 CONFIGPARMS cfg;
1416 SasPhyPage0_t *buffer;
1417 dma_addr_t dma_handle;
1418 int error;
1419
1420 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1421 hdr.ExtPageLength = 0;
1422 hdr.PageNumber = 0;
1423 hdr.Reserved1 = 0;
1424 hdr.Reserved2 = 0;
1425 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1426 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1427
1428 cfg.cfghdr.ehdr = &hdr;
1429 cfg.dir = 0; /* read */
1430 cfg.timeout = 10;
1431
1432 /* Get Phy Pg 0 for each Phy. */
1433 cfg.physAddr = -1;
1434 cfg.pageAddr = form + form_specific;
1435 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1436
1437 error = mpt_config(ioc, &cfg);
1438 if (error)
1439 goto out;
1440
1441 if (!hdr.ExtPageLength) {
1442 error = -ENXIO;
1443 goto out;
1444 }
1445
1446 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1447 &dma_handle);
1448 if (!buffer) {
1449 error = -ENOMEM;
1450 goto out;
1451 }
1452
1453 cfg.physAddr = dma_handle;
1454 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1455
1456 error = mpt_config(ioc, &cfg);
1457 if (error)
1458 goto out_free_consistent;
1459
1460 mptsas_print_phy_pg0(buffer);
1461
1462 phy_info->hw_link_rate = buffer->HwLinkRate;
1463 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1464 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1465 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1466
1467 out_free_consistent:
1468 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1469 buffer, dma_handle);
1470 out:
1471 return error;
1472}
1473
1474static int
1475mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1476 u32 form, u32 form_specific)
1477{
1478 ConfigExtendedPageHeader_t hdr;
1479 CONFIGPARMS cfg;
1480 SasDevicePage0_t *buffer;
1481 dma_addr_t dma_handle;
1482 __le64 sas_address;
Moore, Ericbd23e942006-04-17 12:43:04 -06001483 int error=0;
1484
1485 if (ioc->sas_discovery_runtime &&
1486 mptsas_is_end_device(device_info))
1487 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001488
1489 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1490 hdr.ExtPageLength = 0;
1491 hdr.PageNumber = 0;
1492 hdr.Reserved1 = 0;
1493 hdr.Reserved2 = 0;
1494 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1495 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1496
1497 cfg.cfghdr.ehdr = &hdr;
1498 cfg.pageAddr = form + form_specific;
1499 cfg.physAddr = -1;
1500 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1501 cfg.dir = 0; /* read */
1502 cfg.timeout = 10;
1503
Moore, Ericdb9c9172006-03-14 09:14:18 -07001504 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001505 error = mpt_config(ioc, &cfg);
1506 if (error)
1507 goto out;
1508 if (!hdr.ExtPageLength) {
1509 error = -ENXIO;
1510 goto out;
1511 }
1512
1513 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1514 &dma_handle);
1515 if (!buffer) {
1516 error = -ENOMEM;
1517 goto out;
1518 }
1519
1520 cfg.physAddr = dma_handle;
1521 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1522
1523 error = mpt_config(ioc, &cfg);
1524 if (error)
1525 goto out_free_consistent;
1526
1527 mptsas_print_device_pg0(buffer);
1528
1529 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001530 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +01001531 device_info->handle_enclosure =
1532 le16_to_cpu(buffer->EnclosureHandle);
1533 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001534 device_info->phy_id = buffer->PhyNum;
1535 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001536 device_info->id = buffer->TargetID;
Eric Mooreb506ade2007-01-29 09:45:37 -07001537 device_info->phys_disk_num = ~0;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001538 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001539 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1540 device_info->sas_address = le64_to_cpu(sas_address);
1541 device_info->device_info =
1542 le32_to_cpu(buffer->DeviceInfo);
1543
1544 out_free_consistent:
1545 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1546 buffer, dma_handle);
1547 out:
1548 return error;
1549}
1550
1551static int
1552mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1553 u32 form, u32 form_specific)
1554{
1555 ConfigExtendedPageHeader_t hdr;
1556 CONFIGPARMS cfg;
1557 SasExpanderPage0_t *buffer;
1558 dma_addr_t dma_handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001559 int i, error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001560
1561 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1562 hdr.ExtPageLength = 0;
1563 hdr.PageNumber = 0;
1564 hdr.Reserved1 = 0;
1565 hdr.Reserved2 = 0;
1566 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1567 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1568
1569 cfg.cfghdr.ehdr = &hdr;
1570 cfg.physAddr = -1;
1571 cfg.pageAddr = form + form_specific;
1572 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1573 cfg.dir = 0; /* read */
1574 cfg.timeout = 10;
1575
Moore, Ericdb9c9172006-03-14 09:14:18 -07001576 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001577 error = mpt_config(ioc, &cfg);
1578 if (error)
1579 goto out;
1580
1581 if (!hdr.ExtPageLength) {
1582 error = -ENXIO;
1583 goto out;
1584 }
1585
1586 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1587 &dma_handle);
1588 if (!buffer) {
1589 error = -ENOMEM;
1590 goto out;
1591 }
1592
1593 cfg.physAddr = dma_handle;
1594 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1595
1596 error = mpt_config(ioc, &cfg);
1597 if (error)
1598 goto out_free_consistent;
1599
1600 /* save config data */
1601 port_info->num_phys = buffer->NumPhys;
1602 port_info->handle = le16_to_cpu(buffer->DevHandle);
1603 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001604 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001605 if (!port_info->phy_info) {
1606 error = -ENOMEM;
1607 goto out_free_consistent;
1608 }
1609
Eric Moore547f9a22006-06-27 14:42:12 -06001610 for (i = 0; i < port_info->num_phys; i++)
1611 port_info->phy_info[i].portinfo = port_info;
1612
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001613 out_free_consistent:
1614 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1615 buffer, dma_handle);
1616 out:
1617 return error;
1618}
1619
1620static int
1621mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1622 u32 form, u32 form_specific)
1623{
1624 ConfigExtendedPageHeader_t hdr;
1625 CONFIGPARMS cfg;
1626 SasExpanderPage1_t *buffer;
1627 dma_addr_t dma_handle;
Moore, Ericbd23e942006-04-17 12:43:04 -06001628 int error=0;
1629
1630 if (ioc->sas_discovery_runtime &&
1631 mptsas_is_end_device(&phy_info->attached))
1632 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001633
1634 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1635 hdr.ExtPageLength = 0;
1636 hdr.PageNumber = 1;
1637 hdr.Reserved1 = 0;
1638 hdr.Reserved2 = 0;
1639 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1640 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1641
1642 cfg.cfghdr.ehdr = &hdr;
1643 cfg.physAddr = -1;
1644 cfg.pageAddr = form + form_specific;
1645 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1646 cfg.dir = 0; /* read */
1647 cfg.timeout = 10;
1648
1649 error = mpt_config(ioc, &cfg);
1650 if (error)
1651 goto out;
1652
1653 if (!hdr.ExtPageLength) {
1654 error = -ENXIO;
1655 goto out;
1656 }
1657
1658 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1659 &dma_handle);
1660 if (!buffer) {
1661 error = -ENOMEM;
1662 goto out;
1663 }
1664
1665 cfg.physAddr = dma_handle;
1666 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1667
1668 error = mpt_config(ioc, &cfg);
1669 if (error)
1670 goto out_free_consistent;
1671
1672
1673 mptsas_print_expander_pg1(buffer);
1674
1675 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001676 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001677 phy_info->port_id = buffer->PhysicalPort;
1678 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1679 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1680 phy_info->hw_link_rate = buffer->HwLinkRate;
1681 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1682 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1683
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001684 out_free_consistent:
1685 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1686 buffer, dma_handle);
1687 out:
1688 return error;
1689}
1690
1691static void
1692mptsas_parse_device_info(struct sas_identify *identify,
1693 struct mptsas_devinfo *device_info)
1694{
1695 u16 protocols;
1696
1697 identify->sas_address = device_info->sas_address;
1698 identify->phy_identifier = device_info->phy_id;
1699
1700 /*
1701 * Fill in Phy Initiator Port Protocol.
1702 * Bits 6:3, more than one bit can be set, fall through cases.
1703 */
1704 protocols = device_info->device_info & 0x78;
1705 identify->initiator_port_protocols = 0;
1706 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1707 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1708 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1709 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1710 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1711 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1712 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1713 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1714
1715 /*
1716 * Fill in Phy Target Port Protocol.
1717 * Bits 10:7, more than one bit can be set, fall through cases.
1718 */
1719 protocols = device_info->device_info & 0x780;
1720 identify->target_port_protocols = 0;
1721 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1722 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1723 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1724 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1725 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1726 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1727 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1728 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1729
1730 /*
1731 * Fill in Attached device type.
1732 */
1733 switch (device_info->device_info &
1734 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1735 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1736 identify->device_type = SAS_PHY_UNUSED;
1737 break;
1738 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1739 identify->device_type = SAS_END_DEVICE;
1740 break;
1741 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1742 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1743 break;
1744 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1745 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1746 break;
1747 }
1748}
1749
1750static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001751 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001752{
Moore, Erice6b2d762006-03-14 09:14:24 -07001753 MPT_ADAPTER *ioc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001754 struct sas_phy *phy;
Eric Moore547f9a22006-06-27 14:42:12 -06001755 struct sas_port *port;
1756 int error = 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001757
Eric Moore547f9a22006-06-27 14:42:12 -06001758 if (!dev) {
1759 error = -ENODEV;
1760 goto out;
1761 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001762
1763 if (!phy_info->phy) {
1764 phy = sas_phy_alloc(dev, index);
Eric Moore547f9a22006-06-27 14:42:12 -06001765 if (!phy) {
1766 error = -ENOMEM;
1767 goto out;
1768 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001769 } else
1770 phy = phy_info->phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001771
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001772 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001773
1774 /*
1775 * Set Negotiated link rate.
1776 */
1777 switch (phy_info->negotiated_link_rate) {
1778 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001779 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001780 break;
1781 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001782 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001783 break;
1784 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001785 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001786 break;
1787 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001788 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001789 break;
1790 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1791 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1792 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001793 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001794 break;
1795 }
1796
1797 /*
1798 * Set Max hardware link rate.
1799 */
1800 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1801 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001802 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001803 break;
1804 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001805 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001806 break;
1807 default:
1808 break;
1809 }
1810
1811 /*
1812 * Set Max programmed link rate.
1813 */
1814 switch (phy_info->programmed_link_rate &
1815 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1816 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001817 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001818 break;
1819 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001820 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001821 break;
1822 default:
1823 break;
1824 }
1825
1826 /*
1827 * Set Min hardware link rate.
1828 */
1829 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1830 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001831 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001832 break;
1833 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001834 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001835 break;
1836 default:
1837 break;
1838 }
1839
1840 /*
1841 * Set Min programmed link rate.
1842 */
1843 switch (phy_info->programmed_link_rate &
1844 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1845 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001846 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001847 break;
1848 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001849 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001850 break;
1851 default:
1852 break;
1853 }
1854
Moore, Erice6b2d762006-03-14 09:14:24 -07001855 if (!phy_info->phy) {
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001856
Moore, Erice6b2d762006-03-14 09:14:24 -07001857 error = sas_phy_add(phy);
1858 if (error) {
1859 sas_phy_free(phy);
Eric Moore547f9a22006-06-27 14:42:12 -06001860 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001861 }
1862 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001863 }
1864
Eric Moore547f9a22006-06-27 14:42:12 -06001865 if (!phy_info->attached.handle ||
1866 !phy_info->port_details)
1867 goto out;
1868
1869 port = mptsas_get_port(phy_info);
1870 ioc = phy_to_ioc(phy_info->phy);
1871
1872 if (phy_info->sas_port_add_phy) {
1873
1874 if (!port) {
Eric Mooredc22f162006-07-06 11:23:14 -06001875 port = sas_port_alloc_num(dev);
Eric Moore547f9a22006-06-27 14:42:12 -06001876 if (!port) {
1877 error = -ENOMEM;
1878 goto out;
1879 }
1880 error = sas_port_add(port);
1881 if (error) {
1882 dfailprintk((MYIOC_s_ERR_FMT
1883 "%s: exit at line=%d\n", ioc->name,
1884 __FUNCTION__, __LINE__));
1885 goto out;
1886 }
1887 mptsas_set_port(phy_info, port);
Eric Mooredc22f162006-07-06 11:23:14 -06001888 dsaswideprintk((KERN_DEBUG
1889 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
1890 port, dev, port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06001891 }
1892 dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
1893 phy_info->phy_id));
1894 sas_port_add_phy(port, phy_info->phy);
1895 phy_info->sas_port_add_phy = 0;
1896 }
1897
1898 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
Moore, Erice6b2d762006-03-14 09:14:24 -07001899
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001900 struct sas_rphy *rphy;
James Bottomley2686de22006-06-30 12:54:02 -05001901 struct device *parent;
James Bottomleyf013db32006-03-18 14:54:36 -06001902 struct sas_identify identify;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001903
James Bottomley2686de22006-06-30 12:54:02 -05001904 parent = dev->parent->parent;
Moore, Erice6b2d762006-03-14 09:14:24 -07001905 /*
1906 * Let the hotplug_work thread handle processing
1907 * the adding/removing of devices that occur
1908 * after start of day.
1909 */
1910 if (ioc->sas_discovery_runtime &&
1911 mptsas_is_end_device(&phy_info->attached))
Eric Moore547f9a22006-06-27 14:42:12 -06001912 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001913
James Bottomleyf013db32006-03-18 14:54:36 -06001914 mptsas_parse_device_info(&identify, &phy_info->attached);
James Bottomley2686de22006-06-30 12:54:02 -05001915 if (scsi_is_host_device(parent)) {
1916 struct mptsas_portinfo *port_info;
1917 int i;
1918
1919 mutex_lock(&ioc->sas_topology_mutex);
1920 port_info = mptsas_find_portinfo_by_handle(ioc,
1921 ioc->handle);
1922 mutex_unlock(&ioc->sas_topology_mutex);
1923
1924 for (i = 0; i < port_info->num_phys; i++)
1925 if (port_info->phy_info[i].identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001926 identify.sas_address) {
1927 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001928 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001929 }
James Bottomley2686de22006-06-30 12:54:02 -05001930
1931 } else if (scsi_is_sas_rphy(parent)) {
1932 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
1933 if (identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001934 parent_rphy->identify.sas_address) {
1935 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001936 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001937 }
James Bottomley2686de22006-06-30 12:54:02 -05001938 }
1939
James Bottomleyf013db32006-03-18 14:54:36 -06001940 switch (identify.device_type) {
1941 case SAS_END_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001942 rphy = sas_end_device_alloc(port);
James Bottomleyf013db32006-03-18 14:54:36 -06001943 break;
1944 case SAS_EDGE_EXPANDER_DEVICE:
1945 case SAS_FANOUT_EXPANDER_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001946 rphy = sas_expander_alloc(port, identify.device_type);
James Bottomleyf013db32006-03-18 14:54:36 -06001947 break;
1948 default:
1949 rphy = NULL;
1950 break;
1951 }
Eric Moore547f9a22006-06-27 14:42:12 -06001952 if (!rphy) {
1953 dfailprintk((MYIOC_s_ERR_FMT
1954 "%s: exit at line=%d\n", ioc->name,
1955 __FUNCTION__, __LINE__));
1956 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001957 }
1958
Eric Moore547f9a22006-06-27 14:42:12 -06001959 rphy->identify = identify;
1960 error = sas_rphy_add(rphy);
1961 if (error) {
1962 dfailprintk((MYIOC_s_ERR_FMT
1963 "%s: exit at line=%d\n", ioc->name,
1964 __FUNCTION__, __LINE__));
1965 sas_rphy_free(rphy);
1966 goto out;
1967 }
1968 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001969 }
1970
Eric Moore547f9a22006-06-27 14:42:12 -06001971 out:
1972 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001973}
1974
1975static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001976mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001977{
Moore, Erice6b2d762006-03-14 09:14:24 -07001978 struct mptsas_portinfo *port_info, *hba;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001979 u32 handle = 0xFFFF;
1980 int error = -ENOMEM, i;
1981
Moore, Erice6b2d762006-03-14 09:14:24 -07001982 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
1983 if (! hba)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001984 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001985
Moore, Erice6b2d762006-03-14 09:14:24 -07001986 error = mptsas_sas_io_unit_pg0(ioc, hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001987 if (error)
1988 goto out_free_port_info;
1989
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001990 mutex_lock(&ioc->sas_topology_mutex);
James Bottomley2686de22006-06-30 12:54:02 -05001991 ioc->handle = hba->handle;
Moore, Erice6b2d762006-03-14 09:14:24 -07001992 port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
1993 if (!port_info) {
1994 port_info = hba;
1995 list_add_tail(&port_info->list, &ioc->sas_topology);
1996 } else {
1997 port_info->handle = hba->handle;
1998 for (i = 0; i < hba->num_phys; i++)
1999 port_info->phy_info[i].negotiated_link_rate =
2000 hba->phy_info[i].negotiated_link_rate;
Eric Moore547f9a22006-06-27 14:42:12 -06002001 kfree(hba->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002002 kfree(hba);
2003 hba = NULL;
2004 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002005 mutex_unlock(&ioc->sas_topology_mutex);
2006
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002007 for (i = 0; i < port_info->num_phys; i++) {
2008 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
2009 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
2010 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
2011
2012 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
2013 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
2014 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02002015 port_info->phy_info[i].identify.phy_id =
2016 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002017 handle = port_info->phy_info[i].identify.handle;
2018
Eric Moore547f9a22006-06-27 14:42:12 -06002019 if (port_info->phy_info[i].attached.handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002020 mptsas_sas_device_pg0(ioc,
2021 &port_info->phy_info[i].attached,
2022 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2023 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2024 port_info->phy_info[i].attached.handle);
Eric Moore547f9a22006-06-27 14:42:12 -06002025 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002026
Eric Moore547f9a22006-06-27 14:42:12 -06002027 mptsas_setup_wide_ports(ioc, port_info);
2028
2029 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002030 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Moore, Erice6b2d762006-03-14 09:14:24 -07002031 &port_info->phy_info[i], ioc->sas_index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002032
2033 return 0;
2034
2035 out_free_port_info:
Eric Moore547f9a22006-06-27 14:42:12 -06002036 kfree(hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002037 out:
2038 return error;
2039}
2040
2041static int
Moore, Erice6b2d762006-03-14 09:14:24 -07002042mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002043{
Moore, Erice6b2d762006-03-14 09:14:24 -07002044 struct mptsas_portinfo *port_info, *p, *ex;
Eric Moore547f9a22006-06-27 14:42:12 -06002045 struct device *parent;
2046 struct sas_rphy *rphy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002047 int error = -ENOMEM, i, j;
2048
Moore, Erice6b2d762006-03-14 09:14:24 -07002049 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
2050 if (!ex)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002051 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002052
Moore, Erice6b2d762006-03-14 09:14:24 -07002053 error = mptsas_sas_expander_pg0(ioc, ex,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002054 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
2055 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
2056 if (error)
2057 goto out_free_port_info;
2058
Moore, Erice6b2d762006-03-14 09:14:24 -07002059 *handle = ex->handle;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002060
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002061 mutex_lock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07002062 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
2063 if (!port_info) {
2064 port_info = ex;
2065 list_add_tail(&port_info->list, &ioc->sas_topology);
2066 } else {
2067 port_info->handle = ex->handle;
Eric Moore547f9a22006-06-27 14:42:12 -06002068 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002069 kfree(ex);
2070 ex = NULL;
2071 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002072 mutex_unlock(&ioc->sas_topology_mutex);
2073
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002074 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002075 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
2076 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
2077 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
2078
2079 if (port_info->phy_info[i].identify.handle) {
2080 mptsas_sas_device_pg0(ioc,
2081 &port_info->phy_info[i].identify,
2082 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2083 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2084 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02002085 port_info->phy_info[i].identify.phy_id =
2086 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002087 }
2088
2089 if (port_info->phy_info[i].attached.handle) {
2090 mptsas_sas_device_pg0(ioc,
2091 &port_info->phy_info[i].attached,
2092 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2093 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2094 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07002095 port_info->phy_info[i].attached.phy_id =
2096 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002097 }
Eric Moore547f9a22006-06-27 14:42:12 -06002098 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002099
Eric Moore547f9a22006-06-27 14:42:12 -06002100 parent = &ioc->sh->shost_gendev;
2101 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002102 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002103 list_for_each_entry(p, &ioc->sas_topology, list) {
2104 for (j = 0; j < p->num_phys; j++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002105 if (port_info->phy_info[i].identify.handle !=
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002106 p->phy_info[j].attached.handle)
Eric Moore547f9a22006-06-27 14:42:12 -06002107 continue;
2108 rphy = mptsas_get_rphy(&p->phy_info[j]);
2109 parent = &rphy->dev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002110 }
2111 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002112 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002113 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002114
Eric Moore547f9a22006-06-27 14:42:12 -06002115 mptsas_setup_wide_ports(ioc, port_info);
2116
2117 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02002118 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
Moore, Erice6b2d762006-03-14 09:14:24 -07002119 ioc->sas_index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002120
2121 return 0;
2122
2123 out_free_port_info:
Moore, Erice6b2d762006-03-14 09:14:24 -07002124 if (ex) {
Eric Moore547f9a22006-06-27 14:42:12 -06002125 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002126 kfree(ex);
2127 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002128 out:
2129 return error;
2130}
2131
Moore, Erice6b2d762006-03-14 09:14:24 -07002132/*
2133 * mptsas_delete_expander_phys
2134 *
2135 *
2136 * This will traverse topology, and remove expanders
2137 * that are no longer present
2138 */
2139static void
2140mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
2141{
2142 struct mptsas_portinfo buffer;
2143 struct mptsas_portinfo *port_info, *n, *parent;
Eric Moore547f9a22006-06-27 14:42:12 -06002144 struct mptsas_phyinfo *phy_info;
Eric Moore547f9a22006-06-27 14:42:12 -06002145 struct sas_port * port;
Moore, Erice6b2d762006-03-14 09:14:24 -07002146 int i;
Eric Moore547f9a22006-06-27 14:42:12 -06002147 u64 expander_sas_address;
Moore, Erice6b2d762006-03-14 09:14:24 -07002148
2149 mutex_lock(&ioc->sas_topology_mutex);
2150 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
2151
2152 if (port_info->phy_info &&
2153 (!(port_info->phy_info[0].identify.device_info &
2154 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
2155 continue;
2156
2157 if (mptsas_sas_expander_pg0(ioc, &buffer,
2158 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
2159 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
2160
2161 /*
2162 * Obtain the port_info instance to the parent port
2163 */
2164 parent = mptsas_find_portinfo_by_handle(ioc,
2165 port_info->phy_info[0].identify.handle_parent);
2166
2167 if (!parent)
2168 goto next_port;
2169
Eric Moore547f9a22006-06-27 14:42:12 -06002170 expander_sas_address =
2171 port_info->phy_info[0].identify.sas_address;
2172
Moore, Erice6b2d762006-03-14 09:14:24 -07002173 /*
2174 * Delete rphys in the parent that point
2175 * to this expander. The transport layer will
2176 * cleanup all the children.
2177 */
Eric Moore547f9a22006-06-27 14:42:12 -06002178 phy_info = parent->phy_info;
2179 for (i = 0; i < parent->num_phys; i++, phy_info++) {
2180 port = mptsas_get_port(phy_info);
2181 if (!port)
Moore, Erice6b2d762006-03-14 09:14:24 -07002182 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002183 if (phy_info->attached.sas_address !=
2184 expander_sas_address)
2185 continue;
2186#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06002187 dev_printk(KERN_DEBUG, &port->dev,
2188 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002189#endif
2190 sas_port_delete(port);
2191 mptsas_port_delete(phy_info->port_details);
Moore, Erice6b2d762006-03-14 09:14:24 -07002192 }
2193 next_port:
Eric Moore547f9a22006-06-27 14:42:12 -06002194
2195 phy_info = port_info->phy_info;
2196 for (i = 0; i < port_info->num_phys; i++, phy_info++)
2197 mptsas_port_delete(phy_info->port_details);
2198
Moore, Erice6b2d762006-03-14 09:14:24 -07002199 list_del(&port_info->list);
Eric Moore547f9a22006-06-27 14:42:12 -06002200 kfree(port_info->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002201 kfree(port_info);
2202 }
2203 /*
2204 * Free this memory allocated from inside
2205 * mptsas_sas_expander_pg0
2206 */
Eric Moore547f9a22006-06-27 14:42:12 -06002207 kfree(buffer.phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002208 }
2209 mutex_unlock(&ioc->sas_topology_mutex);
2210}
2211
2212/*
2213 * Start of day discovery
2214 */
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002215static void
2216mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
2217{
2218 u32 handle = 0xFFFF;
Moore, Ericf44e5462006-03-14 09:14:21 -07002219 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002220
Moore, Erice6b2d762006-03-14 09:14:24 -07002221 mutex_lock(&ioc->sas_discovery_mutex);
2222 mptsas_probe_hba_phys(ioc);
2223 while (!mptsas_probe_expander_phys(ioc, &handle))
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002224 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07002225 /*
2226 Reporting RAID volumes.
2227 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002228 if (!ioc->ir_firmware)
2229 goto out;
Moore, Ericf44e5462006-03-14 09:14:21 -07002230 if (!ioc->raid_data.pIocPg2)
2231 goto out;
2232 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
2233 goto out;
Eric Moore793955f2007-01-29 09:42:20 -07002234 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
James Bottomleye8bf3942006-07-11 17:49:34 -04002235 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
Moore, Ericf44e5462006-03-14 09:14:21 -07002236 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
2237 }
2238 out:
Moore, Erice6b2d762006-03-14 09:14:24 -07002239 mutex_unlock(&ioc->sas_discovery_mutex);
2240}
2241
2242/*
2243 * Work queue thread to handle Runtime discovery
2244 * Mere purpose is the hot add/delete of expanders
Eric Moore547f9a22006-06-27 14:42:12 -06002245 *(Mutex UNLOCKED)
Moore, Erice6b2d762006-03-14 09:14:24 -07002246 */
2247static void
Eric Moore547f9a22006-06-27 14:42:12 -06002248__mptsas_discovery_work(MPT_ADAPTER *ioc)
Moore, Erice6b2d762006-03-14 09:14:24 -07002249{
Moore, Erice6b2d762006-03-14 09:14:24 -07002250 u32 handle = 0xFFFF;
2251
Moore, Erice6b2d762006-03-14 09:14:24 -07002252 ioc->sas_discovery_runtime=1;
2253 mptsas_delete_expander_phys(ioc);
2254 mptsas_probe_hba_phys(ioc);
2255 while (!mptsas_probe_expander_phys(ioc, &handle))
2256 ;
Moore, Erice6b2d762006-03-14 09:14:24 -07002257 ioc->sas_discovery_runtime=0;
Eric Moore547f9a22006-06-27 14:42:12 -06002258}
2259
2260/*
2261 * Work queue thread to handle Runtime discovery
2262 * Mere purpose is the hot add/delete of expanders
2263 *(Mutex LOCKED)
2264 */
2265static void
David Howellsc4028952006-11-22 14:57:56 +00002266mptsas_discovery_work(struct work_struct *work)
Eric Moore547f9a22006-06-27 14:42:12 -06002267{
David Howellsc4028952006-11-22 14:57:56 +00002268 struct mptsas_discovery_event *ev =
2269 container_of(work, struct mptsas_discovery_event, work);
Eric Moore547f9a22006-06-27 14:42:12 -06002270 MPT_ADAPTER *ioc = ev->ioc;
2271
2272 mutex_lock(&ioc->sas_discovery_mutex);
2273 __mptsas_discovery_work(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002274 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002275 kfree(ev);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002276}
2277
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002278static struct mptsas_phyinfo *
Eric Moore547f9a22006-06-27 14:42:12 -06002279mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002280{
2281 struct mptsas_portinfo *port_info;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002282 struct mptsas_phyinfo *phy_info = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -06002283 int i;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002284
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002285 mutex_lock(&ioc->sas_topology_mutex);
2286 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2287 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002288 if (!mptsas_is_end_device(
2289 &port_info->phy_info[i].attached))
2290 continue;
Eric Mooreb506ade2007-01-29 09:45:37 -07002291 if (port_info->phy_info[i].attached.sas_address
2292 != sas_address)
2293 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002294 phy_info = &port_info->phy_info[i];
2295 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002296 }
2297 }
2298 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002299 return phy_info;
2300}
2301
2302static struct mptsas_phyinfo *
Eric Mooreb506ade2007-01-29 09:45:37 -07002303mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002304{
2305 struct mptsas_portinfo *port_info;
2306 struct mptsas_phyinfo *phy_info = NULL;
2307 int i;
2308
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002309 mutex_lock(&ioc->sas_topology_mutex);
2310 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -06002311 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002312 if (!mptsas_is_end_device(
2313 &port_info->phy_info[i].attached))
2314 continue;
Eric Mooreb506ade2007-01-29 09:45:37 -07002315 if (port_info->phy_info[i].attached.id != id)
2316 continue;
2317 if (port_info->phy_info[i].attached.channel != channel)
2318 continue;
2319 phy_info = &port_info->phy_info[i];
2320 break;
2321 }
2322 }
2323 mutex_unlock(&ioc->sas_topology_mutex);
2324 return phy_info;
2325}
2326
2327static struct mptsas_phyinfo *
2328mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2329{
2330 struct mptsas_portinfo *port_info;
2331 struct mptsas_phyinfo *phy_info = NULL;
2332 int i;
2333
2334 mutex_lock(&ioc->sas_topology_mutex);
2335 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2336 for (i = 0; i < port_info->num_phys; i++) {
2337 if (!mptsas_is_end_device(
2338 &port_info->phy_info[i].attached))
2339 continue;
2340 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
2341 continue;
2342 if (port_info->phy_info[i].attached.phys_disk_num != id)
2343 continue;
2344 if (port_info->phy_info[i].attached.channel != channel)
2345 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002346 phy_info = &port_info->phy_info[i];
2347 break;
2348 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002349 }
2350 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002351 return phy_info;
2352}
2353
Moore, Eric4b766472006-03-14 09:14:12 -07002354/*
2355 * Work queue thread to clear the persitency table
2356 */
2357static void
David Howellsc4028952006-11-22 14:57:56 +00002358mptsas_persist_clear_table(struct work_struct *work)
Moore, Eric4b766472006-03-14 09:14:12 -07002359{
David Howellsc4028952006-11-22 14:57:56 +00002360 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002361
2362 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2363}
2364
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002365static void
Moore, Ericf44e5462006-03-14 09:14:21 -07002366mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2367{
Eric Mooref99be432007-01-04 20:46:54 -07002368 int rc;
2369
Moore, Ericf44e5462006-03-14 09:14:21 -07002370 sdev->no_uld_attach = data ? 1 : 0;
Eric Mooref99be432007-01-04 20:46:54 -07002371 rc = scsi_device_reprobe(sdev);
Moore, Ericf44e5462006-03-14 09:14:21 -07002372}
2373
2374static void
2375mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2376{
2377 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2378 mptsas_reprobe_lun);
2379}
2380
Eric Mooreb506ade2007-01-29 09:45:37 -07002381static void
2382mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
2383{
2384 CONFIGPARMS cfg;
2385 ConfigPageHeader_t hdr;
2386 dma_addr_t dma_handle;
2387 pRaidVolumePage0_t buffer = NULL;
2388 RaidPhysDiskPage0_t phys_disk;
2389 int i;
2390 struct mptsas_hotplug_event *ev;
2391
2392 memset(&cfg, 0 , sizeof(CONFIGPARMS));
2393 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
2394 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
2395 cfg.pageAddr = (channel << 8) + id;
2396 cfg.cfghdr.hdr = &hdr;
2397 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2398
2399 if (mpt_config(ioc, &cfg) != 0)
2400 goto out;
2401
2402 if (!hdr.PageLength)
2403 goto out;
2404
2405 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
2406 &dma_handle);
2407
2408 if (!buffer)
2409 goto out;
2410
2411 cfg.physAddr = dma_handle;
2412 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2413
2414 if (mpt_config(ioc, &cfg) != 0)
2415 goto out;
2416
2417 if (!(buffer->VolumeStatus.Flags &
2418 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
2419 goto out;
2420
2421 if (!buffer->NumPhysDisks)
2422 goto out;
2423
2424 for (i = 0; i < buffer->NumPhysDisks; i++) {
2425
2426 if (mpt_raid_phys_disk_pg0(ioc,
2427 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
2428 continue;
2429
2430 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2431 if (!ev) {
2432 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2433 goto out;
2434 }
2435
2436 INIT_WORK(&ev->work, mptsas_hotplug_work);
2437 ev->ioc = ioc;
2438 ev->id = phys_disk.PhysDiskID;
2439 ev->channel = phys_disk.PhysDiskBus;
2440 ev->phys_disk_num_valid = 1;
2441 ev->phys_disk_num = phys_disk.PhysDiskNum;
2442 ev->event_type = MPTSAS_ADD_DEVICE;
2443 schedule_work(&ev->work);
2444 }
2445
2446 out:
2447 if (buffer)
2448 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
2449 dma_handle);
2450}
Moore, Erice6b2d762006-03-14 09:14:24 -07002451/*
2452 * Work queue thread to handle SAS hotplug events
2453 */
Moore, Ericf44e5462006-03-14 09:14:21 -07002454static void
David Howellsc4028952006-11-22 14:57:56 +00002455mptsas_hotplug_work(struct work_struct *work)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002456{
David Howellsc4028952006-11-22 14:57:56 +00002457 struct mptsas_hotplug_event *ev =
2458 container_of(work, struct mptsas_hotplug_event, work);
Eric Mooreb506ade2007-01-29 09:45:37 -07002459
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002460 MPT_ADAPTER *ioc = ev->ioc;
2461 struct mptsas_phyinfo *phy_info;
2462 struct sas_rphy *rphy;
Eric Moore547f9a22006-06-27 14:42:12 -06002463 struct sas_port *port;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002464 struct scsi_device *sdev;
Eric Moore547f9a22006-06-27 14:42:12 -06002465 struct scsi_target * starget;
James Bottomleyf013db32006-03-18 14:54:36 -06002466 struct sas_identify identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002467 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002468 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07002469 VirtTarget *vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -06002470 VirtDevice *vdevice;
2471
Moore, Erice6b2d762006-03-14 09:14:24 -07002472 mutex_lock(&ioc->sas_discovery_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002473 switch (ev->event_type) {
2474 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002475
Eric Mooreb506ade2007-01-29 09:45:37 -07002476 phy_info = NULL;
2477 if (ev->phys_disk_num_valid) {
2478 if (ev->hidden_raid_component){
2479 if (mptsas_sas_device_pg0(ioc, &sas_device,
2480 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
2481 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2482 (ev->channel << 8) + ev->id)) {
2483 dfailprintk((MYIOC_s_ERR_FMT
2484 "%s: exit at line=%d\n", ioc->name,
2485 __FUNCTION__, __LINE__));
2486 break;
2487 }
2488 phy_info = mptsas_find_phyinfo_by_sas_address(
2489 ioc, sas_device.sas_address);
2490 }else
2491 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
2492 ioc, ev->channel, ev->phys_disk_num);
2493 }
2494
2495 if (!phy_info)
2496 phy_info = mptsas_find_phyinfo_by_target(ioc,
2497 ev->channel, ev->id);
Moore, Erice6b2d762006-03-14 09:14:24 -07002498
Moore, Ericf44e5462006-03-14 09:14:21 -07002499 /*
2500 * Sanity checks, for non-existing phys and remote rphys.
2501 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002502 if (!phy_info){
2503 dfailprintk((MYIOC_s_ERR_FMT
2504 "%s: exit at line=%d\n", ioc->name,
2505 __FUNCTION__, __LINE__));
2506 break;
2507 }
2508 if (!phy_info->port_details) {
Eric Moore547f9a22006-06-27 14:42:12 -06002509 dfailprintk((MYIOC_s_ERR_FMT
2510 "%s: exit at line=%d\n", ioc->name,
2511 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002512 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002513 }
2514 rphy = mptsas_get_rphy(phy_info);
2515 if (!rphy) {
2516 dfailprintk((MYIOC_s_ERR_FMT
2517 "%s: exit at line=%d\n", ioc->name,
2518 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002519 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002520 }
Eric Mooreb506ade2007-01-29 09:45:37 -07002521
Eric Moore547f9a22006-06-27 14:42:12 -06002522 port = mptsas_get_port(phy_info);
2523 if (!port) {
2524 dfailprintk((MYIOC_s_ERR_FMT
2525 "%s: exit at line=%d\n", ioc->name,
2526 __FUNCTION__, __LINE__));
2527 break;
2528 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002529
Eric Moore547f9a22006-06-27 14:42:12 -06002530 starget = mptsas_get_starget(phy_info);
2531 if (starget) {
2532 vtarget = starget->hostdata;
2533
2534 if (!vtarget) {
2535 dfailprintk((MYIOC_s_ERR_FMT
2536 "%s: exit at line=%d\n", ioc->name,
2537 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002538 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002539 }
2540
Moore, Ericf44e5462006-03-14 09:14:21 -07002541 /*
2542 * Handling RAID components
2543 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002544 if (ev->phys_disk_num_valid &&
2545 ev->hidden_raid_component) {
2546 printk(MYIOC_s_INFO_FMT
2547 "RAID Hidding: channel=%d, id=%d, "
2548 "physdsk %d \n", ioc->name, ev->channel,
2549 ev->id, ev->phys_disk_num);
Eric Moore793955f2007-01-29 09:42:20 -07002550 vtarget->id = ev->phys_disk_num;
Eric Mooreb506ade2007-01-29 09:45:37 -07002551 vtarget->tflags |=
2552 MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore547f9a22006-06-27 14:42:12 -06002553 mptsas_reprobe_target(starget, 1);
Eric Mooreb506ade2007-01-29 09:45:37 -07002554 phy_info->attached.phys_disk_num =
2555 ev->phys_disk_num;
2556 break;
Moore, Ericf44e5462006-03-14 09:14:21 -07002557 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002558 }
2559
Eric Mooreb506ade2007-01-29 09:45:37 -07002560 if (phy_info->attached.device_info &
2561 MPI_SAS_DEVICE_INFO_SSP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002562 ds = "ssp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002563 if (phy_info->attached.device_info &
2564 MPI_SAS_DEVICE_INFO_STP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002565 ds = "stp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002566 if (phy_info->attached.device_info &
2567 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002568 ds = "sata";
2569
2570 printk(MYIOC_s_INFO_FMT
2571 "removing %s device, channel %d, id %d, phy %d\n",
2572 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
Eric Moore547f9a22006-06-27 14:42:12 -06002573#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06002574 dev_printk(KERN_DEBUG, &port->dev,
2575 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002576#endif
2577 sas_port_delete(port);
2578 mptsas_port_delete(phy_info->port_details);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002579 break;
2580 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002581
Moore, Ericbd23e942006-04-17 12:43:04 -06002582 if (ev->phys_disk_num_valid)
2583 mpt_findImVolumes(ioc);
2584
Moore, Ericc73787ee2006-01-26 16:20:06 -07002585 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01002586 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07002587 */
Christoph Hellwige3094442006-02-16 13:25:36 +01002588 if (mptsas_sas_device_pg0(ioc, &sas_device,
2589 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
Eric Mooreb506ade2007-01-29 09:45:37 -07002590 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2591 (ev->channel << 8) + ev->id)) {
Eric Moore547f9a22006-06-27 14:42:12 -06002592 dfailprintk((MYIOC_s_ERR_FMT
2593 "%s: exit at line=%d\n", ioc->name,
2594 __FUNCTION__, __LINE__));
Christoph Hellwige3094442006-02-16 13:25:36 +01002595 break;
Moore, Erice6b2d762006-03-14 09:14:24 -07002596 }
2597
Eric Moore547f9a22006-06-27 14:42:12 -06002598 __mptsas_discovery_work(ioc);
Moore, Ericf44e5462006-03-14 09:14:21 -07002599
Eric Moore547f9a22006-06-27 14:42:12 -06002600 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2601 sas_device.sas_address);
2602
2603 if (!phy_info || !phy_info->port_details) {
2604 dfailprintk((MYIOC_s_ERR_FMT
2605 "%s: exit at line=%d\n", ioc->name,
2606 __FUNCTION__, __LINE__));
2607 break;
2608 }
2609
2610 starget = mptsas_get_starget(phy_info);
Eric Mooreb506ade2007-01-29 09:45:37 -07002611 if (starget && (!ev->hidden_raid_component)){
2612
Eric Moore547f9a22006-06-27 14:42:12 -06002613 vtarget = starget->hostdata;
2614
2615 if (!vtarget) {
2616 dfailprintk((MYIOC_s_ERR_FMT
2617 "%s: exit at line=%d\n", ioc->name,
2618 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002619 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002620 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002621 /*
2622 * Handling RAID components
2623 */
2624 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
Eric Mooreb506ade2007-01-29 09:45:37 -07002625 printk(MYIOC_s_INFO_FMT
2626 "RAID Exposing: channel=%d, id=%d, "
2627 "physdsk %d \n", ioc->name, ev->channel,
2628 ev->id, ev->phys_disk_num);
2629 vtarget->tflags &=
2630 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore793955f2007-01-29 09:42:20 -07002631 vtarget->id = ev->id;
Eric Moore547f9a22006-06-27 14:42:12 -06002632 mptsas_reprobe_target(starget, 0);
Eric Mooreb506ade2007-01-29 09:45:37 -07002633 phy_info->attached.phys_disk_num = ~0;
Moore, Ericf44e5462006-03-14 09:14:21 -07002634 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002635 break;
2636 }
2637
Eric Moore547f9a22006-06-27 14:42:12 -06002638 if (mptsas_get_rphy(phy_info)) {
2639 dfailprintk((MYIOC_s_ERR_FMT
2640 "%s: exit at line=%d\n", ioc->name,
2641 __FUNCTION__, __LINE__));
Eric Mooreb506ade2007-01-29 09:45:37 -07002642 if (ev->channel) printk("%d\n", __LINE__);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002643 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002644 }
Eric Mooreb506ade2007-01-29 09:45:37 -07002645
Eric Moore547f9a22006-06-27 14:42:12 -06002646 port = mptsas_get_port(phy_info);
2647 if (!port) {
2648 dfailprintk((MYIOC_s_ERR_FMT
2649 "%s: exit at line=%d\n", ioc->name,
2650 __FUNCTION__, __LINE__));
2651 break;
2652 }
Christoph Hellwige3094442006-02-16 13:25:36 +01002653 memcpy(&phy_info->attached, &sas_device,
2654 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002655
Eric Mooreb506ade2007-01-29 09:45:37 -07002656 if (phy_info->attached.device_info &
2657 MPI_SAS_DEVICE_INFO_SSP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002658 ds = "ssp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002659 if (phy_info->attached.device_info &
2660 MPI_SAS_DEVICE_INFO_STP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002661 ds = "stp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002662 if (phy_info->attached.device_info &
2663 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002664 ds = "sata";
2665
2666 printk(MYIOC_s_INFO_FMT
2667 "attaching %s device, channel %d, id %d, phy %d\n",
2668 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2669
James Bottomleyf013db32006-03-18 14:54:36 -06002670 mptsas_parse_device_info(&identify, &phy_info->attached);
Eric Moore547f9a22006-06-27 14:42:12 -06002671 rphy = sas_end_device_alloc(port);
2672 if (!rphy) {
2673 dfailprintk((MYIOC_s_ERR_FMT
2674 "%s: exit at line=%d\n", ioc->name,
2675 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002676 break; /* non-fatal: an rphy can be added later */
Eric Moore547f9a22006-06-27 14:42:12 -06002677 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002678
James Bottomleyf013db32006-03-18 14:54:36 -06002679 rphy->identify = identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002680 if (sas_rphy_add(rphy)) {
Eric Moore547f9a22006-06-27 14:42:12 -06002681 dfailprintk((MYIOC_s_ERR_FMT
2682 "%s: exit at line=%d\n", ioc->name,
2683 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002684 sas_rphy_free(rphy);
2685 break;
2686 }
Eric Moore547f9a22006-06-27 14:42:12 -06002687 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002688 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002689 case MPTSAS_ADD_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002690 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2691 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002692 if (sdev) {
2693 scsi_device_put(sdev);
2694 break;
2695 }
2696 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002697 "attaching raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002698 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2699 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002700 mpt_findImVolumes(ioc);
2701 break;
2702 case MPTSAS_DEL_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002703 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
Eric Mooreb506ade2007-01-29 09:45:37 -07002704 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002705 if (!sdev)
2706 break;
2707 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002708 "removing raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002709 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
Eric Mooreb506ade2007-01-29 09:45:37 -07002710 vdevice = sdev->hostdata;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002711 scsi_remove_device(sdev);
2712 scsi_device_put(sdev);
2713 mpt_findImVolumes(ioc);
2714 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07002715 case MPTSAS_ADD_INACTIVE_VOLUME:
2716 mptsas_adding_inactive_raid_components(ioc,
2717 ev->channel, ev->id);
2718 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002719 case MPTSAS_IGNORE_EVENT:
2720 default:
2721 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002722 }
2723
Moore, Erice6b2d762006-03-14 09:14:24 -07002724 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002725 kfree(ev);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002726}
2727
2728static void
Eric Moore547f9a22006-06-27 14:42:12 -06002729mptsas_send_sas_event(MPT_ADAPTER *ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002730 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2731{
2732 struct mptsas_hotplug_event *ev;
2733 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2734 __le64 sas_address;
2735
2736 if ((device_info &
2737 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2738 MPI_SAS_DEVICE_INFO_STP_TARGET |
2739 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2740 return;
2741
Moore, Eric4b766472006-03-14 09:14:12 -07002742 switch (sas_event_data->ReasonCode) {
Moore, Eric4b766472006-03-14 09:14:12 -07002743 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
Eric Mooredf9e0622007-01-29 09:46:21 -07002744
2745 mptsas_target_reset_queue(ioc, sas_event_data);
2746 break;
2747
2748 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
Eric Moore547f9a22006-06-27 14:42:12 -06002749 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Eric4b766472006-03-14 09:14:12 -07002750 if (!ev) {
2751 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2752 break;
2753 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002754
David Howellsc4028952006-11-22 14:57:56 +00002755 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Eric4b766472006-03-14 09:14:12 -07002756 ev->ioc = ioc;
2757 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2758 ev->parent_handle =
2759 le16_to_cpu(sas_event_data->ParentDevHandle);
2760 ev->channel = sas_event_data->Bus;
2761 ev->id = sas_event_data->TargetID;
2762 ev->phy_id = sas_event_data->PhyNum;
2763 memcpy(&sas_address, &sas_event_data->SASAddress,
2764 sizeof(__le64));
2765 ev->sas_address = le64_to_cpu(sas_address);
2766 ev->device_info = device_info;
2767
2768 if (sas_event_data->ReasonCode &
2769 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2770 ev->event_type = MPTSAS_ADD_DEVICE;
2771 else
2772 ev->event_type = MPTSAS_DEL_DEVICE;
2773 schedule_work(&ev->work);
2774 break;
2775 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2776 /*
2777 * Persistent table is full.
2778 */
Eric Moore547f9a22006-06-27 14:42:12 -06002779 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00002780 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06002781 schedule_work(&ioc->sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002782 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07002783 /*
2784 * TODO, handle other events
2785 */
Moore, Eric4b766472006-03-14 09:14:12 -07002786 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
Eric Mooreb506ade2007-01-29 09:45:37 -07002787 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
Moore, Eric4b766472006-03-14 09:14:12 -07002788 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
Eric Mooreb506ade2007-01-29 09:45:37 -07002789 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
2790 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
2791 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
2792 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
Moore, Eric4b766472006-03-14 09:14:12 -07002793 default:
2794 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002795 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002796}
Moore, Ericc73787ee2006-01-26 16:20:06 -07002797static void
Eric Moore547f9a22006-06-27 14:42:12 -06002798mptsas_send_raid_event(MPT_ADAPTER *ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002799 EVENT_DATA_RAID *raid_event_data)
2800{
2801 struct mptsas_hotplug_event *ev;
Moore, Ericbd23e942006-04-17 12:43:04 -06002802 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2803 int state = (status >> 8) & 0xff;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002804
2805 if (ioc->bus_type != SAS)
2806 return;
2807
Eric Moore547f9a22006-06-27 14:42:12 -06002808 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002809 if (!ev) {
2810 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2811 return;
2812 }
2813
David Howellsc4028952006-11-22 14:57:56 +00002814 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002815 ev->ioc = ioc;
2816 ev->id = raid_event_data->VolumeID;
Eric Mooreb506ade2007-01-29 09:45:37 -07002817 ev->channel = raid_event_data->VolumeBus;
Moore, Ericbd23e942006-04-17 12:43:04 -06002818 ev->event_type = MPTSAS_IGNORE_EVENT;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002819
2820 switch (raid_event_data->ReasonCode) {
2821 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
Eric Mooreb506ade2007-01-29 09:45:37 -07002822 ev->phys_disk_num_valid = 1;
2823 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002824 ev->event_type = MPTSAS_ADD_DEVICE;
2825 break;
2826 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07002827 ev->phys_disk_num_valid = 1;
2828 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Eric Mooreb506ade2007-01-29 09:45:37 -07002829 ev->hidden_raid_component = 1;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002830 ev->event_type = MPTSAS_DEL_DEVICE;
2831 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002832 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2833 switch (state) {
2834 case MPI_PD_STATE_ONLINE:
Eric Mooreb506ade2007-01-29 09:45:37 -07002835 case MPI_PD_STATE_NOT_COMPATIBLE:
Moore, Ericbd23e942006-04-17 12:43:04 -06002836 ev->phys_disk_num_valid = 1;
2837 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Eric Mooreb506ade2007-01-29 09:45:37 -07002838 ev->hidden_raid_component = 1;
Moore, Ericbd23e942006-04-17 12:43:04 -06002839 ev->event_type = MPTSAS_ADD_DEVICE;
2840 break;
2841 case MPI_PD_STATE_MISSING:
Moore, Ericbd23e942006-04-17 12:43:04 -06002842 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2843 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2844 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
Eric Mooreb506ade2007-01-29 09:45:37 -07002845 ev->phys_disk_num_valid = 1;
2846 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericbd23e942006-04-17 12:43:04 -06002847 ev->event_type = MPTSAS_DEL_DEVICE;
2848 break;
2849 default:
2850 break;
2851 }
2852 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002853 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2854 ev->event_type = MPTSAS_DEL_RAID;
2855 break;
2856 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2857 ev->event_type = MPTSAS_ADD_RAID;
2858 break;
2859 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
Moore, Ericbd23e942006-04-17 12:43:04 -06002860 switch (state) {
2861 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2862 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2863 ev->event_type = MPTSAS_DEL_RAID;
2864 break;
2865 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2866 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2867 ev->event_type = MPTSAS_ADD_RAID;
2868 break;
2869 default:
2870 break;
2871 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002872 break;
2873 default:
2874 break;
2875 }
2876 schedule_work(&ev->work);
2877}
2878
Moore, Erice6b2d762006-03-14 09:14:24 -07002879static void
Eric Moore547f9a22006-06-27 14:42:12 -06002880mptsas_send_discovery_event(MPT_ADAPTER *ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002881 EVENT_DATA_SAS_DISCOVERY *discovery_data)
2882{
2883 struct mptsas_discovery_event *ev;
2884
2885 /*
2886 * DiscoveryStatus
2887 *
2888 * This flag will be non-zero when firmware
2889 * kicks off discovery, and return to zero
2890 * once its completed.
2891 */
2892 if (discovery_data->DiscoveryStatus)
2893 return;
2894
Eric Moore547f9a22006-06-27 14:42:12 -06002895 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Erice6b2d762006-03-14 09:14:24 -07002896 if (!ev)
2897 return;
David Howellsc4028952006-11-22 14:57:56 +00002898 INIT_WORK(&ev->work, mptsas_discovery_work);
Moore, Erice6b2d762006-03-14 09:14:24 -07002899 ev->ioc = ioc;
2900 schedule_work(&ev->work);
2901};
2902
Eric Mooreb506ade2007-01-29 09:45:37 -07002903/*
2904 * mptsas_send_ir2_event - handle exposing hidden disk when
2905 * an inactive raid volume is added
2906 *
2907 * @ioc: Pointer to MPT_ADAPTER structure
2908 * @ir2_data
2909 *
2910 */
2911static void
2912mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
2913{
2914 struct mptsas_hotplug_event *ev;
2915
2916 if (ir2_data->ReasonCode !=
2917 MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
2918 return;
2919
2920 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2921 if (!ev)
2922 return;
2923
2924 INIT_WORK(&ev->work, mptsas_hotplug_work);
2925 ev->ioc = ioc;
2926 ev->id = ir2_data->TargetID;
2927 ev->channel = ir2_data->Bus;
2928 ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
2929
2930 schedule_work(&ev->work);
2931};
Moore, Erice6b2d762006-03-14 09:14:24 -07002932
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002933static int
2934mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
2935{
Moore, Ericc73787ee2006-01-26 16:20:06 -07002936 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002937 u8 event = le32_to_cpu(reply->Event) & 0xFF;
2938
2939 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002940 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002941
Moore, Erice6b2d762006-03-14 09:14:24 -07002942 /*
2943 * sas_discovery_ignore_events
2944 *
2945 * This flag is to prevent anymore processing of
2946 * sas events once mptsas_remove function is called.
2947 */
2948 if (ioc->sas_discovery_ignore_events) {
2949 rc = mptscsih_event_process(ioc, reply);
2950 goto out;
2951 }
2952
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002953 switch (event) {
2954 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
Eric Moore547f9a22006-06-27 14:42:12 -06002955 mptsas_send_sas_event(ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002956 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002957 break;
2958 case MPI_EVENT_INTEGRATED_RAID:
Eric Moore547f9a22006-06-27 14:42:12 -06002959 mptsas_send_raid_event(ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002960 (EVENT_DATA_RAID *)reply->Data);
2961 break;
Moore, Eric79de2782006-01-25 18:05:15 -07002962 case MPI_EVENT_PERSISTENT_TABLE_FULL:
Eric Moore547f9a22006-06-27 14:42:12 -06002963 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00002964 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06002965 schedule_work(&ioc->sas_persist_task);
Moore, Eric79de2782006-01-25 18:05:15 -07002966 break;
Moore, Eric4b766472006-03-14 09:14:12 -07002967 case MPI_EVENT_SAS_DISCOVERY:
Eric Moore547f9a22006-06-27 14:42:12 -06002968 mptsas_send_discovery_event(ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002969 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
2970 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07002971 case MPI_EVENT_IR2:
2972 mptsas_send_ir2_event(ioc,
2973 (PTR_MPI_EVENT_DATA_IR2)reply->Data);
2974 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002975 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002976 rc = mptscsih_event_process(ioc, reply);
2977 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002978 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002979 out:
2980
2981 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002982}
2983
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002984static int
2985mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2986{
2987 struct Scsi_Host *sh;
2988 MPT_SCSI_HOST *hd;
2989 MPT_ADAPTER *ioc;
2990 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002991 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002992 int numSGE = 0;
2993 int scale;
2994 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002995 int error=0;
2996 int r;
2997
2998 r = mpt_attach(pdev,id);
2999 if (r)
3000 return r;
3001
3002 ioc = pci_get_drvdata(pdev);
3003 ioc->DoneCtx = mptsasDoneCtx;
3004 ioc->TaskCtx = mptsasTaskCtx;
3005 ioc->InternalCtx = mptsasInternalCtx;
3006
3007 /* Added sanity check on readiness of the MPT adapter.
3008 */
3009 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
3010 printk(MYIOC_s_WARN_FMT
3011 "Skipping because it's not operational!\n",
3012 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003013 error = -ENODEV;
3014 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003015 }
3016
3017 if (!ioc->active) {
3018 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
3019 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003020 error = -ENODEV;
3021 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003022 }
3023
3024 /* Sanity check - ensure at least 1 port is INITIATOR capable
3025 */
3026 ioc_cap = 0;
3027 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
3028 if (ioc->pfacts[ii].ProtocolFlags &
3029 MPI_PORTFACTS_PROTOCOL_INITIATOR)
3030 ioc_cap++;
3031 }
3032
3033 if (!ioc_cap) {
3034 printk(MYIOC_s_WARN_FMT
3035 "Skipping ioc=%p because SCSI Initiator mode "
3036 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06003037 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003038 }
3039
3040 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
3041 if (!sh) {
3042 printk(MYIOC_s_WARN_FMT
3043 "Unable to register controller with SCSI subsystem\n",
3044 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003045 error = -1;
3046 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003047 }
3048
3049 spin_lock_irqsave(&ioc->FreeQlock, flags);
3050
3051 /* Attach the SCSI Host to the IOC structure
3052 */
3053 ioc->sh = sh;
3054
3055 sh->io_port = 0;
3056 sh->n_io_port = 0;
3057 sh->irq = 0;
3058
3059 /* set 16 byte cdb's */
3060 sh->max_cmd_len = 16;
3061
Eric Moore793955f2007-01-29 09:42:20 -07003062 sh->max_id = ioc->pfacts[0].PortSCSIID;
3063 sh->max_lun = max_lun;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003064
3065 sh->transportt = mptsas_transport_template;
3066
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003067 sh->this_id = ioc->pfacts[0].PortSCSIID;
3068
3069 /* Required entry.
3070 */
3071 sh->unique_id = ioc->id;
3072
3073 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003074 mutex_init(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07003075 mutex_init(&ioc->sas_discovery_mutex);
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01003076 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003077 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003078
3079 /* Verify that we won't exceed the maximum
3080 * number of chain buffers
3081 * We can optimize: ZZ = req_sz/sizeof(SGE)
3082 * For 32bit SGE's:
3083 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
3084 * + (req_sz - 64)/sizeof(SGE)
3085 * A slightly different algorithm is required for
3086 * 64bit SGEs.
3087 */
3088 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3089 if (sizeof(dma_addr_t) == sizeof(u64)) {
3090 numSGE = (scale - 1) *
3091 (ioc->facts.MaxChainDepth-1) + scale +
3092 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
3093 sizeof(u32));
3094 } else {
3095 numSGE = 1 + (scale - 1) *
3096 (ioc->facts.MaxChainDepth-1) + scale +
3097 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
3098 sizeof(u32));
3099 }
3100
3101 if (numSGE < sh->sg_tablesize) {
3102 /* Reset this value */
3103 dprintk((MYIOC_s_INFO_FMT
3104 "Resetting sg_tablesize to %d from %d\n",
3105 ioc->name, numSGE, sh->sg_tablesize));
3106 sh->sg_tablesize = numSGE;
3107 }
3108
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003109 hd = (MPT_SCSI_HOST *) sh->hostdata;
3110 hd->ioc = ioc;
3111
3112 /* SCSI needs scsi_cmnd lookup table!
3113 * (with size equal to req_depth*PtrSz!)
3114 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01003115 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
3116 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003117 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003118 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003119 }
3120
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01003121 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
3122 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003123
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003124 /* Clear the TM flags
3125 */
3126 hd->tmPending = 0;
3127 hd->tmState = TM_STATE_NONE;
3128 hd->resetPending = 0;
3129 hd->abortSCpnt = NULL;
3130
3131 /* Clear the pointer used to store
3132 * single-threaded commands, i.e., those
3133 * issued during a bus scan, dv and
3134 * configuration pages.
3135 */
3136 hd->cmdPtr = NULL;
3137
3138 /* Initialize this SCSI Hosts' timers
3139 * To use, set the timer expires field
3140 * and add_timer
3141 */
3142 init_timer(&hd->timer);
3143 hd->timer.data = (unsigned long) hd;
3144 hd->timer.function = mptscsih_timer_expired;
3145
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003146 ioc->sas_data.ptClear = mpt_pt_clear;
3147
Eric Mooredf9e0622007-01-29 09:46:21 -07003148 init_waitqueue_head(&hd->scandv_waitq);
3149 hd->scandv_wait_done = 0;
3150 hd->last_queue_full = 0;
3151 INIT_LIST_HEAD(&hd->target_reset_list);
3152 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3153
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003154 if (ioc->sas_data.ptClear==1) {
3155 mptbase_sas_persist_operation(
3156 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
3157 }
3158
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003159 error = scsi_add_host(sh, &ioc->pcidev->dev);
3160 if (error) {
3161 dprintk((KERN_ERR MYNAM
3162 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003163 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003164 }
3165
3166 mptsas_scan_sas_topology(ioc);
3167
3168 return 0;
3169
Eric Moore547f9a22006-06-27 14:42:12 -06003170 out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003171
3172 mptscsih_remove(pdev);
3173 return error;
3174}
3175
3176static void __devexit mptsas_remove(struct pci_dev *pdev)
3177{
3178 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
3179 struct mptsas_portinfo *p, *n;
Eric Moore547f9a22006-06-27 14:42:12 -06003180 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003181
Eric Mooreb506ade2007-01-29 09:45:37 -07003182 ioc->sas_discovery_ignore_events = 1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003183 sas_remove_host(ioc->sh);
3184
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003185 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003186 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
3187 list_del(&p->list);
Eric Moore547f9a22006-06-27 14:42:12 -06003188 for (i = 0 ; i < p->num_phys ; i++)
3189 mptsas_port_delete(p->phy_info[i].port_details);
3190 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003191 kfree(p);
3192 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003193 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003194
3195 mptscsih_remove(pdev);
3196}
3197
3198static struct pci_device_id mptsas_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06003199 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003200 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003201 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003202 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003203 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003204 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003205 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003206 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003207 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003208 PCI_ANY_ID, PCI_ANY_ID },
3209 {0} /* Terminating entry */
3210};
3211MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
3212
3213
3214static struct pci_driver mptsas_driver = {
3215 .name = "mptsas",
3216 .id_table = mptsas_pci_table,
3217 .probe = mptsas_probe,
3218 .remove = __devexit_p(mptsas_remove),
3219 .shutdown = mptscsih_shutdown,
3220#ifdef CONFIG_PM
3221 .suspend = mptscsih_suspend,
3222 .resume = mptscsih_resume,
3223#endif
3224};
3225
3226static int __init
3227mptsas_init(void)
3228{
3229 show_mptmod_ver(my_NAME, my_VERSION);
3230
3231 mptsas_transport_template =
3232 sas_attach_transport(&mptsas_transport_functions);
3233 if (!mptsas_transport_template)
3234 return -ENODEV;
3235
3236 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
Eric Mooredf9e0622007-01-29 09:46:21 -07003237 mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003238 mptsasInternalCtx =
3239 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003240 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003241
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003242 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07003243 devtverboseprintk((KERN_INFO MYNAM
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003244 ": Registered for IOC event notifications\n"));
3245 }
3246
Eric Mooredf9e0622007-01-29 09:46:21 -07003247 if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003248 dprintk((KERN_INFO MYNAM
3249 ": Registered for IOC reset notifications\n"));
3250 }
3251
3252 return pci_register_driver(&mptsas_driver);
3253}
3254
3255static void __exit
3256mptsas_exit(void)
3257{
3258 pci_unregister_driver(&mptsas_driver);
3259 sas_release_transport(mptsas_transport_template);
3260
3261 mpt_reset_deregister(mptsasDoneCtx);
3262 mpt_event_deregister(mptsasDoneCtx);
3263
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003264 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003265 mpt_deregister(mptsasInternalCtx);
3266 mpt_deregister(mptsasTaskCtx);
3267 mpt_deregister(mptsasDoneCtx);
3268}
3269
3270module_init(mptsas_init);
3271module_exit(mptsas_exit);