blob: 0fb7d5881f4fab732855e2334bcf52f65829cebb [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 *
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01008 * Copyright (c) 2005-2006 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
70MODULE_AUTHOR(MODULEAUTHOR);
71MODULE_DESCRIPTION(my_NAME);
72MODULE_LICENSE("GPL");
73
74static int mpt_pq_filter;
75module_param(mpt_pq_filter, int, 0);
76MODULE_PARM_DESC(mpt_pq_filter,
77 "Enable peripheral qualifier filter: enable=1 "
78 "(default=0)");
79
80static int mpt_pt_clear;
81module_param(mpt_pt_clear, int, 0);
82MODULE_PARM_DESC(mpt_pt_clear,
83 "Clear persistency table: enable=1 "
84 "(default=MPTSCSIH_PT_CLEAR=0)");
85
86static int mptsasDoneCtx = -1;
87static int mptsasTaskCtx = -1;
88static int mptsasInternalCtx = -1; /* Used only for internal commands */
Christoph Hellwigda4fa652005-10-19 20:01:42 +020089static int mptsasMgmtCtx = -1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020090
91
Christoph Hellwig9a28f492006-01-13 18:04:41 +010092enum mptsas_hotplug_action {
93 MPTSAS_ADD_DEVICE,
94 MPTSAS_DEL_DEVICE,
Moore, Ericc73787ee2006-01-26 16:20:06 -070095 MPTSAS_ADD_RAID,
96 MPTSAS_DEL_RAID,
Moore, Ericbd23e942006-04-17 12:43:04 -060097 MPTSAS_IGNORE_EVENT,
Christoph Hellwig9a28f492006-01-13 18:04:41 +010098};
99
100struct mptsas_hotplug_event {
101 struct work_struct work;
102 MPT_ADAPTER *ioc;
103 enum mptsas_hotplug_action event_type;
104 u64 sas_address;
105 u32 channel;
106 u32 id;
107 u32 device_info;
108 u16 handle;
109 u16 parent_handle;
110 u8 phy_id;
Moore, Ericf44e5462006-03-14 09:14:21 -0700111 u8 phys_disk_num;
112 u8 phys_disk_num_valid;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100113};
114
Moore, Erice6b2d762006-03-14 09:14:24 -0700115struct mptsas_discovery_event {
116 struct work_struct work;
117 MPT_ADAPTER *ioc;
118};
119
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200120/*
121 * SAS topology structures
122 *
123 * The MPT Fusion firmware interface spreads information about the
124 * SAS topology over many manufacture pages, thus we need some data
125 * structure to collect it and process it for the SAS transport class.
126 */
127
128struct mptsas_devinfo {
129 u16 handle; /* unique id to address this device */
Moore, Ericc73787ee2006-01-26 16:20:06 -0700130 u16 handle_parent; /* unique id to address parent device */
Christoph Hellwige3094442006-02-16 13:25:36 +0100131 u16 handle_enclosure; /* enclosure identifier of the enclosure */
132 u16 slot; /* physical slot in enclosure */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200133 u8 phy_id; /* phy number of parent device */
134 u8 port_id; /* sas physical port this device
135 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100136 u8 id; /* logical target id of this device */
137 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200138 u64 sas_address; /* WWN of this device,
139 SATA is assigned by HBA,expander */
140 u32 device_info; /* bitfield detailed info about this device */
141};
142
Eric Moore547f9a22006-06-27 14:42:12 -0600143/*
144 * Specific details on ports, wide/narrow
145 */
146struct mptsas_portinfo_details{
Eric Moore547f9a22006-06-27 14:42:12 -0600147 u16 num_phys; /* number of phys belong to this port */
148 u64 phy_bitmask; /* TODO, extend support for 255 phys */
149 struct sas_rphy *rphy; /* transport layer rphy object */
150 struct sas_port *port; /* transport layer port object */
151 struct scsi_target *starget;
152 struct mptsas_portinfo *port_info;
153};
154
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200155struct mptsas_phyinfo {
156 u8 phy_id; /* phy index */
Eric Moore547f9a22006-06-27 14:42:12 -0600157 u8 port_id; /* firmware port identifier */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200158 u8 negotiated_link_rate; /* nego'd link rate for this phy */
159 u8 hw_link_rate; /* hardware max/min phys link rate */
160 u8 programmed_link_rate; /* programmed max/min phy link rate */
Eric Moore547f9a22006-06-27 14:42:12 -0600161 u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200162 struct mptsas_devinfo identify; /* point to phy device info */
163 struct mptsas_devinfo attached; /* point to attached device info */
Eric Moore547f9a22006-06-27 14:42:12 -0600164 struct sas_phy *phy; /* transport layer phy object */
165 struct mptsas_portinfo *portinfo;
166 struct mptsas_portinfo_details * port_details;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200167};
168
169struct mptsas_portinfo {
170 struct list_head list;
171 u16 handle; /* unique id to address this */
Eric Moore547f9a22006-06-27 14:42:12 -0600172 u16 num_phys; /* number of phys */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200173 struct mptsas_phyinfo *phy_info;
174};
175
Christoph Hellwige3094442006-02-16 13:25:36 +0100176struct mptsas_enclosure {
177 u64 enclosure_logical_id; /* The WWN for the enclosure */
178 u16 enclosure_handle; /* unique id to address this */
179 u16 flags; /* details enclosure management */
180 u16 num_slot; /* num slots */
181 u16 start_slot; /* first slot */
182 u8 start_id; /* starting logical target id */
183 u8 start_channel; /* starting logical channel id */
184 u8 sep_id; /* SEP device logical target id */
185 u8 sep_channel; /* SEP channel logical channel id */
186};
187
Eric Moore547f9a22006-06-27 14:42:12 -0600188#ifdef MPT_DEBUG_SAS
Christoph Hellwigb5141122005-10-28 22:07:41 +0200189static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
190{
191 printk("---- IO UNIT PAGE 0 ------------\n");
192 printk("Handle=0x%X\n",
193 le16_to_cpu(phy_data->AttachedDeviceHandle));
194 printk("Controller Handle=0x%X\n",
195 le16_to_cpu(phy_data->ControllerDevHandle));
196 printk("Port=0x%X\n", phy_data->Port);
197 printk("Port Flags=0x%X\n", phy_data->PortFlags);
198 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
199 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
200 printk("Controller PHY Device Info=0x%X\n",
201 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
202 printk("DiscoveryStatus=0x%X\n",
203 le32_to_cpu(phy_data->DiscoveryStatus));
204 printk("\n");
205}
206
207static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
208{
209 __le64 sas_address;
210
211 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
212
213 printk("---- SAS PHY PAGE 0 ------------\n");
214 printk("Attached Device Handle=0x%X\n",
215 le16_to_cpu(pg0->AttachedDevHandle));
216 printk("SAS Address=0x%llX\n",
217 (unsigned long long)le64_to_cpu(sas_address));
218 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
219 printk("Attached Device Info=0x%X\n",
220 le32_to_cpu(pg0->AttachedDeviceInfo));
221 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
222 printk("Change Count=0x%X\n", pg0->ChangeCount);
223 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
224 printk("\n");
225}
226
227static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
228{
229 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200230 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
231 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200232 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200233 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
234 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
235 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200236}
237
238static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
239{
240 __le64 sas_address;
241
242 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
243
244 printk("---- SAS DEVICE PAGE 0 ---------\n");
245 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
Christoph Hellwige3094442006-02-16 13:25:36 +0100246 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200247 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
248 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
249 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
250 printk("Target ID=0x%X\n", pg0->TargetID);
251 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200252 /* The PhyNum field specifies the PHY number of the parent
253 * device this device is linked to
254 */
255 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
256 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200257 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
258 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
259 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
260 printk("\n");
261}
262
263static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
264{
265 printk("---- SAS EXPANDER PAGE 1 ------------\n");
266
267 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200268 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200269 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
270 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
271 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
272 printk("Owner Device Handle=0x%X\n",
273 le16_to_cpu(pg1->OwnerDevHandle));
274 printk("Attached Device Handle=0x%X\n",
275 le16_to_cpu(pg1->AttachedDevHandle));
276}
277#else
278#define mptsas_print_phy_data(phy_data) do { } while (0)
279#define mptsas_print_phy_pg0(pg0) do { } while (0)
280#define mptsas_print_phy_pg1(pg1) do { } while (0)
281#define mptsas_print_device_pg0(pg0) do { } while (0)
282#define mptsas_print_expander_pg1(pg1) do { } while (0)
283#endif
284
Christoph Hellwige3094442006-02-16 13:25:36 +0100285static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
286{
287 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
288 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
289}
290
291static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
292{
293 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
294 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
295}
296
Moore, Erice6b2d762006-03-14 09:14:24 -0700297/*
298 * mptsas_find_portinfo_by_handle
299 *
300 * This function should be called with the sas_topology_mutex already held
301 */
302static struct mptsas_portinfo *
303mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
304{
305 struct mptsas_portinfo *port_info, *rc=NULL;
306 int i;
307
308 list_for_each_entry(port_info, &ioc->sas_topology, list)
309 for (i = 0; i < port_info->num_phys; i++)
310 if (port_info->phy_info[i].identify.handle == handle) {
311 rc = port_info;
312 goto out;
313 }
314 out:
315 return rc;
316}
317
Moore, Ericbd23e942006-04-17 12:43:04 -0600318/*
319 * Returns true if there is a scsi end device
320 */
321static inline int
322mptsas_is_end_device(struct mptsas_devinfo * attached)
323{
Eric Moore547f9a22006-06-27 14:42:12 -0600324 if ((attached->sas_address) &&
Moore, Ericbd23e942006-04-17 12:43:04 -0600325 (attached->device_info &
326 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
327 ((attached->device_info &
328 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
329 (attached->device_info &
330 MPI_SAS_DEVICE_INFO_STP_TARGET) |
331 (attached->device_info &
332 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
333 return 1;
334 else
335 return 0;
336}
337
Eric Moore547f9a22006-06-27 14:42:12 -0600338/* no mutex */
Eric Moore376ac832006-06-29 17:36:26 -0600339static void
Eric Moore547f9a22006-06-27 14:42:12 -0600340mptsas_port_delete(struct mptsas_portinfo_details * port_details)
341{
342 struct mptsas_portinfo *port_info;
343 struct mptsas_phyinfo *phy_info;
344 u8 i;
345
346 if (!port_details)
347 return;
348
349 port_info = port_details->port_info;
350 phy_info = port_info->phy_info;
351
Eric Mooredc22f162006-07-06 11:23:14 -0600352 dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
Eric Moore547f9a22006-06-27 14:42:12 -0600353 "bitmask=0x%016llX\n",
Eric Mooredc22f162006-07-06 11:23:14 -0600354 __FUNCTION__, port_details, port_details->num_phys,
355 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600356
357 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
358 if(phy_info->port_details != port_details)
359 continue;
360 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
361 phy_info->port_details = NULL;
362 }
363 kfree(port_details);
364}
365
366static inline struct sas_rphy *
367mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
368{
369 if (phy_info->port_details)
370 return phy_info->port_details->rphy;
371 else
372 return NULL;
373}
374
375static inline void
376mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
377{
378 if (phy_info->port_details) {
379 phy_info->port_details->rphy = rphy;
380 dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
381 }
382
383#ifdef MPT_DEBUG_SAS_WIDE
384 if (rphy) {
385 dev_printk(KERN_DEBUG, &rphy->dev, "add:");
386 printk("rphy=%p release=%p\n",
387 rphy, rphy->dev.release);
388 }
389#endif
390}
391
392static inline struct sas_port *
393mptsas_get_port(struct mptsas_phyinfo *phy_info)
394{
395 if (phy_info->port_details)
396 return phy_info->port_details->port;
397 else
398 return NULL;
399}
400
401static inline void
402mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port)
403{
404 if (phy_info->port_details)
405 phy_info->port_details->port = port;
406
407#ifdef MPT_DEBUG_SAS_WIDE
408 if (port) {
409 dev_printk(KERN_DEBUG, &port->dev, "add: ");
410 printk("port=%p release=%p\n",
411 port, port->dev.release);
412 }
413#endif
414}
415
416static inline struct scsi_target *
417mptsas_get_starget(struct mptsas_phyinfo *phy_info)
418{
419 if (phy_info->port_details)
420 return phy_info->port_details->starget;
421 else
422 return NULL;
423}
424
425static inline void
426mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
427starget)
428{
429 if (phy_info->port_details)
430 phy_info->port_details->starget = starget;
431}
432
433
434/*
435 * mptsas_setup_wide_ports
436 *
437 * Updates for new and existing narrow/wide port configuration
438 * in the sas_topology
439 */
Eric Moore376ac832006-06-29 17:36:26 -0600440static void
Eric Moore547f9a22006-06-27 14:42:12 -0600441mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
442{
443 struct mptsas_portinfo_details * port_details;
444 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
445 u64 sas_address;
446 int i, j;
447
448 mutex_lock(&ioc->sas_topology_mutex);
449
450 phy_info = port_info->phy_info;
451 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
452 if (phy_info->attached.handle)
453 continue;
454 port_details = phy_info->port_details;
455 if (!port_details)
456 continue;
457 if (port_details->num_phys < 2)
458 continue;
459 /*
460 * Removing a phy from a port, letting the last
461 * phy be removed by firmware events.
462 */
463 dsaswideprintk((KERN_DEBUG
Eric Mooredc22f162006-07-06 11:23:14 -0600464 "%s: [%p]: deleting phy = %d\n",
465 __FUNCTION__, port_details, i));
Eric Moore547f9a22006-06-27 14:42:12 -0600466 port_details->num_phys--;
467 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
468 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
469 sas_port_delete_phy(port_details->port, phy_info->phy);
470 phy_info->port_details = NULL;
471 }
472
473 /*
474 * Populate and refresh the tree
475 */
476 phy_info = port_info->phy_info;
477 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
478 sas_address = phy_info->attached.sas_address;
479 dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
480 i, sas_address));
481 if (!sas_address)
482 continue;
483 port_details = phy_info->port_details;
484 /*
485 * Forming a port
486 */
487 if (!port_details) {
488 port_details = kzalloc(sizeof(*port_details),
489 GFP_KERNEL);
490 if (!port_details)
491 goto out;
492 port_details->num_phys = 1;
493 port_details->port_info = port_info;
Eric Moore547f9a22006-06-27 14:42:12 -0600494 if (phy_info->phy_id < 64 )
495 port_details->phy_bitmask |=
496 (1 << phy_info->phy_id);
497 phy_info->sas_port_add_phy=1;
498 dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
499 "phy_id=%d sas_address=0x%018llX\n",
500 i, sas_address));
501 phy_info->port_details = port_details;
502 }
503
504 if (i == port_info->num_phys - 1)
505 continue;
506 phy_info_cmp = &port_info->phy_info[i + 1];
507 for (j = i + 1 ; j < port_info->num_phys ; j++,
508 phy_info_cmp++) {
509 if (!phy_info_cmp->attached.sas_address)
510 continue;
511 if (sas_address != phy_info_cmp->attached.sas_address)
512 continue;
513 if (phy_info_cmp->port_details == port_details )
514 continue;
515 dsaswideprintk((KERN_DEBUG
516 "\t\tphy_id=%d sas_address=0x%018llX\n",
517 j, phy_info_cmp->attached.sas_address));
518 if (phy_info_cmp->port_details) {
519 port_details->rphy =
520 mptsas_get_rphy(phy_info_cmp);
521 port_details->port =
522 mptsas_get_port(phy_info_cmp);
523 port_details->starget =
524 mptsas_get_starget(phy_info_cmp);
Eric Moore547f9a22006-06-27 14:42:12 -0600525 port_details->num_phys =
526 phy_info_cmp->port_details->num_phys;
Eric Moore547f9a22006-06-27 14:42:12 -0600527 if (!phy_info_cmp->port_details->num_phys)
528 kfree(phy_info_cmp->port_details);
529 } else
530 phy_info_cmp->sas_port_add_phy=1;
531 /*
532 * Adding a phy to a port
533 */
534 phy_info_cmp->port_details = port_details;
535 if (phy_info_cmp->phy_id < 64 )
536 port_details->phy_bitmask |=
537 (1 << phy_info_cmp->phy_id);
538 port_details->num_phys++;
539 }
540 }
541
542 out:
543
544#ifdef MPT_DEBUG_SAS_WIDE
545 for (i = 0; i < port_info->num_phys; i++) {
546 port_details = port_info->phy_info[i].port_details;
547 if (!port_details)
548 continue;
549 dsaswideprintk((KERN_DEBUG
Eric Mooredc22f162006-07-06 11:23:14 -0600550 "%s: [%p]: phy_id=%02d num_phys=%02d "
Eric Moore547f9a22006-06-27 14:42:12 -0600551 "bitmask=0x%016llX\n",
552 __FUNCTION__,
Eric Mooredc22f162006-07-06 11:23:14 -0600553 port_details, i, port_details->num_phys,
554 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600555 dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
556 port_details->port, port_details->rphy));
557 }
558 dsaswideprintk((KERN_DEBUG"\n"));
559#endif
560 mutex_unlock(&ioc->sas_topology_mutex);
561}
562
563static void
564mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
565{
566 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
567
568 if (mptscsih_TMHandler(hd,
569 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
570 vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) {
571 hd->tmPending = 0;
572 hd->tmState = TM_STATE_NONE;
573 printk(MYIOC_s_WARN_FMT
574 "Error processing TaskMgmt id=%d TARGET_RESET\n",
575 ioc->name, vtarget->target_id);
576 }
577}
578
Christoph Hellwige3094442006-02-16 13:25:36 +0100579static int
Moore, Eric52435432006-03-14 09:14:15 -0700580mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
Christoph Hellwige3094442006-02-16 13:25:36 +0100581 u32 form, u32 form_specific)
582{
583 ConfigExtendedPageHeader_t hdr;
584 CONFIGPARMS cfg;
585 SasEnclosurePage0_t *buffer;
586 dma_addr_t dma_handle;
587 int error;
588 __le64 le_identifier;
589
590 memset(&hdr, 0, sizeof(hdr));
591 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
592 hdr.PageNumber = 0;
593 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
594 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
595
596 cfg.cfghdr.ehdr = &hdr;
597 cfg.physAddr = -1;
598 cfg.pageAddr = form + form_specific;
599 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
600 cfg.dir = 0; /* read */
601 cfg.timeout = 10;
602
603 error = mpt_config(ioc, &cfg);
604 if (error)
605 goto out;
606 if (!hdr.ExtPageLength) {
607 error = -ENXIO;
608 goto out;
609 }
610
611 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
612 &dma_handle);
613 if (!buffer) {
614 error = -ENOMEM;
615 goto out;
616 }
617
618 cfg.physAddr = dma_handle;
619 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
620
621 error = mpt_config(ioc, &cfg);
622 if (error)
623 goto out_free_consistent;
624
625 /* save config data */
626 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
627 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
628 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
629 enclosure->flags = le16_to_cpu(buffer->Flags);
630 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
631 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
632 enclosure->start_id = buffer->StartTargetID;
633 enclosure->start_channel = buffer->StartBus;
634 enclosure->sep_id = buffer->SEPTargetID;
635 enclosure->sep_channel = buffer->SEPBus;
636
637 out_free_consistent:
638 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
639 buffer, dma_handle);
640 out:
641 return error;
642}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200643
James Bottomleyf013db32006-03-18 14:54:36 -0600644static int
645mptsas_slave_configure(struct scsi_device *sdev)
646{
Moore, Eric3c0c25b2006-04-13 16:08:17 -0600647 struct Scsi_Host *host = sdev->host;
648 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
649
650 /*
651 * RAID volumes placed beyond the last expected port.
652 * Ignore sending sas mode pages in that case..
653 */
654 if (sdev->channel < hd->ioc->num_ports)
655 sas_read_port_mode_page(sdev);
James Bottomleyf013db32006-03-18 14:54:36 -0600656
657 return mptscsih_slave_configure(sdev);
658}
659
Eric Moore547f9a22006-06-27 14:42:12 -0600660static int
661mptsas_target_alloc(struct scsi_target *starget)
662{
663 struct Scsi_Host *host = dev_to_shost(&starget->dev);
664 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
665 VirtTarget *vtarget;
666 u32 target_id;
667 u32 channel;
668 struct sas_rphy *rphy;
669 struct mptsas_portinfo *p;
670 int i;
671
672 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
673 if (!vtarget)
674 return -ENOMEM;
675
676 vtarget->starget = starget;
677 vtarget->ioc_id = hd->ioc->id;
678 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
679
680 target_id = starget->id;
681 channel = 0;
682
683 hd->Targets[target_id] = vtarget;
684
685 /*
686 * RAID volumes placed beyond the last expected port.
687 */
688 if (starget->channel == hd->ioc->num_ports)
689 goto out;
690
691 rphy = dev_to_rphy(starget->dev.parent);
692 mutex_lock(&hd->ioc->sas_topology_mutex);
693 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
694 for (i = 0; i < p->num_phys; i++) {
695 if (p->phy_info[i].attached.sas_address !=
696 rphy->identify.sas_address)
697 continue;
698 target_id = p->phy_info[i].attached.id;
699 channel = p->phy_info[i].attached.channel;
700 mptsas_set_starget(&p->phy_info[i], starget);
701
702 /*
703 * Exposing hidden raid components
704 */
705 if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
706 target_id = mptscsih_raid_id_to_num(hd,
707 target_id);
708 vtarget->tflags |=
709 MPT_TARGET_FLAGS_RAID_COMPONENT;
710 }
711 mutex_unlock(&hd->ioc->sas_topology_mutex);
712 goto out;
713 }
714 }
715 mutex_unlock(&hd->ioc->sas_topology_mutex);
716
717 kfree(vtarget);
718 return -ENXIO;
719
720 out:
721 vtarget->target_id = target_id;
722 vtarget->bus_id = channel;
723 starget->hostdata = vtarget;
724 return 0;
725}
726
727static void
728mptsas_target_destroy(struct scsi_target *starget)
729{
730 struct Scsi_Host *host = dev_to_shost(&starget->dev);
731 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
732 struct sas_rphy *rphy;
733 struct mptsas_portinfo *p;
734 int i;
735
736 if (!starget->hostdata)
737 return;
738
739 if (starget->channel == hd->ioc->num_ports)
740 goto out;
741
742 rphy = dev_to_rphy(starget->dev.parent);
743 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
744 for (i = 0; i < p->num_phys; i++) {
745 if (p->phy_info[i].attached.sas_address !=
746 rphy->identify.sas_address)
747 continue;
748 mptsas_set_starget(&p->phy_info[i], NULL);
749 goto out;
750 }
751 }
752
753 out:
754 kfree(starget->hostdata);
755 starget->hostdata = NULL;
756}
757
758
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200759static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700760mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200761{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700762 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200763 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
764 struct sas_rphy *rphy;
765 struct mptsas_portinfo *p;
766 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700767 struct scsi_target *starget;
Eric Moore547f9a22006-06-27 14:42:12 -0600768 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200769
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100770 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200771 if (!vdev) {
Eric Moore547f9a22006-06-27 14:42:12 -0600772 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200773 hd->ioc->name, sizeof(VirtDevice));
774 return -ENOMEM;
775 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700776 starget = scsi_target(sdev);
Eric Moore547f9a22006-06-27 14:42:12 -0600777 vdev->vtarget = starget->hostdata;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200778
Moore, Eric816aa902006-01-13 16:25:20 -0700779 /*
Eric Moore547f9a22006-06-27 14:42:12 -0600780 * RAID volumes placed beyond the last expected port.
781 */
782 if (sdev->channel == hd->ioc->num_ports)
Moore, Eric816aa902006-01-13 16:25:20 -0700783 goto out;
Moore, Eric816aa902006-01-13 16:25:20 -0700784
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700785 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100786 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200787 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
788 for (i = 0; i < p->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -0600789 if (p->phy_info[i].attached.sas_address !=
790 rphy->identify.sas_address)
791 continue;
792 vdev->lun = sdev->lun;
793 /*
794 * Exposing hidden raid components
795 */
796 if (mptscsih_is_phys_disk(hd->ioc,
797 p->phy_info[i].attached.id))
798 sdev->no_uld_attach = 1;
799 mutex_unlock(&hd->ioc->sas_topology_mutex);
800 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200801 }
802 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100803 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200804
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200805 kfree(vdev);
Christoph Hellwig23f236e2006-01-30 19:00:43 +0100806 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200807
808 out:
Eric Moore547f9a22006-06-27 14:42:12 -0600809 vdev->vtarget->num_luns++;
810 sdev->hostdata = vdev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200811 return 0;
812}
813
Eric Moore547f9a22006-06-27 14:42:12 -0600814static int
815mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100816{
Eric Moore547f9a22006-06-27 14:42:12 -0600817 VirtDevice *vdev = SCpnt->device->hostdata;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100818
Eric Moore547f9a22006-06-27 14:42:12 -0600819// scsi_print_command(SCpnt);
820 if (vdev->vtarget->deleted) {
821 SCpnt->result = DID_NO_CONNECT << 16;
822 done(SCpnt);
823 return 0;
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700824 }
Eric Moore547f9a22006-06-27 14:42:12 -0600825
826 return mptscsih_qcmd(SCpnt,done);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100827}
828
Eric Moore547f9a22006-06-27 14:42:12 -0600829
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200830static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700831 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200832 .proc_name = "mptsas",
833 .proc_info = mptscsih_proc_info,
834 .name = "MPT SPI Host",
835 .info = mptscsih_info,
Eric Moore547f9a22006-06-27 14:42:12 -0600836 .queuecommand = mptsas_qcmd,
837 .target_alloc = mptsas_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200838 .slave_alloc = mptsas_slave_alloc,
James Bottomleyf013db32006-03-18 14:54:36 -0600839 .slave_configure = mptsas_slave_configure,
Eric Moore547f9a22006-06-27 14:42:12 -0600840 .target_destroy = mptsas_target_destroy,
841 .slave_destroy = mptscsih_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200842 .change_queue_depth = mptscsih_change_queue_depth,
843 .eh_abort_handler = mptscsih_abort,
844 .eh_device_reset_handler = mptscsih_dev_reset,
845 .eh_bus_reset_handler = mptscsih_bus_reset,
846 .eh_host_reset_handler = mptscsih_host_reset,
847 .bios_param = mptscsih_bios_param,
848 .can_queue = MPT_FC_CAN_QUEUE,
849 .this_id = -1,
850 .sg_tablesize = MPT_SCSI_SG_DEPTH,
851 .max_sectors = 8192,
852 .cmd_per_lun = 7,
853 .use_clustering = ENABLE_CLUSTERING,
854};
855
Christoph Hellwigb5141122005-10-28 22:07:41 +0200856static int mptsas_get_linkerrors(struct sas_phy *phy)
857{
858 MPT_ADAPTER *ioc = phy_to_ioc(phy);
859 ConfigExtendedPageHeader_t hdr;
860 CONFIGPARMS cfg;
861 SasPhyPage1_t *buffer;
862 dma_addr_t dma_handle;
863 int error;
864
865 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
866 hdr.ExtPageLength = 0;
867 hdr.PageNumber = 1 /* page number 1*/;
868 hdr.Reserved1 = 0;
869 hdr.Reserved2 = 0;
870 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
871 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
872
873 cfg.cfghdr.ehdr = &hdr;
874 cfg.physAddr = -1;
875 cfg.pageAddr = phy->identify.phy_identifier;
876 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
877 cfg.dir = 0; /* read */
878 cfg.timeout = 10;
879
880 error = mpt_config(ioc, &cfg);
881 if (error)
882 return error;
883 if (!hdr.ExtPageLength)
884 return -ENXIO;
885
886 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
887 &dma_handle);
888 if (!buffer)
889 return -ENOMEM;
890
891 cfg.physAddr = dma_handle;
892 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
893
894 error = mpt_config(ioc, &cfg);
895 if (error)
896 goto out_free_consistent;
897
898 mptsas_print_phy_pg1(buffer);
899
900 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
901 phy->running_disparity_error_count =
902 le32_to_cpu(buffer->RunningDisparityErrorCount);
903 phy->loss_of_dword_sync_count =
904 le32_to_cpu(buffer->LossDwordSynchCount);
905 phy->phy_reset_problem_count =
906 le32_to_cpu(buffer->PhyResetProblemCount);
907
908 out_free_consistent:
909 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
910 buffer, dma_handle);
911 return error;
912}
913
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200914static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
915 MPT_FRAME_HDR *reply)
916{
917 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
918 if (reply != NULL) {
919 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
920 memcpy(ioc->sas_mgmt.reply, reply,
921 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
922 }
923 complete(&ioc->sas_mgmt.done);
924 return 1;
925}
926
927static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
928{
929 MPT_ADAPTER *ioc = phy_to_ioc(phy);
930 SasIoUnitControlRequest_t *req;
931 SasIoUnitControlReply_t *reply;
932 MPT_FRAME_HDR *mf;
933 MPIHeader_t *hdr;
934 unsigned long timeleft;
935 int error = -ERESTARTSYS;
936
937 /* not implemented for expanders */
938 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
939 return -ENXIO;
940
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100941 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200942 goto out;
943
944 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
945 if (!mf) {
946 error = -ENOMEM;
947 goto out_unlock;
948 }
949
950 hdr = (MPIHeader_t *) mf;
951 req = (SasIoUnitControlRequest_t *)mf;
952 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
953 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
954 req->MsgContext = hdr->MsgContext;
955 req->Operation = hard_reset ?
956 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
957 req->PhyNum = phy->identify.phy_identifier;
958
959 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
960
961 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
962 10 * HZ);
963 if (!timeleft) {
964 /* On timeout reset the board */
965 mpt_free_msg_frame(ioc, mf);
966 mpt_HardResetHandler(ioc, CAN_SLEEP);
967 error = -ETIMEDOUT;
968 goto out_unlock;
969 }
970
971 /* a reply frame is expected */
972 if ((ioc->sas_mgmt.status &
973 MPT_IOCTL_STATUS_RF_VALID) == 0) {
974 error = -ENXIO;
975 goto out_unlock;
976 }
977
978 /* process the completed Reply Message Frame */
979 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
980 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
981 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
982 __FUNCTION__,
983 reply->IOCStatus,
984 reply->IOCLogInfo);
985 error = -ENXIO;
986 goto out_unlock;
987 }
988
989 error = 0;
990
991 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100992 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200993 out:
994 return error;
995}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200996
Christoph Hellwige3094442006-02-16 13:25:36 +0100997static int
998mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
999{
1000 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1001 int i, error;
1002 struct mptsas_portinfo *p;
1003 struct mptsas_enclosure enclosure_info;
1004 u64 enclosure_handle;
1005
1006 mutex_lock(&ioc->sas_topology_mutex);
1007 list_for_each_entry(p, &ioc->sas_topology, list) {
1008 for (i = 0; i < p->num_phys; i++) {
1009 if (p->phy_info[i].attached.sas_address ==
1010 rphy->identify.sas_address) {
1011 enclosure_handle = p->phy_info[i].
1012 attached.handle_enclosure;
1013 goto found_info;
1014 }
1015 }
1016 }
1017 mutex_unlock(&ioc->sas_topology_mutex);
1018 return -ENXIO;
1019
1020 found_info:
1021 mutex_unlock(&ioc->sas_topology_mutex);
1022 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -07001023 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +01001024 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1025 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1026 if (!error)
1027 *identifier = enclosure_info.enclosure_logical_id;
1028 return error;
1029}
1030
1031static int
1032mptsas_get_bay_identifier(struct sas_rphy *rphy)
1033{
1034 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1035 struct mptsas_portinfo *p;
1036 int i, rc;
1037
1038 mutex_lock(&ioc->sas_topology_mutex);
1039 list_for_each_entry(p, &ioc->sas_topology, list) {
1040 for (i = 0; i < p->num_phys; i++) {
1041 if (p->phy_info[i].attached.sas_address ==
1042 rphy->identify.sas_address) {
1043 rc = p->phy_info[i].attached.slot;
1044 goto out;
1045 }
1046 }
1047 }
1048 rc = -ENXIO;
1049 out:
1050 mutex_unlock(&ioc->sas_topology_mutex);
1051 return rc;
1052}
1053
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001054static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +02001055 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +01001056 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1057 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001058 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001059};
1060
1061static struct scsi_transport_template *mptsas_transport_template;
1062
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001063static int
1064mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1065{
1066 ConfigExtendedPageHeader_t hdr;
1067 CONFIGPARMS cfg;
1068 SasIOUnitPage0_t *buffer;
1069 dma_addr_t dma_handle;
1070 int error, i;
1071
1072 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1073 hdr.ExtPageLength = 0;
1074 hdr.PageNumber = 0;
1075 hdr.Reserved1 = 0;
1076 hdr.Reserved2 = 0;
1077 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1078 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1079
1080 cfg.cfghdr.ehdr = &hdr;
1081 cfg.physAddr = -1;
1082 cfg.pageAddr = 0;
1083 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1084 cfg.dir = 0; /* read */
1085 cfg.timeout = 10;
1086
1087 error = mpt_config(ioc, &cfg);
1088 if (error)
1089 goto out;
1090 if (!hdr.ExtPageLength) {
1091 error = -ENXIO;
1092 goto out;
1093 }
1094
1095 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1096 &dma_handle);
1097 if (!buffer) {
1098 error = -ENOMEM;
1099 goto out;
1100 }
1101
1102 cfg.physAddr = dma_handle;
1103 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1104
1105 error = mpt_config(ioc, &cfg);
1106 if (error)
1107 goto out_free_consistent;
1108
1109 port_info->num_phys = buffer->NumPhys;
1110 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001111 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001112 if (!port_info->phy_info) {
1113 error = -ENOMEM;
1114 goto out_free_consistent;
1115 }
1116
Moore, Ericdb9c9172006-03-14 09:14:18 -07001117 if (port_info->num_phys)
1118 port_info->handle =
1119 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001120 for (i = 0; i < port_info->num_phys; i++) {
1121 mptsas_print_phy_data(&buffer->PhyData[i]);
1122 port_info->phy_info[i].phy_id = i;
1123 port_info->phy_info[i].port_id =
1124 buffer->PhyData[i].Port;
1125 port_info->phy_info[i].negotiated_link_rate =
1126 buffer->PhyData[i].NegotiatedLinkRate;
Eric Moore547f9a22006-06-27 14:42:12 -06001127 port_info->phy_info[i].portinfo = port_info;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001128 }
1129
1130 out_free_consistent:
1131 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1132 buffer, dma_handle);
1133 out:
1134 return error;
1135}
1136
1137static int
1138mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1139 u32 form, u32 form_specific)
1140{
1141 ConfigExtendedPageHeader_t hdr;
1142 CONFIGPARMS cfg;
1143 SasPhyPage0_t *buffer;
1144 dma_addr_t dma_handle;
1145 int error;
1146
1147 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1148 hdr.ExtPageLength = 0;
1149 hdr.PageNumber = 0;
1150 hdr.Reserved1 = 0;
1151 hdr.Reserved2 = 0;
1152 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1153 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1154
1155 cfg.cfghdr.ehdr = &hdr;
1156 cfg.dir = 0; /* read */
1157 cfg.timeout = 10;
1158
1159 /* Get Phy Pg 0 for each Phy. */
1160 cfg.physAddr = -1;
1161 cfg.pageAddr = form + form_specific;
1162 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1163
1164 error = mpt_config(ioc, &cfg);
1165 if (error)
1166 goto out;
1167
1168 if (!hdr.ExtPageLength) {
1169 error = -ENXIO;
1170 goto out;
1171 }
1172
1173 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1174 &dma_handle);
1175 if (!buffer) {
1176 error = -ENOMEM;
1177 goto out;
1178 }
1179
1180 cfg.physAddr = dma_handle;
1181 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1182
1183 error = mpt_config(ioc, &cfg);
1184 if (error)
1185 goto out_free_consistent;
1186
1187 mptsas_print_phy_pg0(buffer);
1188
1189 phy_info->hw_link_rate = buffer->HwLinkRate;
1190 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1191 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1192 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1193
1194 out_free_consistent:
1195 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1196 buffer, dma_handle);
1197 out:
1198 return error;
1199}
1200
1201static int
1202mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1203 u32 form, u32 form_specific)
1204{
1205 ConfigExtendedPageHeader_t hdr;
1206 CONFIGPARMS cfg;
1207 SasDevicePage0_t *buffer;
1208 dma_addr_t dma_handle;
1209 __le64 sas_address;
Moore, Ericbd23e942006-04-17 12:43:04 -06001210 int error=0;
1211
1212 if (ioc->sas_discovery_runtime &&
1213 mptsas_is_end_device(device_info))
1214 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001215
1216 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1217 hdr.ExtPageLength = 0;
1218 hdr.PageNumber = 0;
1219 hdr.Reserved1 = 0;
1220 hdr.Reserved2 = 0;
1221 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1222 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1223
1224 cfg.cfghdr.ehdr = &hdr;
1225 cfg.pageAddr = form + form_specific;
1226 cfg.physAddr = -1;
1227 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1228 cfg.dir = 0; /* read */
1229 cfg.timeout = 10;
1230
Moore, Ericdb9c9172006-03-14 09:14:18 -07001231 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001232 error = mpt_config(ioc, &cfg);
1233 if (error)
1234 goto out;
1235 if (!hdr.ExtPageLength) {
1236 error = -ENXIO;
1237 goto out;
1238 }
1239
1240 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1241 &dma_handle);
1242 if (!buffer) {
1243 error = -ENOMEM;
1244 goto out;
1245 }
1246
1247 cfg.physAddr = dma_handle;
1248 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1249
1250 error = mpt_config(ioc, &cfg);
1251 if (error)
1252 goto out_free_consistent;
1253
1254 mptsas_print_device_pg0(buffer);
1255
1256 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001257 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +01001258 device_info->handle_enclosure =
1259 le16_to_cpu(buffer->EnclosureHandle);
1260 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001261 device_info->phy_id = buffer->PhyNum;
1262 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001263 device_info->id = buffer->TargetID;
1264 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001265 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1266 device_info->sas_address = le64_to_cpu(sas_address);
1267 device_info->device_info =
1268 le32_to_cpu(buffer->DeviceInfo);
1269
1270 out_free_consistent:
1271 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1272 buffer, dma_handle);
1273 out:
1274 return error;
1275}
1276
1277static int
1278mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1279 u32 form, u32 form_specific)
1280{
1281 ConfigExtendedPageHeader_t hdr;
1282 CONFIGPARMS cfg;
1283 SasExpanderPage0_t *buffer;
1284 dma_addr_t dma_handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001285 int i, error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001286
1287 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1288 hdr.ExtPageLength = 0;
1289 hdr.PageNumber = 0;
1290 hdr.Reserved1 = 0;
1291 hdr.Reserved2 = 0;
1292 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1293 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1294
1295 cfg.cfghdr.ehdr = &hdr;
1296 cfg.physAddr = -1;
1297 cfg.pageAddr = form + form_specific;
1298 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1299 cfg.dir = 0; /* read */
1300 cfg.timeout = 10;
1301
Moore, Ericdb9c9172006-03-14 09:14:18 -07001302 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001303 error = mpt_config(ioc, &cfg);
1304 if (error)
1305 goto out;
1306
1307 if (!hdr.ExtPageLength) {
1308 error = -ENXIO;
1309 goto out;
1310 }
1311
1312 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1313 &dma_handle);
1314 if (!buffer) {
1315 error = -ENOMEM;
1316 goto out;
1317 }
1318
1319 cfg.physAddr = dma_handle;
1320 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1321
1322 error = mpt_config(ioc, &cfg);
1323 if (error)
1324 goto out_free_consistent;
1325
1326 /* save config data */
1327 port_info->num_phys = buffer->NumPhys;
1328 port_info->handle = le16_to_cpu(buffer->DevHandle);
1329 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001330 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001331 if (!port_info->phy_info) {
1332 error = -ENOMEM;
1333 goto out_free_consistent;
1334 }
1335
Eric Moore547f9a22006-06-27 14:42:12 -06001336 for (i = 0; i < port_info->num_phys; i++)
1337 port_info->phy_info[i].portinfo = port_info;
1338
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001339 out_free_consistent:
1340 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1341 buffer, dma_handle);
1342 out:
1343 return error;
1344}
1345
1346static int
1347mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1348 u32 form, u32 form_specific)
1349{
1350 ConfigExtendedPageHeader_t hdr;
1351 CONFIGPARMS cfg;
1352 SasExpanderPage1_t *buffer;
1353 dma_addr_t dma_handle;
Moore, Ericbd23e942006-04-17 12:43:04 -06001354 int error=0;
1355
1356 if (ioc->sas_discovery_runtime &&
1357 mptsas_is_end_device(&phy_info->attached))
1358 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001359
1360 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1361 hdr.ExtPageLength = 0;
1362 hdr.PageNumber = 1;
1363 hdr.Reserved1 = 0;
1364 hdr.Reserved2 = 0;
1365 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1366 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1367
1368 cfg.cfghdr.ehdr = &hdr;
1369 cfg.physAddr = -1;
1370 cfg.pageAddr = form + form_specific;
1371 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1372 cfg.dir = 0; /* read */
1373 cfg.timeout = 10;
1374
1375 error = mpt_config(ioc, &cfg);
1376 if (error)
1377 goto out;
1378
1379 if (!hdr.ExtPageLength) {
1380 error = -ENXIO;
1381 goto out;
1382 }
1383
1384 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1385 &dma_handle);
1386 if (!buffer) {
1387 error = -ENOMEM;
1388 goto out;
1389 }
1390
1391 cfg.physAddr = dma_handle;
1392 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1393
1394 error = mpt_config(ioc, &cfg);
1395 if (error)
1396 goto out_free_consistent;
1397
1398
1399 mptsas_print_expander_pg1(buffer);
1400
1401 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001402 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001403 phy_info->port_id = buffer->PhysicalPort;
1404 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1405 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1406 phy_info->hw_link_rate = buffer->HwLinkRate;
1407 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1408 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1409
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001410 out_free_consistent:
1411 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1412 buffer, dma_handle);
1413 out:
1414 return error;
1415}
1416
1417static void
1418mptsas_parse_device_info(struct sas_identify *identify,
1419 struct mptsas_devinfo *device_info)
1420{
1421 u16 protocols;
1422
1423 identify->sas_address = device_info->sas_address;
1424 identify->phy_identifier = device_info->phy_id;
1425
1426 /*
1427 * Fill in Phy Initiator Port Protocol.
1428 * Bits 6:3, more than one bit can be set, fall through cases.
1429 */
1430 protocols = device_info->device_info & 0x78;
1431 identify->initiator_port_protocols = 0;
1432 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1433 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1434 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1435 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1436 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1437 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1438 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1439 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1440
1441 /*
1442 * Fill in Phy Target Port Protocol.
1443 * Bits 10:7, more than one bit can be set, fall through cases.
1444 */
1445 protocols = device_info->device_info & 0x780;
1446 identify->target_port_protocols = 0;
1447 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1448 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1449 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1450 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1451 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1452 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1453 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1454 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1455
1456 /*
1457 * Fill in Attached device type.
1458 */
1459 switch (device_info->device_info &
1460 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1461 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1462 identify->device_type = SAS_PHY_UNUSED;
1463 break;
1464 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1465 identify->device_type = SAS_END_DEVICE;
1466 break;
1467 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1468 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1469 break;
1470 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1471 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1472 break;
1473 }
1474}
1475
1476static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001477 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001478{
Moore, Erice6b2d762006-03-14 09:14:24 -07001479 MPT_ADAPTER *ioc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001480 struct sas_phy *phy;
Eric Moore547f9a22006-06-27 14:42:12 -06001481 struct sas_port *port;
1482 int error = 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001483
Eric Moore547f9a22006-06-27 14:42:12 -06001484 if (!dev) {
1485 error = -ENODEV;
1486 goto out;
1487 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001488
1489 if (!phy_info->phy) {
1490 phy = sas_phy_alloc(dev, index);
Eric Moore547f9a22006-06-27 14:42:12 -06001491 if (!phy) {
1492 error = -ENOMEM;
1493 goto out;
1494 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001495 } else
1496 phy = phy_info->phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001497
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001498 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001499
1500 /*
1501 * Set Negotiated link rate.
1502 */
1503 switch (phy_info->negotiated_link_rate) {
1504 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001505 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001506 break;
1507 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001508 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001509 break;
1510 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001511 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001512 break;
1513 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001514 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001515 break;
1516 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1517 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1518 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001519 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001520 break;
1521 }
1522
1523 /*
1524 * Set Max hardware link rate.
1525 */
1526 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1527 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001528 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001529 break;
1530 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001531 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001532 break;
1533 default:
1534 break;
1535 }
1536
1537 /*
1538 * Set Max programmed link rate.
1539 */
1540 switch (phy_info->programmed_link_rate &
1541 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1542 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001543 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001544 break;
1545 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001546 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001547 break;
1548 default:
1549 break;
1550 }
1551
1552 /*
1553 * Set Min hardware link rate.
1554 */
1555 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1556 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001557 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001558 break;
1559 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001560 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001561 break;
1562 default:
1563 break;
1564 }
1565
1566 /*
1567 * Set Min programmed link rate.
1568 */
1569 switch (phy_info->programmed_link_rate &
1570 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1571 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001572 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001573 break;
1574 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001575 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001576 break;
1577 default:
1578 break;
1579 }
1580
Moore, Erice6b2d762006-03-14 09:14:24 -07001581 if (!phy_info->phy) {
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001582
Moore, Erice6b2d762006-03-14 09:14:24 -07001583 if (local)
1584 phy->local_attached = 1;
1585
1586 error = sas_phy_add(phy);
1587 if (error) {
1588 sas_phy_free(phy);
Eric Moore547f9a22006-06-27 14:42:12 -06001589 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001590 }
1591 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001592 }
1593
Eric Moore547f9a22006-06-27 14:42:12 -06001594 if (!phy_info->attached.handle ||
1595 !phy_info->port_details)
1596 goto out;
1597
1598 port = mptsas_get_port(phy_info);
1599 ioc = phy_to_ioc(phy_info->phy);
1600
1601 if (phy_info->sas_port_add_phy) {
1602
1603 if (!port) {
Eric Mooredc22f162006-07-06 11:23:14 -06001604 port = sas_port_alloc_num(dev);
Eric Moore547f9a22006-06-27 14:42:12 -06001605 if (!port) {
1606 error = -ENOMEM;
1607 goto out;
1608 }
1609 error = sas_port_add(port);
1610 if (error) {
1611 dfailprintk((MYIOC_s_ERR_FMT
1612 "%s: exit at line=%d\n", ioc->name,
1613 __FUNCTION__, __LINE__));
1614 goto out;
1615 }
1616 mptsas_set_port(phy_info, port);
Eric Mooredc22f162006-07-06 11:23:14 -06001617 dsaswideprintk((KERN_DEBUG
1618 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
1619 port, dev, port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06001620 }
1621 dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
1622 phy_info->phy_id));
1623 sas_port_add_phy(port, phy_info->phy);
1624 phy_info->sas_port_add_phy = 0;
1625 }
1626
1627 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
Moore, Erice6b2d762006-03-14 09:14:24 -07001628
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001629 struct sas_rphy *rphy;
James Bottomley2686de22006-06-30 12:54:02 -05001630 struct device *parent;
James Bottomleyf013db32006-03-18 14:54:36 -06001631 struct sas_identify identify;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001632
James Bottomley2686de22006-06-30 12:54:02 -05001633 parent = dev->parent->parent;
Moore, Erice6b2d762006-03-14 09:14:24 -07001634 /*
1635 * Let the hotplug_work thread handle processing
1636 * the adding/removing of devices that occur
1637 * after start of day.
1638 */
1639 if (ioc->sas_discovery_runtime &&
1640 mptsas_is_end_device(&phy_info->attached))
Eric Moore547f9a22006-06-27 14:42:12 -06001641 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001642
James Bottomleyf013db32006-03-18 14:54:36 -06001643 mptsas_parse_device_info(&identify, &phy_info->attached);
James Bottomley2686de22006-06-30 12:54:02 -05001644 if (scsi_is_host_device(parent)) {
1645 struct mptsas_portinfo *port_info;
1646 int i;
1647
1648 mutex_lock(&ioc->sas_topology_mutex);
1649 port_info = mptsas_find_portinfo_by_handle(ioc,
1650 ioc->handle);
1651 mutex_unlock(&ioc->sas_topology_mutex);
1652
1653 for (i = 0; i < port_info->num_phys; i++)
1654 if (port_info->phy_info[i].identify.sas_address ==
1655 identify.sas_address)
1656 goto out;
1657
1658 } else if (scsi_is_sas_rphy(parent)) {
1659 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
1660 if (identify.sas_address ==
1661 parent_rphy->identify.sas_address)
1662 goto out;
1663 }
1664
James Bottomleyf013db32006-03-18 14:54:36 -06001665 switch (identify.device_type) {
1666 case SAS_END_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001667 rphy = sas_end_device_alloc(port);
James Bottomleyf013db32006-03-18 14:54:36 -06001668 break;
1669 case SAS_EDGE_EXPANDER_DEVICE:
1670 case SAS_FANOUT_EXPANDER_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001671 rphy = sas_expander_alloc(port, identify.device_type);
James Bottomleyf013db32006-03-18 14:54:36 -06001672 break;
1673 default:
1674 rphy = NULL;
1675 break;
1676 }
Eric Moore547f9a22006-06-27 14:42:12 -06001677 if (!rphy) {
1678 dfailprintk((MYIOC_s_ERR_FMT
1679 "%s: exit at line=%d\n", ioc->name,
1680 __FUNCTION__, __LINE__));
1681 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001682 }
1683
Eric Moore547f9a22006-06-27 14:42:12 -06001684 rphy->identify = identify;
1685 error = sas_rphy_add(rphy);
1686 if (error) {
1687 dfailprintk((MYIOC_s_ERR_FMT
1688 "%s: exit at line=%d\n", ioc->name,
1689 __FUNCTION__, __LINE__));
1690 sas_rphy_free(rphy);
1691 goto out;
1692 }
1693 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001694 }
1695
Eric Moore547f9a22006-06-27 14:42:12 -06001696 out:
1697 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001698}
1699
1700static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001701mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001702{
Moore, Erice6b2d762006-03-14 09:14:24 -07001703 struct mptsas_portinfo *port_info, *hba;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001704 u32 handle = 0xFFFF;
1705 int error = -ENOMEM, i;
1706
Moore, Erice6b2d762006-03-14 09:14:24 -07001707 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
1708 if (! hba)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001709 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001710
Moore, Erice6b2d762006-03-14 09:14:24 -07001711 error = mptsas_sas_io_unit_pg0(ioc, hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001712 if (error)
1713 goto out_free_port_info;
1714
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001715 mutex_lock(&ioc->sas_topology_mutex);
James Bottomley2686de22006-06-30 12:54:02 -05001716 ioc->handle = hba->handle;
Moore, Erice6b2d762006-03-14 09:14:24 -07001717 port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
1718 if (!port_info) {
1719 port_info = hba;
1720 list_add_tail(&port_info->list, &ioc->sas_topology);
1721 } else {
1722 port_info->handle = hba->handle;
1723 for (i = 0; i < hba->num_phys; i++)
1724 port_info->phy_info[i].negotiated_link_rate =
1725 hba->phy_info[i].negotiated_link_rate;
Eric Moore547f9a22006-06-27 14:42:12 -06001726 kfree(hba->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001727 kfree(hba);
1728 hba = NULL;
1729 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001730 mutex_unlock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07001731 ioc->num_ports = port_info->num_phys;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001732
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001733 for (i = 0; i < port_info->num_phys; i++) {
1734 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1735 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1736 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1737
1738 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1739 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1740 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001741 port_info->phy_info[i].identify.phy_id =
1742 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001743 handle = port_info->phy_info[i].identify.handle;
1744
Eric Moore547f9a22006-06-27 14:42:12 -06001745 if (port_info->phy_info[i].attached.handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001746 mptsas_sas_device_pg0(ioc,
1747 &port_info->phy_info[i].attached,
1748 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1749 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1750 port_info->phy_info[i].attached.handle);
Eric Moore547f9a22006-06-27 14:42:12 -06001751 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001752
Eric Moore547f9a22006-06-27 14:42:12 -06001753 mptsas_setup_wide_ports(ioc, port_info);
1754
1755 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001756 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Moore, Erice6b2d762006-03-14 09:14:24 -07001757 &port_info->phy_info[i], ioc->sas_index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001758
1759 return 0;
1760
1761 out_free_port_info:
Eric Moore547f9a22006-06-27 14:42:12 -06001762 kfree(hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001763 out:
1764 return error;
1765}
1766
1767static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001768mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001769{
Moore, Erice6b2d762006-03-14 09:14:24 -07001770 struct mptsas_portinfo *port_info, *p, *ex;
Eric Moore547f9a22006-06-27 14:42:12 -06001771 struct device *parent;
1772 struct sas_rphy *rphy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001773 int error = -ENOMEM, i, j;
1774
Moore, Erice6b2d762006-03-14 09:14:24 -07001775 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
1776 if (!ex)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001777 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001778
Moore, Erice6b2d762006-03-14 09:14:24 -07001779 error = mptsas_sas_expander_pg0(ioc, ex,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001780 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1781 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1782 if (error)
1783 goto out_free_port_info;
1784
Moore, Erice6b2d762006-03-14 09:14:24 -07001785 *handle = ex->handle;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001786
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001787 mutex_lock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07001788 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
1789 if (!port_info) {
1790 port_info = ex;
1791 list_add_tail(&port_info->list, &ioc->sas_topology);
1792 } else {
1793 port_info->handle = ex->handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001794 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001795 kfree(ex);
1796 ex = NULL;
1797 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001798 mutex_unlock(&ioc->sas_topology_mutex);
1799
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001800 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001801 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1802 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1803 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1804
1805 if (port_info->phy_info[i].identify.handle) {
1806 mptsas_sas_device_pg0(ioc,
1807 &port_info->phy_info[i].identify,
1808 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1809 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1810 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001811 port_info->phy_info[i].identify.phy_id =
1812 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001813 }
1814
1815 if (port_info->phy_info[i].attached.handle) {
1816 mptsas_sas_device_pg0(ioc,
1817 &port_info->phy_info[i].attached,
1818 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1819 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1820 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07001821 port_info->phy_info[i].attached.phy_id =
1822 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001823 }
Eric Moore547f9a22006-06-27 14:42:12 -06001824 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001825
Eric Moore547f9a22006-06-27 14:42:12 -06001826 parent = &ioc->sh->shost_gendev;
1827 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001828 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001829 list_for_each_entry(p, &ioc->sas_topology, list) {
1830 for (j = 0; j < p->num_phys; j++) {
Eric Moore547f9a22006-06-27 14:42:12 -06001831 if (port_info->phy_info[i].identify.handle !=
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001832 p->phy_info[j].attached.handle)
Eric Moore547f9a22006-06-27 14:42:12 -06001833 continue;
1834 rphy = mptsas_get_rphy(&p->phy_info[j]);
1835 parent = &rphy->dev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001836 }
1837 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001838 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06001839 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001840
Eric Moore547f9a22006-06-27 14:42:12 -06001841 mptsas_setup_wide_ports(ioc, port_info);
1842
1843 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001844 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
Moore, Erice6b2d762006-03-14 09:14:24 -07001845 ioc->sas_index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001846
1847 return 0;
1848
1849 out_free_port_info:
Moore, Erice6b2d762006-03-14 09:14:24 -07001850 if (ex) {
Eric Moore547f9a22006-06-27 14:42:12 -06001851 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001852 kfree(ex);
1853 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001854 out:
1855 return error;
1856}
1857
Moore, Erice6b2d762006-03-14 09:14:24 -07001858/*
1859 * mptsas_delete_expander_phys
1860 *
1861 *
1862 * This will traverse topology, and remove expanders
1863 * that are no longer present
1864 */
1865static void
1866mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1867{
1868 struct mptsas_portinfo buffer;
1869 struct mptsas_portinfo *port_info, *n, *parent;
Eric Moore547f9a22006-06-27 14:42:12 -06001870 struct mptsas_phyinfo *phy_info;
1871 struct scsi_target * starget;
1872 VirtTarget * vtarget;
1873 struct sas_port * port;
Moore, Erice6b2d762006-03-14 09:14:24 -07001874 int i;
Eric Moore547f9a22006-06-27 14:42:12 -06001875 u64 expander_sas_address;
Moore, Erice6b2d762006-03-14 09:14:24 -07001876
1877 mutex_lock(&ioc->sas_topology_mutex);
1878 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
1879
1880 if (port_info->phy_info &&
1881 (!(port_info->phy_info[0].identify.device_info &
1882 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
1883 continue;
1884
1885 if (mptsas_sas_expander_pg0(ioc, &buffer,
1886 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
1887 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
1888
1889 /*
Eric Moore547f9a22006-06-27 14:42:12 -06001890 * Issue target reset to all child end devices
1891 * then mark them deleted to prevent further
1892 * IO going to them.
1893 */
1894 phy_info = port_info->phy_info;
1895 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
1896 starget = mptsas_get_starget(phy_info);
1897 if (!starget)
1898 continue;
1899 vtarget = starget->hostdata;
1900 if(vtarget->deleted)
1901 continue;
1902 vtarget->deleted = 1;
1903 mptsas_target_reset(ioc, vtarget);
1904 sas_port_delete(mptsas_get_port(phy_info));
1905 mptsas_port_delete(phy_info->port_details);
1906 }
1907
1908 /*
Moore, Erice6b2d762006-03-14 09:14:24 -07001909 * Obtain the port_info instance to the parent port
1910 */
1911 parent = mptsas_find_portinfo_by_handle(ioc,
1912 port_info->phy_info[0].identify.handle_parent);
1913
1914 if (!parent)
1915 goto next_port;
1916
Eric Moore547f9a22006-06-27 14:42:12 -06001917 expander_sas_address =
1918 port_info->phy_info[0].identify.sas_address;
1919
Moore, Erice6b2d762006-03-14 09:14:24 -07001920 /*
1921 * Delete rphys in the parent that point
1922 * to this expander. The transport layer will
1923 * cleanup all the children.
1924 */
Eric Moore547f9a22006-06-27 14:42:12 -06001925 phy_info = parent->phy_info;
1926 for (i = 0; i < parent->num_phys; i++, phy_info++) {
1927 port = mptsas_get_port(phy_info);
1928 if (!port)
Moore, Erice6b2d762006-03-14 09:14:24 -07001929 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06001930 if (phy_info->attached.sas_address !=
1931 expander_sas_address)
1932 continue;
1933#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06001934 dev_printk(KERN_DEBUG, &port->dev,
1935 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06001936#endif
1937 sas_port_delete(port);
1938 mptsas_port_delete(phy_info->port_details);
Moore, Erice6b2d762006-03-14 09:14:24 -07001939 }
1940 next_port:
Eric Moore547f9a22006-06-27 14:42:12 -06001941
1942 phy_info = port_info->phy_info;
1943 for (i = 0; i < port_info->num_phys; i++, phy_info++)
1944 mptsas_port_delete(phy_info->port_details);
1945
Moore, Erice6b2d762006-03-14 09:14:24 -07001946 list_del(&port_info->list);
Eric Moore547f9a22006-06-27 14:42:12 -06001947 kfree(port_info->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001948 kfree(port_info);
1949 }
1950 /*
1951 * Free this memory allocated from inside
1952 * mptsas_sas_expander_pg0
1953 */
Eric Moore547f9a22006-06-27 14:42:12 -06001954 kfree(buffer.phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001955 }
1956 mutex_unlock(&ioc->sas_topology_mutex);
1957}
1958
1959/*
1960 * Start of day discovery
1961 */
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001962static void
1963mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1964{
1965 u32 handle = 0xFFFF;
Moore, Ericf44e5462006-03-14 09:14:21 -07001966 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001967
Moore, Erice6b2d762006-03-14 09:14:24 -07001968 mutex_lock(&ioc->sas_discovery_mutex);
1969 mptsas_probe_hba_phys(ioc);
1970 while (!mptsas_probe_expander_phys(ioc, &handle))
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001971 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07001972 /*
1973 Reporting RAID volumes.
1974 */
1975 if (!ioc->raid_data.pIocPg2)
1976 goto out;
1977 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1978 goto out;
1979 for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
1980 scsi_add_device(ioc->sh, ioc->num_ports,
1981 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
1982 }
1983 out:
Moore, Erice6b2d762006-03-14 09:14:24 -07001984 mutex_unlock(&ioc->sas_discovery_mutex);
1985}
1986
1987/*
1988 * Work queue thread to handle Runtime discovery
1989 * Mere purpose is the hot add/delete of expanders
Eric Moore547f9a22006-06-27 14:42:12 -06001990 *(Mutex UNLOCKED)
Moore, Erice6b2d762006-03-14 09:14:24 -07001991 */
1992static void
Eric Moore547f9a22006-06-27 14:42:12 -06001993__mptsas_discovery_work(MPT_ADAPTER *ioc)
Moore, Erice6b2d762006-03-14 09:14:24 -07001994{
Moore, Erice6b2d762006-03-14 09:14:24 -07001995 u32 handle = 0xFFFF;
1996
Moore, Erice6b2d762006-03-14 09:14:24 -07001997 ioc->sas_discovery_runtime=1;
1998 mptsas_delete_expander_phys(ioc);
1999 mptsas_probe_hba_phys(ioc);
2000 while (!mptsas_probe_expander_phys(ioc, &handle))
2001 ;
Moore, Erice6b2d762006-03-14 09:14:24 -07002002 ioc->sas_discovery_runtime=0;
Eric Moore547f9a22006-06-27 14:42:12 -06002003}
2004
2005/*
2006 * Work queue thread to handle Runtime discovery
2007 * Mere purpose is the hot add/delete of expanders
2008 *(Mutex LOCKED)
2009 */
2010static void
2011mptsas_discovery_work(void * arg)
2012{
2013 struct mptsas_discovery_event *ev = arg;
2014 MPT_ADAPTER *ioc = ev->ioc;
2015
2016 mutex_lock(&ioc->sas_discovery_mutex);
2017 __mptsas_discovery_work(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002018 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002019 kfree(ev);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002020}
2021
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002022static struct mptsas_phyinfo *
Eric Moore547f9a22006-06-27 14:42:12 -06002023mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002024{
2025 struct mptsas_portinfo *port_info;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002026 struct mptsas_phyinfo *phy_info = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -06002027 int i;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002028
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002029 mutex_lock(&ioc->sas_topology_mutex);
2030 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2031 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002032 if (port_info->phy_info[i].attached.sas_address
2033 != sas_address)
2034 continue;
2035 if (!mptsas_is_end_device(
2036 &port_info->phy_info[i].attached))
2037 continue;
2038 phy_info = &port_info->phy_info[i];
2039 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002040 }
2041 }
2042 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002043 return phy_info;
2044}
2045
2046static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07002047mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002048{
2049 struct mptsas_portinfo *port_info;
2050 struct mptsas_phyinfo *phy_info = NULL;
2051 int i;
2052
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002053 mutex_lock(&ioc->sas_topology_mutex);
2054 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -06002055 for (i = 0; i < port_info->num_phys; i++) {
2056 if (port_info->phy_info[i].attached.id != id)
2057 continue;
2058 if (!mptsas_is_end_device(
2059 &port_info->phy_info[i].attached))
2060 continue;
2061 phy_info = &port_info->phy_info[i];
2062 break;
2063 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002064 }
2065 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002066 return phy_info;
2067}
2068
Moore, Eric4b766472006-03-14 09:14:12 -07002069/*
2070 * Work queue thread to clear the persitency table
2071 */
2072static void
Eric Moore547f9a22006-06-27 14:42:12 -06002073mptsas_persist_clear_table(void * arg)
Moore, Eric4b766472006-03-14 09:14:12 -07002074{
2075 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
2076
2077 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2078}
2079
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002080static void
Moore, Ericf44e5462006-03-14 09:14:21 -07002081mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2082{
2083 sdev->no_uld_attach = data ? 1 : 0;
2084 scsi_device_reprobe(sdev);
2085}
2086
2087static void
2088mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2089{
2090 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2091 mptsas_reprobe_lun);
2092}
2093
Moore, Erice6b2d762006-03-14 09:14:24 -07002094/*
2095 * Work queue thread to handle SAS hotplug events
2096 */
Moore, Ericf44e5462006-03-14 09:14:21 -07002097static void
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002098mptsas_hotplug_work(void *arg)
2099{
2100 struct mptsas_hotplug_event *ev = arg;
2101 MPT_ADAPTER *ioc = ev->ioc;
2102 struct mptsas_phyinfo *phy_info;
2103 struct sas_rphy *rphy;
Eric Moore547f9a22006-06-27 14:42:12 -06002104 struct sas_port *port;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002105 struct scsi_device *sdev;
Eric Moore547f9a22006-06-27 14:42:12 -06002106 struct scsi_target * starget;
James Bottomleyf013db32006-03-18 14:54:36 -06002107 struct sas_identify identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002108 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002109 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07002110 VirtTarget *vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -06002111 VirtDevice *vdevice;
2112
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002113
Moore, Erice6b2d762006-03-14 09:14:24 -07002114 mutex_lock(&ioc->sas_discovery_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002115 switch (ev->event_type) {
2116 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002117
Moore, Ericc73787ee2006-01-26 16:20:06 -07002118 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Moore, Erice6b2d762006-03-14 09:14:24 -07002119
Moore, Ericf44e5462006-03-14 09:14:21 -07002120 /*
2121 * Sanity checks, for non-existing phys and remote rphys.
2122 */
Eric Moore547f9a22006-06-27 14:42:12 -06002123 if (!phy_info || !phy_info->port_details) {
2124 dfailprintk((MYIOC_s_ERR_FMT
2125 "%s: exit at line=%d\n", ioc->name,
2126 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002127 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002128 }
2129 rphy = mptsas_get_rphy(phy_info);
2130 if (!rphy) {
2131 dfailprintk((MYIOC_s_ERR_FMT
2132 "%s: exit at line=%d\n", ioc->name,
2133 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002134 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002135 }
2136 port = mptsas_get_port(phy_info);
2137 if (!port) {
2138 dfailprintk((MYIOC_s_ERR_FMT
2139 "%s: exit at line=%d\n", ioc->name,
2140 __FUNCTION__, __LINE__));
2141 break;
2142 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002143
Eric Moore547f9a22006-06-27 14:42:12 -06002144 starget = mptsas_get_starget(phy_info);
2145 if (starget) {
2146 vtarget = starget->hostdata;
2147
2148 if (!vtarget) {
2149 dfailprintk((MYIOC_s_ERR_FMT
2150 "%s: exit at line=%d\n", ioc->name,
2151 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002152 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002153 }
2154
Moore, Ericf44e5462006-03-14 09:14:21 -07002155 /*
2156 * Handling RAID components
2157 */
2158 if (ev->phys_disk_num_valid) {
2159 vtarget->target_id = ev->phys_disk_num;
2160 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore547f9a22006-06-27 14:42:12 -06002161 mptsas_reprobe_target(starget, 1);
Moore, Ericf44e5462006-03-14 09:14:21 -07002162 break;
2163 }
Eric Moore547f9a22006-06-27 14:42:12 -06002164
2165 vtarget->deleted = 1;
2166 mptsas_target_reset(ioc, vtarget);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002167 }
2168
Moore, Ericc73787ee2006-01-26 16:20:06 -07002169 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2170 ds = "ssp";
2171 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2172 ds = "stp";
2173 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2174 ds = "sata";
2175
2176 printk(MYIOC_s_INFO_FMT
2177 "removing %s device, channel %d, id %d, phy %d\n",
2178 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
2179
Eric Moore547f9a22006-06-27 14:42:12 -06002180#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06002181 dev_printk(KERN_DEBUG, &port->dev,
2182 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002183#endif
2184 sas_port_delete(port);
2185 mptsas_port_delete(phy_info->port_details);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002186 break;
2187 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002188
Moore, Ericbd23e942006-04-17 12:43:04 -06002189 if (ev->phys_disk_num_valid)
2190 mpt_findImVolumes(ioc);
2191
Moore, Ericc73787ee2006-01-26 16:20:06 -07002192 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01002193 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07002194 */
Christoph Hellwige3094442006-02-16 13:25:36 +01002195 if (mptsas_sas_device_pg0(ioc, &sas_device,
2196 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
Eric Moore547f9a22006-06-27 14:42:12 -06002197 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
2198 dfailprintk((MYIOC_s_ERR_FMT
2199 "%s: exit at line=%d\n", ioc->name,
2200 __FUNCTION__, __LINE__));
Christoph Hellwige3094442006-02-16 13:25:36 +01002201 break;
Moore, Erice6b2d762006-03-14 09:14:24 -07002202 }
2203
Eric Moore547f9a22006-06-27 14:42:12 -06002204 ssleep(2);
2205 __mptsas_discovery_work(ioc);
Moore, Ericf44e5462006-03-14 09:14:21 -07002206
Eric Moore547f9a22006-06-27 14:42:12 -06002207 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2208 sas_device.sas_address);
2209
2210 if (!phy_info || !phy_info->port_details) {
2211 dfailprintk((MYIOC_s_ERR_FMT
2212 "%s: exit at line=%d\n", ioc->name,
2213 __FUNCTION__, __LINE__));
2214 break;
2215 }
2216
2217 starget = mptsas_get_starget(phy_info);
2218 if (starget) {
2219 vtarget = starget->hostdata;
2220
2221 if (!vtarget) {
2222 dfailprintk((MYIOC_s_ERR_FMT
2223 "%s: exit at line=%d\n", ioc->name,
2224 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002225 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002226 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002227 /*
2228 * Handling RAID components
2229 */
2230 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
2231 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
2232 vtarget->target_id = ev->id;
Eric Moore547f9a22006-06-27 14:42:12 -06002233 mptsas_reprobe_target(starget, 0);
Moore, Ericf44e5462006-03-14 09:14:21 -07002234 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002235 break;
2236 }
2237
Eric Moore547f9a22006-06-27 14:42:12 -06002238 if (mptsas_get_rphy(phy_info)) {
2239 dfailprintk((MYIOC_s_ERR_FMT
2240 "%s: exit at line=%d\n", ioc->name,
2241 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002242 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002243 }
2244 port = mptsas_get_port(phy_info);
2245 if (!port) {
2246 dfailprintk((MYIOC_s_ERR_FMT
2247 "%s: exit at line=%d\n", ioc->name,
2248 __FUNCTION__, __LINE__));
2249 break;
2250 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002251
Christoph Hellwige3094442006-02-16 13:25:36 +01002252 memcpy(&phy_info->attached, &sas_device,
2253 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002254
Moore, Ericc73787ee2006-01-26 16:20:06 -07002255 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2256 ds = "ssp";
2257 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2258 ds = "stp";
2259 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2260 ds = "sata";
2261
2262 printk(MYIOC_s_INFO_FMT
2263 "attaching %s device, channel %d, id %d, phy %d\n",
2264 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2265
James Bottomleyf013db32006-03-18 14:54:36 -06002266 mptsas_parse_device_info(&identify, &phy_info->attached);
Eric Moore547f9a22006-06-27 14:42:12 -06002267 rphy = sas_end_device_alloc(port);
2268 if (!rphy) {
2269 dfailprintk((MYIOC_s_ERR_FMT
2270 "%s: exit at line=%d\n", ioc->name,
2271 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002272 break; /* non-fatal: an rphy can be added later */
Eric Moore547f9a22006-06-27 14:42:12 -06002273 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002274
James Bottomleyf013db32006-03-18 14:54:36 -06002275 rphy->identify = identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002276 if (sas_rphy_add(rphy)) {
Eric Moore547f9a22006-06-27 14:42:12 -06002277 dfailprintk((MYIOC_s_ERR_FMT
2278 "%s: exit at line=%d\n", ioc->name,
2279 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002280 sas_rphy_free(rphy);
2281 break;
2282 }
Eric Moore547f9a22006-06-27 14:42:12 -06002283 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002284 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002285 case MPTSAS_ADD_RAID:
2286 sdev = scsi_device_lookup(
2287 ioc->sh,
2288 ioc->num_ports,
2289 ev->id,
2290 0);
2291 if (sdev) {
2292 scsi_device_put(sdev);
2293 break;
2294 }
2295 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002296 "attaching raid volume, channel %d, id %d\n",
Moore, Ericc73787ee2006-01-26 16:20:06 -07002297 ioc->name, ioc->num_ports, ev->id);
2298 scsi_add_device(ioc->sh,
2299 ioc->num_ports,
2300 ev->id,
2301 0);
2302 mpt_findImVolumes(ioc);
2303 break;
2304 case MPTSAS_DEL_RAID:
2305 sdev = scsi_device_lookup(
2306 ioc->sh,
2307 ioc->num_ports,
2308 ev->id,
2309 0);
2310 if (!sdev)
2311 break;
2312 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002313 "removing raid volume, channel %d, id %d\n",
Moore, Ericc73787ee2006-01-26 16:20:06 -07002314 ioc->name, ioc->num_ports, ev->id);
Eric Moore547f9a22006-06-27 14:42:12 -06002315 vdevice = sdev->hostdata;
2316 vdevice->vtarget->deleted = 1;
2317 mptsas_target_reset(ioc, vdevice->vtarget);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002318 scsi_remove_device(sdev);
2319 scsi_device_put(sdev);
2320 mpt_findImVolumes(ioc);
2321 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002322 case MPTSAS_IGNORE_EVENT:
2323 default:
2324 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002325 }
2326
Moore, Erice6b2d762006-03-14 09:14:24 -07002327 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002328 kfree(ev);
2329
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002330}
2331
2332static void
Eric Moore547f9a22006-06-27 14:42:12 -06002333mptsas_send_sas_event(MPT_ADAPTER *ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002334 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2335{
2336 struct mptsas_hotplug_event *ev;
2337 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2338 __le64 sas_address;
2339
2340 if ((device_info &
2341 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2342 MPI_SAS_DEVICE_INFO_STP_TARGET |
2343 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2344 return;
2345
Moore, Eric4b766472006-03-14 09:14:12 -07002346 switch (sas_event_data->ReasonCode) {
2347 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2348 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
Eric Moore547f9a22006-06-27 14:42:12 -06002349 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Eric4b766472006-03-14 09:14:12 -07002350 if (!ev) {
2351 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2352 break;
2353 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002354
Moore, Eric4b766472006-03-14 09:14:12 -07002355 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
2356 ev->ioc = ioc;
2357 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2358 ev->parent_handle =
2359 le16_to_cpu(sas_event_data->ParentDevHandle);
2360 ev->channel = sas_event_data->Bus;
2361 ev->id = sas_event_data->TargetID;
2362 ev->phy_id = sas_event_data->PhyNum;
2363 memcpy(&sas_address, &sas_event_data->SASAddress,
2364 sizeof(__le64));
2365 ev->sas_address = le64_to_cpu(sas_address);
2366 ev->device_info = device_info;
2367
2368 if (sas_event_data->ReasonCode &
2369 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2370 ev->event_type = MPTSAS_ADD_DEVICE;
2371 else
2372 ev->event_type = MPTSAS_DEL_DEVICE;
2373 schedule_work(&ev->work);
2374 break;
2375 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2376 /*
2377 * Persistent table is full.
2378 */
Eric Moore547f9a22006-06-27 14:42:12 -06002379 INIT_WORK(&ioc->sas_persist_task,
2380 mptsas_persist_clear_table, (void *)ioc);
2381 schedule_work(&ioc->sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002382 break;
2383 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
2384 /* TODO */
2385 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
2386 /* TODO */
2387 default:
2388 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002389 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002390}
2391
Moore, Ericc73787ee2006-01-26 16:20:06 -07002392static void
Eric Moore547f9a22006-06-27 14:42:12 -06002393mptsas_send_raid_event(MPT_ADAPTER *ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002394 EVENT_DATA_RAID *raid_event_data)
2395{
2396 struct mptsas_hotplug_event *ev;
Moore, Ericbd23e942006-04-17 12:43:04 -06002397 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2398 int state = (status >> 8) & 0xff;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002399
2400 if (ioc->bus_type != SAS)
2401 return;
2402
Eric Moore547f9a22006-06-27 14:42:12 -06002403 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002404 if (!ev) {
2405 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2406 return;
2407 }
2408
Moore, Ericc73787ee2006-01-26 16:20:06 -07002409 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
2410 ev->ioc = ioc;
2411 ev->id = raid_event_data->VolumeID;
Moore, Ericbd23e942006-04-17 12:43:04 -06002412 ev->event_type = MPTSAS_IGNORE_EVENT;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002413
2414 switch (raid_event_data->ReasonCode) {
2415 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
2416 ev->event_type = MPTSAS_ADD_DEVICE;
2417 break;
2418 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07002419 ioc->raid_data.isRaid = 1;
2420 ev->phys_disk_num_valid = 1;
2421 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002422 ev->event_type = MPTSAS_DEL_DEVICE;
2423 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002424 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2425 switch (state) {
2426 case MPI_PD_STATE_ONLINE:
2427 ioc->raid_data.isRaid = 1;
2428 ev->phys_disk_num_valid = 1;
2429 ev->phys_disk_num = raid_event_data->PhysDiskNum;
2430 ev->event_type = MPTSAS_ADD_DEVICE;
2431 break;
2432 case MPI_PD_STATE_MISSING:
2433 case MPI_PD_STATE_NOT_COMPATIBLE:
2434 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2435 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2436 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
2437 ev->event_type = MPTSAS_DEL_DEVICE;
2438 break;
2439 default:
2440 break;
2441 }
2442 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002443 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2444 ev->event_type = MPTSAS_DEL_RAID;
2445 break;
2446 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2447 ev->event_type = MPTSAS_ADD_RAID;
2448 break;
2449 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
Moore, Ericbd23e942006-04-17 12:43:04 -06002450 switch (state) {
2451 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2452 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2453 ev->event_type = MPTSAS_DEL_RAID;
2454 break;
2455 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2456 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2457 ev->event_type = MPTSAS_ADD_RAID;
2458 break;
2459 default:
2460 break;
2461 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002462 break;
2463 default:
2464 break;
2465 }
2466 schedule_work(&ev->work);
2467}
2468
Moore, Erice6b2d762006-03-14 09:14:24 -07002469static void
Eric Moore547f9a22006-06-27 14:42:12 -06002470mptsas_send_discovery_event(MPT_ADAPTER *ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002471 EVENT_DATA_SAS_DISCOVERY *discovery_data)
2472{
2473 struct mptsas_discovery_event *ev;
2474
2475 /*
2476 * DiscoveryStatus
2477 *
2478 * This flag will be non-zero when firmware
2479 * kicks off discovery, and return to zero
2480 * once its completed.
2481 */
2482 if (discovery_data->DiscoveryStatus)
2483 return;
2484
Eric Moore547f9a22006-06-27 14:42:12 -06002485 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Erice6b2d762006-03-14 09:14:24 -07002486 if (!ev)
2487 return;
Eric Moore547f9a22006-06-27 14:42:12 -06002488 INIT_WORK(&ev->work, mptsas_discovery_work, ev);
Moore, Erice6b2d762006-03-14 09:14:24 -07002489 ev->ioc = ioc;
2490 schedule_work(&ev->work);
2491};
2492
2493
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002494static int
2495mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
2496{
Moore, Ericc73787ee2006-01-26 16:20:06 -07002497 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002498 u8 event = le32_to_cpu(reply->Event) & 0xFF;
2499
2500 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002501 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002502
Moore, Erice6b2d762006-03-14 09:14:24 -07002503 /*
2504 * sas_discovery_ignore_events
2505 *
2506 * This flag is to prevent anymore processing of
2507 * sas events once mptsas_remove function is called.
2508 */
2509 if (ioc->sas_discovery_ignore_events) {
2510 rc = mptscsih_event_process(ioc, reply);
2511 goto out;
2512 }
2513
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002514 switch (event) {
2515 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
Eric Moore547f9a22006-06-27 14:42:12 -06002516 mptsas_send_sas_event(ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002517 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002518 break;
2519 case MPI_EVENT_INTEGRATED_RAID:
Eric Moore547f9a22006-06-27 14:42:12 -06002520 mptsas_send_raid_event(ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002521 (EVENT_DATA_RAID *)reply->Data);
2522 break;
Moore, Eric79de2782006-01-25 18:05:15 -07002523 case MPI_EVENT_PERSISTENT_TABLE_FULL:
Eric Moore547f9a22006-06-27 14:42:12 -06002524 INIT_WORK(&ioc->sas_persist_task,
2525 mptsas_persist_clear_table,
Moore, Eric79de2782006-01-25 18:05:15 -07002526 (void *)ioc);
Eric Moore547f9a22006-06-27 14:42:12 -06002527 schedule_work(&ioc->sas_persist_task);
Moore, Eric79de2782006-01-25 18:05:15 -07002528 break;
Moore, Eric4b766472006-03-14 09:14:12 -07002529 case MPI_EVENT_SAS_DISCOVERY:
Eric Moore547f9a22006-06-27 14:42:12 -06002530 mptsas_send_discovery_event(ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002531 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
2532 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002533 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002534 rc = mptscsih_event_process(ioc, reply);
2535 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002536 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002537 out:
2538
2539 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002540}
2541
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002542static int
2543mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2544{
2545 struct Scsi_Host *sh;
2546 MPT_SCSI_HOST *hd;
2547 MPT_ADAPTER *ioc;
2548 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002549 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002550 int numSGE = 0;
2551 int scale;
2552 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002553 int error=0;
2554 int r;
2555
2556 r = mpt_attach(pdev,id);
2557 if (r)
2558 return r;
2559
2560 ioc = pci_get_drvdata(pdev);
2561 ioc->DoneCtx = mptsasDoneCtx;
2562 ioc->TaskCtx = mptsasTaskCtx;
2563 ioc->InternalCtx = mptsasInternalCtx;
2564
2565 /* Added sanity check on readiness of the MPT adapter.
2566 */
2567 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
2568 printk(MYIOC_s_WARN_FMT
2569 "Skipping because it's not operational!\n",
2570 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002571 error = -ENODEV;
2572 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002573 }
2574
2575 if (!ioc->active) {
2576 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
2577 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002578 error = -ENODEV;
2579 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002580 }
2581
2582 /* Sanity check - ensure at least 1 port is INITIATOR capable
2583 */
2584 ioc_cap = 0;
2585 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
2586 if (ioc->pfacts[ii].ProtocolFlags &
2587 MPI_PORTFACTS_PROTOCOL_INITIATOR)
2588 ioc_cap++;
2589 }
2590
2591 if (!ioc_cap) {
2592 printk(MYIOC_s_WARN_FMT
2593 "Skipping ioc=%p because SCSI Initiator mode "
2594 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06002595 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002596 }
2597
2598 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
2599 if (!sh) {
2600 printk(MYIOC_s_WARN_FMT
2601 "Unable to register controller with SCSI subsystem\n",
2602 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002603 error = -1;
2604 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002605 }
2606
2607 spin_lock_irqsave(&ioc->FreeQlock, flags);
2608
2609 /* Attach the SCSI Host to the IOC structure
2610 */
2611 ioc->sh = sh;
2612
2613 sh->io_port = 0;
2614 sh->n_io_port = 0;
2615 sh->irq = 0;
2616
2617 /* set 16 byte cdb's */
2618 sh->max_cmd_len = 16;
2619
2620 sh->max_id = ioc->pfacts->MaxDevices + 1;
2621
2622 sh->transportt = mptsas_transport_template;
2623
2624 sh->max_lun = MPT_LAST_LUN + 1;
2625 sh->max_channel = 0;
2626 sh->this_id = ioc->pfacts[0].PortSCSIID;
2627
2628 /* Required entry.
2629 */
2630 sh->unique_id = ioc->id;
2631
2632 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002633 mutex_init(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07002634 mutex_init(&ioc->sas_discovery_mutex);
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01002635 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002636 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002637
2638 /* Verify that we won't exceed the maximum
2639 * number of chain buffers
2640 * We can optimize: ZZ = req_sz/sizeof(SGE)
2641 * For 32bit SGE's:
2642 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
2643 * + (req_sz - 64)/sizeof(SGE)
2644 * A slightly different algorithm is required for
2645 * 64bit SGEs.
2646 */
2647 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
2648 if (sizeof(dma_addr_t) == sizeof(u64)) {
2649 numSGE = (scale - 1) *
2650 (ioc->facts.MaxChainDepth-1) + scale +
2651 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
2652 sizeof(u32));
2653 } else {
2654 numSGE = 1 + (scale - 1) *
2655 (ioc->facts.MaxChainDepth-1) + scale +
2656 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
2657 sizeof(u32));
2658 }
2659
2660 if (numSGE < sh->sg_tablesize) {
2661 /* Reset this value */
2662 dprintk((MYIOC_s_INFO_FMT
2663 "Resetting sg_tablesize to %d from %d\n",
2664 ioc->name, numSGE, sh->sg_tablesize));
2665 sh->sg_tablesize = numSGE;
2666 }
2667
2668 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2669
2670 hd = (MPT_SCSI_HOST *) sh->hostdata;
2671 hd->ioc = ioc;
2672
2673 /* SCSI needs scsi_cmnd lookup table!
2674 * (with size equal to req_depth*PtrSz!)
2675 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002676 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
2677 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002678 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002679 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002680 }
2681
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002682 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
2683 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002684
2685 /* Allocate memory for the device structures.
2686 * A non-Null pointer at an offset
2687 * indicates a device exists.
2688 * max_id = 1 + maximum id (hosts.h)
2689 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002690 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
2691 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002692 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002693 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002694 }
2695
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002696 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002697
2698 /* Clear the TM flags
2699 */
2700 hd->tmPending = 0;
2701 hd->tmState = TM_STATE_NONE;
2702 hd->resetPending = 0;
2703 hd->abortSCpnt = NULL;
2704
2705 /* Clear the pointer used to store
2706 * single-threaded commands, i.e., those
2707 * issued during a bus scan, dv and
2708 * configuration pages.
2709 */
2710 hd->cmdPtr = NULL;
2711
2712 /* Initialize this SCSI Hosts' timers
2713 * To use, set the timer expires field
2714 * and add_timer
2715 */
2716 init_timer(&hd->timer);
2717 hd->timer.data = (unsigned long) hd;
2718 hd->timer.function = mptscsih_timer_expired;
2719
2720 hd->mpt_pq_filter = mpt_pq_filter;
2721 ioc->sas_data.ptClear = mpt_pt_clear;
2722
2723 if (ioc->sas_data.ptClear==1) {
2724 mptbase_sas_persist_operation(
2725 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
2726 }
2727
2728 ddvprintk((MYIOC_s_INFO_FMT
2729 "mpt_pq_filter %x mpt_pq_filter %x\n",
2730 ioc->name,
2731 mpt_pq_filter,
2732 mpt_pq_filter));
2733
2734 init_waitqueue_head(&hd->scandv_waitq);
2735 hd->scandv_wait_done = 0;
2736 hd->last_queue_full = 0;
2737
2738 error = scsi_add_host(sh, &ioc->pcidev->dev);
2739 if (error) {
2740 dprintk((KERN_ERR MYNAM
2741 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002742 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002743 }
2744
2745 mptsas_scan_sas_topology(ioc);
2746
2747 return 0;
2748
Eric Moore547f9a22006-06-27 14:42:12 -06002749 out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002750
2751 mptscsih_remove(pdev);
2752 return error;
2753}
2754
2755static void __devexit mptsas_remove(struct pci_dev *pdev)
2756{
2757 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2758 struct mptsas_portinfo *p, *n;
Eric Moore547f9a22006-06-27 14:42:12 -06002759 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002760
Moore, Erice6b2d762006-03-14 09:14:24 -07002761 ioc->sas_discovery_ignore_events=1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002762 sas_remove_host(ioc->sh);
2763
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002764 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002765 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
2766 list_del(&p->list);
Eric Moore547f9a22006-06-27 14:42:12 -06002767 for (i = 0 ; i < p->num_phys ; i++)
2768 mptsas_port_delete(p->phy_info[i].port_details);
2769 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002770 kfree(p);
2771 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002772 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002773
2774 mptscsih_remove(pdev);
2775}
2776
2777static struct pci_device_id mptsas_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06002778 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002779 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002780 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002781 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002782 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002783 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002784 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002785 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002786 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002787 PCI_ANY_ID, PCI_ANY_ID },
2788 {0} /* Terminating entry */
2789};
2790MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
2791
2792
2793static struct pci_driver mptsas_driver = {
2794 .name = "mptsas",
2795 .id_table = mptsas_pci_table,
2796 .probe = mptsas_probe,
2797 .remove = __devexit_p(mptsas_remove),
2798 .shutdown = mptscsih_shutdown,
2799#ifdef CONFIG_PM
2800 .suspend = mptscsih_suspend,
2801 .resume = mptscsih_resume,
2802#endif
2803};
2804
2805static int __init
2806mptsas_init(void)
2807{
2808 show_mptmod_ver(my_NAME, my_VERSION);
2809
2810 mptsas_transport_template =
2811 sas_attach_transport(&mptsas_transport_functions);
2812 if (!mptsas_transport_template)
2813 return -ENODEV;
2814
2815 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2816 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2817 mptsasInternalCtx =
2818 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002819 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002820
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002821 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07002822 devtverboseprintk((KERN_INFO MYNAM
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002823 ": Registered for IOC event notifications\n"));
2824 }
2825
2826 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2827 dprintk((KERN_INFO MYNAM
2828 ": Registered for IOC reset notifications\n"));
2829 }
2830
2831 return pci_register_driver(&mptsas_driver);
2832}
2833
2834static void __exit
2835mptsas_exit(void)
2836{
2837 pci_unregister_driver(&mptsas_driver);
2838 sas_release_transport(mptsas_transport_template);
2839
2840 mpt_reset_deregister(mptsasDoneCtx);
2841 mpt_event_deregister(mptsasDoneCtx);
2842
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002843 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002844 mpt_deregister(mptsasInternalCtx);
2845 mpt_deregister(mptsasTaskCtx);
2846 mpt_deregister(mptsasDoneCtx);
2847}
2848
2849module_init(mptsas_init);
2850module_exit(mptsas_exit);