blob: b28e930528e804b8e3ef2d34d73ea9cdbfff9904 [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
James Bottomleye8bf3942006-07-11 17:49:34 -040070/*
71 * Reserved channel for integrated raid
72 */
73#define MPTSAS_RAID_CHANNEL 1
74
Christoph Hellwig0c33b272005-09-09 16:27:19 +020075MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
78
79static int mpt_pq_filter;
80module_param(mpt_pq_filter, int, 0);
81MODULE_PARM_DESC(mpt_pq_filter,
82 "Enable peripheral qualifier filter: enable=1 "
83 "(default=0)");
84
85static int mpt_pt_clear;
86module_param(mpt_pt_clear, int, 0);
87MODULE_PARM_DESC(mpt_pt_clear,
88 "Clear persistency table: enable=1 "
89 "(default=MPTSCSIH_PT_CLEAR=0)");
90
91static int mptsasDoneCtx = -1;
92static int mptsasTaskCtx = -1;
93static int mptsasInternalCtx = -1; /* Used only for internal commands */
Christoph Hellwigda4fa652005-10-19 20:01:42 +020094static int mptsasMgmtCtx = -1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020095
96
Christoph Hellwig9a28f492006-01-13 18:04:41 +010097enum mptsas_hotplug_action {
98 MPTSAS_ADD_DEVICE,
99 MPTSAS_DEL_DEVICE,
Moore, Ericc73787ee2006-01-26 16:20:06 -0700100 MPTSAS_ADD_RAID,
101 MPTSAS_DEL_RAID,
Moore, Ericbd23e942006-04-17 12:43:04 -0600102 MPTSAS_IGNORE_EVENT,
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100103};
104
105struct mptsas_hotplug_event {
106 struct work_struct work;
107 MPT_ADAPTER *ioc;
108 enum mptsas_hotplug_action event_type;
109 u64 sas_address;
110 u32 channel;
111 u32 id;
112 u32 device_info;
113 u16 handle;
114 u16 parent_handle;
115 u8 phy_id;
Moore, Ericf44e5462006-03-14 09:14:21 -0700116 u8 phys_disk_num;
117 u8 phys_disk_num_valid;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100118};
119
Moore, Erice6b2d762006-03-14 09:14:24 -0700120struct mptsas_discovery_event {
121 struct work_struct work;
122 MPT_ADAPTER *ioc;
123};
124
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200125/*
126 * SAS topology structures
127 *
128 * The MPT Fusion firmware interface spreads information about the
129 * SAS topology over many manufacture pages, thus we need some data
130 * structure to collect it and process it for the SAS transport class.
131 */
132
133struct mptsas_devinfo {
134 u16 handle; /* unique id to address this device */
Moore, Ericc73787ee2006-01-26 16:20:06 -0700135 u16 handle_parent; /* unique id to address parent device */
Christoph Hellwige3094442006-02-16 13:25:36 +0100136 u16 handle_enclosure; /* enclosure identifier of the enclosure */
137 u16 slot; /* physical slot in enclosure */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200138 u8 phy_id; /* phy number of parent device */
139 u8 port_id; /* sas physical port this device
140 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100141 u8 id; /* logical target id of this device */
142 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200143 u64 sas_address; /* WWN of this device,
144 SATA is assigned by HBA,expander */
145 u32 device_info; /* bitfield detailed info about this device */
146};
147
Eric Moore547f9a22006-06-27 14:42:12 -0600148/*
149 * Specific details on ports, wide/narrow
150 */
151struct mptsas_portinfo_details{
Eric Moore547f9a22006-06-27 14:42:12 -0600152 u16 num_phys; /* number of phys belong to this port */
153 u64 phy_bitmask; /* TODO, extend support for 255 phys */
154 struct sas_rphy *rphy; /* transport layer rphy object */
155 struct sas_port *port; /* transport layer port object */
156 struct scsi_target *starget;
157 struct mptsas_portinfo *port_info;
158};
159
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200160struct mptsas_phyinfo {
161 u8 phy_id; /* phy index */
Eric Moore547f9a22006-06-27 14:42:12 -0600162 u8 port_id; /* firmware port identifier */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200163 u8 negotiated_link_rate; /* nego'd link rate for this phy */
164 u8 hw_link_rate; /* hardware max/min phys link rate */
165 u8 programmed_link_rate; /* programmed max/min phy link rate */
Eric Moore547f9a22006-06-27 14:42:12 -0600166 u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200167 struct mptsas_devinfo identify; /* point to phy device info */
168 struct mptsas_devinfo attached; /* point to attached device info */
Eric Moore547f9a22006-06-27 14:42:12 -0600169 struct sas_phy *phy; /* transport layer phy object */
170 struct mptsas_portinfo *portinfo;
171 struct mptsas_portinfo_details * port_details;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200172};
173
174struct mptsas_portinfo {
175 struct list_head list;
176 u16 handle; /* unique id to address this */
Eric Moore547f9a22006-06-27 14:42:12 -0600177 u16 num_phys; /* number of phys */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200178 struct mptsas_phyinfo *phy_info;
179};
180
Christoph Hellwige3094442006-02-16 13:25:36 +0100181struct mptsas_enclosure {
182 u64 enclosure_logical_id; /* The WWN for the enclosure */
183 u16 enclosure_handle; /* unique id to address this */
184 u16 flags; /* details enclosure management */
185 u16 num_slot; /* num slots */
186 u16 start_slot; /* first slot */
187 u8 start_id; /* starting logical target id */
188 u8 start_channel; /* starting logical channel id */
189 u8 sep_id; /* SEP device logical target id */
190 u8 sep_channel; /* SEP channel logical channel id */
191};
192
Eric Moore547f9a22006-06-27 14:42:12 -0600193#ifdef MPT_DEBUG_SAS
Christoph Hellwigb5141122005-10-28 22:07:41 +0200194static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
195{
196 printk("---- IO UNIT PAGE 0 ------------\n");
197 printk("Handle=0x%X\n",
198 le16_to_cpu(phy_data->AttachedDeviceHandle));
199 printk("Controller Handle=0x%X\n",
200 le16_to_cpu(phy_data->ControllerDevHandle));
201 printk("Port=0x%X\n", phy_data->Port);
202 printk("Port Flags=0x%X\n", phy_data->PortFlags);
203 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
204 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
205 printk("Controller PHY Device Info=0x%X\n",
206 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
207 printk("DiscoveryStatus=0x%X\n",
208 le32_to_cpu(phy_data->DiscoveryStatus));
209 printk("\n");
210}
211
212static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
213{
214 __le64 sas_address;
215
216 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
217
218 printk("---- SAS PHY PAGE 0 ------------\n");
219 printk("Attached Device Handle=0x%X\n",
220 le16_to_cpu(pg0->AttachedDevHandle));
221 printk("SAS Address=0x%llX\n",
222 (unsigned long long)le64_to_cpu(sas_address));
223 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
224 printk("Attached Device Info=0x%X\n",
225 le32_to_cpu(pg0->AttachedDeviceInfo));
226 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
227 printk("Change Count=0x%X\n", pg0->ChangeCount);
228 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
229 printk("\n");
230}
231
232static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
233{
234 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200235 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
236 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200237 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200238 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
239 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
240 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200241}
242
243static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
244{
245 __le64 sas_address;
246
247 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
248
249 printk("---- SAS DEVICE PAGE 0 ---------\n");
250 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
Christoph Hellwige3094442006-02-16 13:25:36 +0100251 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200252 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
253 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
254 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
255 printk("Target ID=0x%X\n", pg0->TargetID);
256 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200257 /* The PhyNum field specifies the PHY number of the parent
258 * device this device is linked to
259 */
260 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
261 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200262 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
263 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
264 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
265 printk("\n");
266}
267
268static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
269{
270 printk("---- SAS EXPANDER PAGE 1 ------------\n");
271
272 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200273 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200274 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
275 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
276 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
277 printk("Owner Device Handle=0x%X\n",
278 le16_to_cpu(pg1->OwnerDevHandle));
279 printk("Attached Device Handle=0x%X\n",
280 le16_to_cpu(pg1->AttachedDevHandle));
281}
282#else
283#define mptsas_print_phy_data(phy_data) do { } while (0)
284#define mptsas_print_phy_pg0(pg0) do { } while (0)
285#define mptsas_print_phy_pg1(pg1) do { } while (0)
286#define mptsas_print_device_pg0(pg0) do { } while (0)
287#define mptsas_print_expander_pg1(pg1) do { } while (0)
288#endif
289
Christoph Hellwige3094442006-02-16 13:25:36 +0100290static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
291{
292 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
293 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
294}
295
296static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
297{
298 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
299 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
300}
301
Moore, Erice6b2d762006-03-14 09:14:24 -0700302/*
303 * mptsas_find_portinfo_by_handle
304 *
305 * This function should be called with the sas_topology_mutex already held
306 */
307static struct mptsas_portinfo *
308mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
309{
310 struct mptsas_portinfo *port_info, *rc=NULL;
311 int i;
312
313 list_for_each_entry(port_info, &ioc->sas_topology, list)
314 for (i = 0; i < port_info->num_phys; i++)
315 if (port_info->phy_info[i].identify.handle == handle) {
316 rc = port_info;
317 goto out;
318 }
319 out:
320 return rc;
321}
322
Moore, Ericbd23e942006-04-17 12:43:04 -0600323/*
324 * Returns true if there is a scsi end device
325 */
326static inline int
327mptsas_is_end_device(struct mptsas_devinfo * attached)
328{
Eric Moore547f9a22006-06-27 14:42:12 -0600329 if ((attached->sas_address) &&
Moore, Ericbd23e942006-04-17 12:43:04 -0600330 (attached->device_info &
331 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
332 ((attached->device_info &
333 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
334 (attached->device_info &
335 MPI_SAS_DEVICE_INFO_STP_TARGET) |
336 (attached->device_info &
337 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
338 return 1;
339 else
340 return 0;
341}
342
Eric Moore547f9a22006-06-27 14:42:12 -0600343/* no mutex */
Eric Moore376ac832006-06-29 17:36:26 -0600344static void
Eric Moore547f9a22006-06-27 14:42:12 -0600345mptsas_port_delete(struct mptsas_portinfo_details * port_details)
346{
347 struct mptsas_portinfo *port_info;
348 struct mptsas_phyinfo *phy_info;
349 u8 i;
350
351 if (!port_details)
352 return;
353
354 port_info = port_details->port_info;
355 phy_info = port_info->phy_info;
356
Eric Mooredc22f162006-07-06 11:23:14 -0600357 dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
Eric Moore547f9a22006-06-27 14:42:12 -0600358 "bitmask=0x%016llX\n",
Eric Mooredc22f162006-07-06 11:23:14 -0600359 __FUNCTION__, port_details, port_details->num_phys,
360 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600361
362 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
363 if(phy_info->port_details != port_details)
364 continue;
365 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
366 phy_info->port_details = NULL;
367 }
368 kfree(port_details);
369}
370
371static inline struct sas_rphy *
372mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
373{
374 if (phy_info->port_details)
375 return phy_info->port_details->rphy;
376 else
377 return NULL;
378}
379
380static inline void
381mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
382{
383 if (phy_info->port_details) {
384 phy_info->port_details->rphy = rphy;
385 dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
386 }
387
388#ifdef MPT_DEBUG_SAS_WIDE
389 if (rphy) {
390 dev_printk(KERN_DEBUG, &rphy->dev, "add:");
391 printk("rphy=%p release=%p\n",
392 rphy, rphy->dev.release);
393 }
394#endif
395}
396
397static inline struct sas_port *
398mptsas_get_port(struct mptsas_phyinfo *phy_info)
399{
400 if (phy_info->port_details)
401 return phy_info->port_details->port;
402 else
403 return NULL;
404}
405
406static inline void
407mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port)
408{
409 if (phy_info->port_details)
410 phy_info->port_details->port = port;
411
412#ifdef MPT_DEBUG_SAS_WIDE
413 if (port) {
414 dev_printk(KERN_DEBUG, &port->dev, "add: ");
415 printk("port=%p release=%p\n",
416 port, port->dev.release);
417 }
418#endif
419}
420
421static inline struct scsi_target *
422mptsas_get_starget(struct mptsas_phyinfo *phy_info)
423{
424 if (phy_info->port_details)
425 return phy_info->port_details->starget;
426 else
427 return NULL;
428}
429
430static inline void
431mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
432starget)
433{
434 if (phy_info->port_details)
435 phy_info->port_details->starget = starget;
436}
437
438
439/*
440 * mptsas_setup_wide_ports
441 *
442 * Updates for new and existing narrow/wide port configuration
443 * in the sas_topology
444 */
Eric Moore376ac832006-06-29 17:36:26 -0600445static void
Eric Moore547f9a22006-06-27 14:42:12 -0600446mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
447{
448 struct mptsas_portinfo_details * port_details;
449 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
450 u64 sas_address;
451 int i, j;
452
453 mutex_lock(&ioc->sas_topology_mutex);
454
455 phy_info = port_info->phy_info;
456 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
457 if (phy_info->attached.handle)
458 continue;
459 port_details = phy_info->port_details;
460 if (!port_details)
461 continue;
462 if (port_details->num_phys < 2)
463 continue;
464 /*
465 * Removing a phy from a port, letting the last
466 * phy be removed by firmware events.
467 */
468 dsaswideprintk((KERN_DEBUG
Eric Mooredc22f162006-07-06 11:23:14 -0600469 "%s: [%p]: deleting phy = %d\n",
470 __FUNCTION__, port_details, i));
Eric Moore547f9a22006-06-27 14:42:12 -0600471 port_details->num_phys--;
472 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
473 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
474 sas_port_delete_phy(port_details->port, phy_info->phy);
475 phy_info->port_details = NULL;
476 }
477
478 /*
479 * Populate and refresh the tree
480 */
481 phy_info = port_info->phy_info;
482 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
483 sas_address = phy_info->attached.sas_address;
484 dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
485 i, sas_address));
486 if (!sas_address)
487 continue;
488 port_details = phy_info->port_details;
489 /*
490 * Forming a port
491 */
492 if (!port_details) {
493 port_details = kzalloc(sizeof(*port_details),
494 GFP_KERNEL);
495 if (!port_details)
496 goto out;
497 port_details->num_phys = 1;
498 port_details->port_info = port_info;
Eric Moore547f9a22006-06-27 14:42:12 -0600499 if (phy_info->phy_id < 64 )
500 port_details->phy_bitmask |=
501 (1 << phy_info->phy_id);
502 phy_info->sas_port_add_phy=1;
503 dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
504 "phy_id=%d sas_address=0x%018llX\n",
505 i, sas_address));
506 phy_info->port_details = port_details;
507 }
508
509 if (i == port_info->num_phys - 1)
510 continue;
511 phy_info_cmp = &port_info->phy_info[i + 1];
512 for (j = i + 1 ; j < port_info->num_phys ; j++,
513 phy_info_cmp++) {
514 if (!phy_info_cmp->attached.sas_address)
515 continue;
516 if (sas_address != phy_info_cmp->attached.sas_address)
517 continue;
518 if (phy_info_cmp->port_details == port_details )
519 continue;
520 dsaswideprintk((KERN_DEBUG
521 "\t\tphy_id=%d sas_address=0x%018llX\n",
522 j, phy_info_cmp->attached.sas_address));
523 if (phy_info_cmp->port_details) {
524 port_details->rphy =
525 mptsas_get_rphy(phy_info_cmp);
526 port_details->port =
527 mptsas_get_port(phy_info_cmp);
528 port_details->starget =
529 mptsas_get_starget(phy_info_cmp);
Eric Moore547f9a22006-06-27 14:42:12 -0600530 port_details->num_phys =
531 phy_info_cmp->port_details->num_phys;
Eric Moore547f9a22006-06-27 14:42:12 -0600532 if (!phy_info_cmp->port_details->num_phys)
533 kfree(phy_info_cmp->port_details);
534 } else
535 phy_info_cmp->sas_port_add_phy=1;
536 /*
537 * Adding a phy to a port
538 */
539 phy_info_cmp->port_details = port_details;
540 if (phy_info_cmp->phy_id < 64 )
541 port_details->phy_bitmask |=
542 (1 << phy_info_cmp->phy_id);
543 port_details->num_phys++;
544 }
545 }
546
547 out:
548
549#ifdef MPT_DEBUG_SAS_WIDE
550 for (i = 0; i < port_info->num_phys; i++) {
551 port_details = port_info->phy_info[i].port_details;
552 if (!port_details)
553 continue;
554 dsaswideprintk((KERN_DEBUG
Eric Mooredc22f162006-07-06 11:23:14 -0600555 "%s: [%p]: phy_id=%02d num_phys=%02d "
Eric Moore547f9a22006-06-27 14:42:12 -0600556 "bitmask=0x%016llX\n",
557 __FUNCTION__,
Eric Mooredc22f162006-07-06 11:23:14 -0600558 port_details, i, port_details->num_phys,
559 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600560 dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
561 port_details->port, port_details->rphy));
562 }
563 dsaswideprintk((KERN_DEBUG"\n"));
564#endif
565 mutex_unlock(&ioc->sas_topology_mutex);
566}
567
568static void
569mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
570{
571 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
572
573 if (mptscsih_TMHandler(hd,
574 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
575 vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) {
576 hd->tmPending = 0;
577 hd->tmState = TM_STATE_NONE;
578 printk(MYIOC_s_WARN_FMT
579 "Error processing TaskMgmt id=%d TARGET_RESET\n",
580 ioc->name, vtarget->target_id);
581 }
582}
583
Christoph Hellwige3094442006-02-16 13:25:36 +0100584static int
Moore, Eric52435432006-03-14 09:14:15 -0700585mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
Christoph Hellwige3094442006-02-16 13:25:36 +0100586 u32 form, u32 form_specific)
587{
588 ConfigExtendedPageHeader_t hdr;
589 CONFIGPARMS cfg;
590 SasEnclosurePage0_t *buffer;
591 dma_addr_t dma_handle;
592 int error;
593 __le64 le_identifier;
594
595 memset(&hdr, 0, sizeof(hdr));
596 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
597 hdr.PageNumber = 0;
598 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
599 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
600
601 cfg.cfghdr.ehdr = &hdr;
602 cfg.physAddr = -1;
603 cfg.pageAddr = form + form_specific;
604 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
605 cfg.dir = 0; /* read */
606 cfg.timeout = 10;
607
608 error = mpt_config(ioc, &cfg);
609 if (error)
610 goto out;
611 if (!hdr.ExtPageLength) {
612 error = -ENXIO;
613 goto out;
614 }
615
616 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
617 &dma_handle);
618 if (!buffer) {
619 error = -ENOMEM;
620 goto out;
621 }
622
623 cfg.physAddr = dma_handle;
624 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
625
626 error = mpt_config(ioc, &cfg);
627 if (error)
628 goto out_free_consistent;
629
630 /* save config data */
631 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
632 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
633 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
634 enclosure->flags = le16_to_cpu(buffer->Flags);
635 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
636 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
637 enclosure->start_id = buffer->StartTargetID;
638 enclosure->start_channel = buffer->StartBus;
639 enclosure->sep_id = buffer->SEPTargetID;
640 enclosure->sep_channel = buffer->SEPBus;
641
642 out_free_consistent:
643 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
644 buffer, dma_handle);
645 out:
646 return error;
647}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200648
James Bottomleyf013db32006-03-18 14:54:36 -0600649static int
650mptsas_slave_configure(struct scsi_device *sdev)
651{
Moore, Eric3c0c25b2006-04-13 16:08:17 -0600652
James Bottomleye8bf3942006-07-11 17:49:34 -0400653 if (sdev->channel == MPTSAS_RAID_CHANNEL)
654 goto out;
James Bottomleyf013db32006-03-18 14:54:36 -0600655
James Bottomleye8bf3942006-07-11 17:49:34 -0400656 sas_read_port_mode_page(sdev);
657
658 out:
James Bottomleyf013db32006-03-18 14:54:36 -0600659 return mptscsih_slave_configure(sdev);
660}
661
Eric Moore547f9a22006-06-27 14:42:12 -0600662static int
663mptsas_target_alloc(struct scsi_target *starget)
664{
665 struct Scsi_Host *host = dev_to_shost(&starget->dev);
666 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
667 VirtTarget *vtarget;
668 u32 target_id;
669 u32 channel;
670 struct sas_rphy *rphy;
671 struct mptsas_portinfo *p;
672 int i;
673
674 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
675 if (!vtarget)
676 return -ENOMEM;
677
678 vtarget->starget = starget;
679 vtarget->ioc_id = hd->ioc->id;
680 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
681
682 target_id = starget->id;
683 channel = 0;
684
685 hd->Targets[target_id] = vtarget;
686
James Bottomleye8bf3942006-07-11 17:49:34 -0400687 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -0600688 goto out;
689
690 rphy = dev_to_rphy(starget->dev.parent);
691 mutex_lock(&hd->ioc->sas_topology_mutex);
692 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
693 for (i = 0; i < p->num_phys; i++) {
694 if (p->phy_info[i].attached.sas_address !=
695 rphy->identify.sas_address)
696 continue;
697 target_id = p->phy_info[i].attached.id;
698 channel = p->phy_info[i].attached.channel;
699 mptsas_set_starget(&p->phy_info[i], starget);
700
701 /*
702 * Exposing hidden raid components
703 */
704 if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
705 target_id = mptscsih_raid_id_to_num(hd,
706 target_id);
707 vtarget->tflags |=
708 MPT_TARGET_FLAGS_RAID_COMPONENT;
709 }
710 mutex_unlock(&hd->ioc->sas_topology_mutex);
711 goto out;
712 }
713 }
714 mutex_unlock(&hd->ioc->sas_topology_mutex);
715
716 kfree(vtarget);
717 return -ENXIO;
718
719 out:
720 vtarget->target_id = target_id;
721 vtarget->bus_id = channel;
722 starget->hostdata = vtarget;
723 return 0;
724}
725
726static void
727mptsas_target_destroy(struct scsi_target *starget)
728{
729 struct Scsi_Host *host = dev_to_shost(&starget->dev);
730 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
731 struct sas_rphy *rphy;
732 struct mptsas_portinfo *p;
733 int i;
734
735 if (!starget->hostdata)
736 return;
737
James Bottomleye8bf3942006-07-11 17:49:34 -0400738 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -0600739 goto out;
740
741 rphy = dev_to_rphy(starget->dev.parent);
742 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
743 for (i = 0; i < p->num_phys; i++) {
744 if (p->phy_info[i].attached.sas_address !=
745 rphy->identify.sas_address)
746 continue;
747 mptsas_set_starget(&p->phy_info[i], NULL);
748 goto out;
749 }
750 }
751
752 out:
753 kfree(starget->hostdata);
754 starget->hostdata = NULL;
755}
756
757
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200758static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700759mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200760{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700761 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200762 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
763 struct sas_rphy *rphy;
764 struct mptsas_portinfo *p;
765 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700766 struct scsi_target *starget;
Eric Moore547f9a22006-06-27 14:42:12 -0600767 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200768
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100769 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200770 if (!vdev) {
Eric Moore547f9a22006-06-27 14:42:12 -0600771 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200772 hd->ioc->name, sizeof(VirtDevice));
773 return -ENOMEM;
774 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700775 starget = scsi_target(sdev);
Eric Moore547f9a22006-06-27 14:42:12 -0600776 vdev->vtarget = starget->hostdata;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200777
James Bottomleye8bf3942006-07-11 17:49:34 -0400778 if (sdev->channel == MPTSAS_RAID_CHANNEL)
Moore, Eric816aa902006-01-13 16:25:20 -0700779 goto out;
Moore, Eric816aa902006-01-13 16:25:20 -0700780
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700781 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100782 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200783 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
784 for (i = 0; i < p->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -0600785 if (p->phy_info[i].attached.sas_address !=
786 rphy->identify.sas_address)
787 continue;
788 vdev->lun = sdev->lun;
789 /*
790 * Exposing hidden raid components
791 */
792 if (mptscsih_is_phys_disk(hd->ioc,
793 p->phy_info[i].attached.id))
794 sdev->no_uld_attach = 1;
795 mutex_unlock(&hd->ioc->sas_topology_mutex);
796 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200797 }
798 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100799 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200800
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200801 kfree(vdev);
Christoph Hellwig23f236e2006-01-30 19:00:43 +0100802 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200803
804 out:
Eric Moore547f9a22006-06-27 14:42:12 -0600805 vdev->vtarget->num_luns++;
806 sdev->hostdata = vdev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200807 return 0;
808}
809
Eric Moore547f9a22006-06-27 14:42:12 -0600810static int
811mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100812{
Eric Moore547f9a22006-06-27 14:42:12 -0600813 VirtDevice *vdev = SCpnt->device->hostdata;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100814
Eric Moore547f9a22006-06-27 14:42:12 -0600815// scsi_print_command(SCpnt);
816 if (vdev->vtarget->deleted) {
817 SCpnt->result = DID_NO_CONNECT << 16;
818 done(SCpnt);
819 return 0;
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700820 }
Eric Moore547f9a22006-06-27 14:42:12 -0600821
822 return mptscsih_qcmd(SCpnt,done);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100823}
824
Eric Moore547f9a22006-06-27 14:42:12 -0600825
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200826static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700827 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200828 .proc_name = "mptsas",
829 .proc_info = mptscsih_proc_info,
830 .name = "MPT SPI Host",
831 .info = mptscsih_info,
Eric Moore547f9a22006-06-27 14:42:12 -0600832 .queuecommand = mptsas_qcmd,
833 .target_alloc = mptsas_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200834 .slave_alloc = mptsas_slave_alloc,
James Bottomleyf013db32006-03-18 14:54:36 -0600835 .slave_configure = mptsas_slave_configure,
Eric Moore547f9a22006-06-27 14:42:12 -0600836 .target_destroy = mptsas_target_destroy,
837 .slave_destroy = mptscsih_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200838 .change_queue_depth = mptscsih_change_queue_depth,
839 .eh_abort_handler = mptscsih_abort,
840 .eh_device_reset_handler = mptscsih_dev_reset,
841 .eh_bus_reset_handler = mptscsih_bus_reset,
842 .eh_host_reset_handler = mptscsih_host_reset,
843 .bios_param = mptscsih_bios_param,
844 .can_queue = MPT_FC_CAN_QUEUE,
845 .this_id = -1,
846 .sg_tablesize = MPT_SCSI_SG_DEPTH,
847 .max_sectors = 8192,
848 .cmd_per_lun = 7,
849 .use_clustering = ENABLE_CLUSTERING,
850};
851
Christoph Hellwigb5141122005-10-28 22:07:41 +0200852static int mptsas_get_linkerrors(struct sas_phy *phy)
853{
854 MPT_ADAPTER *ioc = phy_to_ioc(phy);
855 ConfigExtendedPageHeader_t hdr;
856 CONFIGPARMS cfg;
857 SasPhyPage1_t *buffer;
858 dma_addr_t dma_handle;
859 int error;
860
861 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
862 hdr.ExtPageLength = 0;
863 hdr.PageNumber = 1 /* page number 1*/;
864 hdr.Reserved1 = 0;
865 hdr.Reserved2 = 0;
866 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
867 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
868
869 cfg.cfghdr.ehdr = &hdr;
870 cfg.physAddr = -1;
871 cfg.pageAddr = phy->identify.phy_identifier;
872 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
873 cfg.dir = 0; /* read */
874 cfg.timeout = 10;
875
876 error = mpt_config(ioc, &cfg);
877 if (error)
878 return error;
879 if (!hdr.ExtPageLength)
880 return -ENXIO;
881
882 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
883 &dma_handle);
884 if (!buffer)
885 return -ENOMEM;
886
887 cfg.physAddr = dma_handle;
888 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
889
890 error = mpt_config(ioc, &cfg);
891 if (error)
892 goto out_free_consistent;
893
894 mptsas_print_phy_pg1(buffer);
895
896 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
897 phy->running_disparity_error_count =
898 le32_to_cpu(buffer->RunningDisparityErrorCount);
899 phy->loss_of_dword_sync_count =
900 le32_to_cpu(buffer->LossDwordSynchCount);
901 phy->phy_reset_problem_count =
902 le32_to_cpu(buffer->PhyResetProblemCount);
903
904 out_free_consistent:
905 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
906 buffer, dma_handle);
907 return error;
908}
909
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200910static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
911 MPT_FRAME_HDR *reply)
912{
913 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
914 if (reply != NULL) {
915 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
916 memcpy(ioc->sas_mgmt.reply, reply,
917 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
918 }
919 complete(&ioc->sas_mgmt.done);
920 return 1;
921}
922
923static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
924{
925 MPT_ADAPTER *ioc = phy_to_ioc(phy);
926 SasIoUnitControlRequest_t *req;
927 SasIoUnitControlReply_t *reply;
928 MPT_FRAME_HDR *mf;
929 MPIHeader_t *hdr;
930 unsigned long timeleft;
931 int error = -ERESTARTSYS;
932
933 /* not implemented for expanders */
934 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
935 return -ENXIO;
936
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100937 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200938 goto out;
939
940 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
941 if (!mf) {
942 error = -ENOMEM;
943 goto out_unlock;
944 }
945
946 hdr = (MPIHeader_t *) mf;
947 req = (SasIoUnitControlRequest_t *)mf;
948 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
949 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
950 req->MsgContext = hdr->MsgContext;
951 req->Operation = hard_reset ?
952 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
953 req->PhyNum = phy->identify.phy_identifier;
954
955 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
956
957 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
958 10 * HZ);
959 if (!timeleft) {
960 /* On timeout reset the board */
961 mpt_free_msg_frame(ioc, mf);
962 mpt_HardResetHandler(ioc, CAN_SLEEP);
963 error = -ETIMEDOUT;
964 goto out_unlock;
965 }
966
967 /* a reply frame is expected */
968 if ((ioc->sas_mgmt.status &
969 MPT_IOCTL_STATUS_RF_VALID) == 0) {
970 error = -ENXIO;
971 goto out_unlock;
972 }
973
974 /* process the completed Reply Message Frame */
975 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
976 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
977 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
978 __FUNCTION__,
979 reply->IOCStatus,
980 reply->IOCLogInfo);
981 error = -ENXIO;
982 goto out_unlock;
983 }
984
985 error = 0;
986
987 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100988 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200989 out:
990 return error;
991}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200992
Christoph Hellwige3094442006-02-16 13:25:36 +0100993static int
994mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
995{
996 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
997 int i, error;
998 struct mptsas_portinfo *p;
999 struct mptsas_enclosure enclosure_info;
1000 u64 enclosure_handle;
1001
1002 mutex_lock(&ioc->sas_topology_mutex);
1003 list_for_each_entry(p, &ioc->sas_topology, list) {
1004 for (i = 0; i < p->num_phys; i++) {
1005 if (p->phy_info[i].attached.sas_address ==
1006 rphy->identify.sas_address) {
1007 enclosure_handle = p->phy_info[i].
1008 attached.handle_enclosure;
1009 goto found_info;
1010 }
1011 }
1012 }
1013 mutex_unlock(&ioc->sas_topology_mutex);
1014 return -ENXIO;
1015
1016 found_info:
1017 mutex_unlock(&ioc->sas_topology_mutex);
1018 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -07001019 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +01001020 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1021 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1022 if (!error)
1023 *identifier = enclosure_info.enclosure_logical_id;
1024 return error;
1025}
1026
1027static int
1028mptsas_get_bay_identifier(struct sas_rphy *rphy)
1029{
1030 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1031 struct mptsas_portinfo *p;
1032 int i, rc;
1033
1034 mutex_lock(&ioc->sas_topology_mutex);
1035 list_for_each_entry(p, &ioc->sas_topology, list) {
1036 for (i = 0; i < p->num_phys; i++) {
1037 if (p->phy_info[i].attached.sas_address ==
1038 rphy->identify.sas_address) {
1039 rc = p->phy_info[i].attached.slot;
1040 goto out;
1041 }
1042 }
1043 }
1044 rc = -ENXIO;
1045 out:
1046 mutex_unlock(&ioc->sas_topology_mutex);
1047 return rc;
1048}
1049
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001050static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +02001051 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +01001052 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1053 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001054 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001055};
1056
1057static struct scsi_transport_template *mptsas_transport_template;
1058
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001059static int
1060mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1061{
1062 ConfigExtendedPageHeader_t hdr;
1063 CONFIGPARMS cfg;
1064 SasIOUnitPage0_t *buffer;
1065 dma_addr_t dma_handle;
1066 int error, i;
1067
1068 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1069 hdr.ExtPageLength = 0;
1070 hdr.PageNumber = 0;
1071 hdr.Reserved1 = 0;
1072 hdr.Reserved2 = 0;
1073 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1074 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1075
1076 cfg.cfghdr.ehdr = &hdr;
1077 cfg.physAddr = -1;
1078 cfg.pageAddr = 0;
1079 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1080 cfg.dir = 0; /* read */
1081 cfg.timeout = 10;
1082
1083 error = mpt_config(ioc, &cfg);
1084 if (error)
1085 goto out;
1086 if (!hdr.ExtPageLength) {
1087 error = -ENXIO;
1088 goto out;
1089 }
1090
1091 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1092 &dma_handle);
1093 if (!buffer) {
1094 error = -ENOMEM;
1095 goto out;
1096 }
1097
1098 cfg.physAddr = dma_handle;
1099 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1100
1101 error = mpt_config(ioc, &cfg);
1102 if (error)
1103 goto out_free_consistent;
1104
1105 port_info->num_phys = buffer->NumPhys;
1106 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001107 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001108 if (!port_info->phy_info) {
1109 error = -ENOMEM;
1110 goto out_free_consistent;
1111 }
1112
Moore, Ericdb9c9172006-03-14 09:14:18 -07001113 if (port_info->num_phys)
1114 port_info->handle =
1115 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001116 for (i = 0; i < port_info->num_phys; i++) {
1117 mptsas_print_phy_data(&buffer->PhyData[i]);
1118 port_info->phy_info[i].phy_id = i;
1119 port_info->phy_info[i].port_id =
1120 buffer->PhyData[i].Port;
1121 port_info->phy_info[i].negotiated_link_rate =
1122 buffer->PhyData[i].NegotiatedLinkRate;
Eric Moore547f9a22006-06-27 14:42:12 -06001123 port_info->phy_info[i].portinfo = port_info;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001124 }
1125
1126 out_free_consistent:
1127 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1128 buffer, dma_handle);
1129 out:
1130 return error;
1131}
1132
1133static int
1134mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1135 u32 form, u32 form_specific)
1136{
1137 ConfigExtendedPageHeader_t hdr;
1138 CONFIGPARMS cfg;
1139 SasPhyPage0_t *buffer;
1140 dma_addr_t dma_handle;
1141 int error;
1142
1143 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1144 hdr.ExtPageLength = 0;
1145 hdr.PageNumber = 0;
1146 hdr.Reserved1 = 0;
1147 hdr.Reserved2 = 0;
1148 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1149 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1150
1151 cfg.cfghdr.ehdr = &hdr;
1152 cfg.dir = 0; /* read */
1153 cfg.timeout = 10;
1154
1155 /* Get Phy Pg 0 for each Phy. */
1156 cfg.physAddr = -1;
1157 cfg.pageAddr = form + form_specific;
1158 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1159
1160 error = mpt_config(ioc, &cfg);
1161 if (error)
1162 goto out;
1163
1164 if (!hdr.ExtPageLength) {
1165 error = -ENXIO;
1166 goto out;
1167 }
1168
1169 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1170 &dma_handle);
1171 if (!buffer) {
1172 error = -ENOMEM;
1173 goto out;
1174 }
1175
1176 cfg.physAddr = dma_handle;
1177 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1178
1179 error = mpt_config(ioc, &cfg);
1180 if (error)
1181 goto out_free_consistent;
1182
1183 mptsas_print_phy_pg0(buffer);
1184
1185 phy_info->hw_link_rate = buffer->HwLinkRate;
1186 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1187 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1188 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1189
1190 out_free_consistent:
1191 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1192 buffer, dma_handle);
1193 out:
1194 return error;
1195}
1196
1197static int
1198mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1199 u32 form, u32 form_specific)
1200{
1201 ConfigExtendedPageHeader_t hdr;
1202 CONFIGPARMS cfg;
1203 SasDevicePage0_t *buffer;
1204 dma_addr_t dma_handle;
1205 __le64 sas_address;
Moore, Ericbd23e942006-04-17 12:43:04 -06001206 int error=0;
1207
1208 if (ioc->sas_discovery_runtime &&
1209 mptsas_is_end_device(device_info))
1210 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001211
1212 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1213 hdr.ExtPageLength = 0;
1214 hdr.PageNumber = 0;
1215 hdr.Reserved1 = 0;
1216 hdr.Reserved2 = 0;
1217 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1218 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1219
1220 cfg.cfghdr.ehdr = &hdr;
1221 cfg.pageAddr = form + form_specific;
1222 cfg.physAddr = -1;
1223 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1224 cfg.dir = 0; /* read */
1225 cfg.timeout = 10;
1226
Moore, Ericdb9c9172006-03-14 09:14:18 -07001227 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001228 error = mpt_config(ioc, &cfg);
1229 if (error)
1230 goto out;
1231 if (!hdr.ExtPageLength) {
1232 error = -ENXIO;
1233 goto out;
1234 }
1235
1236 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1237 &dma_handle);
1238 if (!buffer) {
1239 error = -ENOMEM;
1240 goto out;
1241 }
1242
1243 cfg.physAddr = dma_handle;
1244 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1245
1246 error = mpt_config(ioc, &cfg);
1247 if (error)
1248 goto out_free_consistent;
1249
1250 mptsas_print_device_pg0(buffer);
1251
1252 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001253 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +01001254 device_info->handle_enclosure =
1255 le16_to_cpu(buffer->EnclosureHandle);
1256 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001257 device_info->phy_id = buffer->PhyNum;
1258 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001259 device_info->id = buffer->TargetID;
1260 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001261 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1262 device_info->sas_address = le64_to_cpu(sas_address);
1263 device_info->device_info =
1264 le32_to_cpu(buffer->DeviceInfo);
1265
1266 out_free_consistent:
1267 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1268 buffer, dma_handle);
1269 out:
1270 return error;
1271}
1272
1273static int
1274mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1275 u32 form, u32 form_specific)
1276{
1277 ConfigExtendedPageHeader_t hdr;
1278 CONFIGPARMS cfg;
1279 SasExpanderPage0_t *buffer;
1280 dma_addr_t dma_handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001281 int i, error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001282
1283 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1284 hdr.ExtPageLength = 0;
1285 hdr.PageNumber = 0;
1286 hdr.Reserved1 = 0;
1287 hdr.Reserved2 = 0;
1288 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1289 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1290
1291 cfg.cfghdr.ehdr = &hdr;
1292 cfg.physAddr = -1;
1293 cfg.pageAddr = form + form_specific;
1294 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1295 cfg.dir = 0; /* read */
1296 cfg.timeout = 10;
1297
Moore, Ericdb9c9172006-03-14 09:14:18 -07001298 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001299 error = mpt_config(ioc, &cfg);
1300 if (error)
1301 goto out;
1302
1303 if (!hdr.ExtPageLength) {
1304 error = -ENXIO;
1305 goto out;
1306 }
1307
1308 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1309 &dma_handle);
1310 if (!buffer) {
1311 error = -ENOMEM;
1312 goto out;
1313 }
1314
1315 cfg.physAddr = dma_handle;
1316 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1317
1318 error = mpt_config(ioc, &cfg);
1319 if (error)
1320 goto out_free_consistent;
1321
1322 /* save config data */
1323 port_info->num_phys = buffer->NumPhys;
1324 port_info->handle = le16_to_cpu(buffer->DevHandle);
1325 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001326 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001327 if (!port_info->phy_info) {
1328 error = -ENOMEM;
1329 goto out_free_consistent;
1330 }
1331
Eric Moore547f9a22006-06-27 14:42:12 -06001332 for (i = 0; i < port_info->num_phys; i++)
1333 port_info->phy_info[i].portinfo = port_info;
1334
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001335 out_free_consistent:
1336 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1337 buffer, dma_handle);
1338 out:
1339 return error;
1340}
1341
1342static int
1343mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1344 u32 form, u32 form_specific)
1345{
1346 ConfigExtendedPageHeader_t hdr;
1347 CONFIGPARMS cfg;
1348 SasExpanderPage1_t *buffer;
1349 dma_addr_t dma_handle;
Moore, Ericbd23e942006-04-17 12:43:04 -06001350 int error=0;
1351
1352 if (ioc->sas_discovery_runtime &&
1353 mptsas_is_end_device(&phy_info->attached))
1354 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001355
1356 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1357 hdr.ExtPageLength = 0;
1358 hdr.PageNumber = 1;
1359 hdr.Reserved1 = 0;
1360 hdr.Reserved2 = 0;
1361 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1362 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1363
1364 cfg.cfghdr.ehdr = &hdr;
1365 cfg.physAddr = -1;
1366 cfg.pageAddr = form + form_specific;
1367 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1368 cfg.dir = 0; /* read */
1369 cfg.timeout = 10;
1370
1371 error = mpt_config(ioc, &cfg);
1372 if (error)
1373 goto out;
1374
1375 if (!hdr.ExtPageLength) {
1376 error = -ENXIO;
1377 goto out;
1378 }
1379
1380 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1381 &dma_handle);
1382 if (!buffer) {
1383 error = -ENOMEM;
1384 goto out;
1385 }
1386
1387 cfg.physAddr = dma_handle;
1388 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1389
1390 error = mpt_config(ioc, &cfg);
1391 if (error)
1392 goto out_free_consistent;
1393
1394
1395 mptsas_print_expander_pg1(buffer);
1396
1397 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001398 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001399 phy_info->port_id = buffer->PhysicalPort;
1400 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1401 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1402 phy_info->hw_link_rate = buffer->HwLinkRate;
1403 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1404 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1405
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001406 out_free_consistent:
1407 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1408 buffer, dma_handle);
1409 out:
1410 return error;
1411}
1412
1413static void
1414mptsas_parse_device_info(struct sas_identify *identify,
1415 struct mptsas_devinfo *device_info)
1416{
1417 u16 protocols;
1418
1419 identify->sas_address = device_info->sas_address;
1420 identify->phy_identifier = device_info->phy_id;
1421
1422 /*
1423 * Fill in Phy Initiator Port Protocol.
1424 * Bits 6:3, more than one bit can be set, fall through cases.
1425 */
1426 protocols = device_info->device_info & 0x78;
1427 identify->initiator_port_protocols = 0;
1428 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1429 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1430 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1431 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1432 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1433 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1434 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1435 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1436
1437 /*
1438 * Fill in Phy Target Port Protocol.
1439 * Bits 10:7, more than one bit can be set, fall through cases.
1440 */
1441 protocols = device_info->device_info & 0x780;
1442 identify->target_port_protocols = 0;
1443 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1444 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1445 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1446 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1447 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1448 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1449 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1450 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1451
1452 /*
1453 * Fill in Attached device type.
1454 */
1455 switch (device_info->device_info &
1456 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1457 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1458 identify->device_type = SAS_PHY_UNUSED;
1459 break;
1460 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1461 identify->device_type = SAS_END_DEVICE;
1462 break;
1463 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1464 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1465 break;
1466 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1467 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1468 break;
1469 }
1470}
1471
1472static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001473 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001474{
Moore, Erice6b2d762006-03-14 09:14:24 -07001475 MPT_ADAPTER *ioc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001476 struct sas_phy *phy;
Eric Moore547f9a22006-06-27 14:42:12 -06001477 struct sas_port *port;
1478 int error = 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001479
Eric Moore547f9a22006-06-27 14:42:12 -06001480 if (!dev) {
1481 error = -ENODEV;
1482 goto out;
1483 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001484
1485 if (!phy_info->phy) {
1486 phy = sas_phy_alloc(dev, index);
Eric Moore547f9a22006-06-27 14:42:12 -06001487 if (!phy) {
1488 error = -ENOMEM;
1489 goto out;
1490 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001491 } else
1492 phy = phy_info->phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001493
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001494 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001495
1496 /*
1497 * Set Negotiated link rate.
1498 */
1499 switch (phy_info->negotiated_link_rate) {
1500 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001501 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001502 break;
1503 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001504 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001505 break;
1506 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001507 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001508 break;
1509 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001510 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001511 break;
1512 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1513 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1514 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001515 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001516 break;
1517 }
1518
1519 /*
1520 * Set Max hardware link rate.
1521 */
1522 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1523 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001524 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001525 break;
1526 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001527 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001528 break;
1529 default:
1530 break;
1531 }
1532
1533 /*
1534 * Set Max programmed link rate.
1535 */
1536 switch (phy_info->programmed_link_rate &
1537 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1538 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001539 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001540 break;
1541 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001542 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001543 break;
1544 default:
1545 break;
1546 }
1547
1548 /*
1549 * Set Min hardware link rate.
1550 */
1551 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1552 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001553 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001554 break;
1555 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001556 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001557 break;
1558 default:
1559 break;
1560 }
1561
1562 /*
1563 * Set Min programmed link rate.
1564 */
1565 switch (phy_info->programmed_link_rate &
1566 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1567 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001568 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001569 break;
1570 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001571 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001572 break;
1573 default:
1574 break;
1575 }
1576
Moore, Erice6b2d762006-03-14 09:14:24 -07001577 if (!phy_info->phy) {
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001578
Moore, Erice6b2d762006-03-14 09:14:24 -07001579 if (local)
1580 phy->local_attached = 1;
1581
1582 error = sas_phy_add(phy);
1583 if (error) {
1584 sas_phy_free(phy);
Eric Moore547f9a22006-06-27 14:42:12 -06001585 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001586 }
1587 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001588 }
1589
Eric Moore547f9a22006-06-27 14:42:12 -06001590 if (!phy_info->attached.handle ||
1591 !phy_info->port_details)
1592 goto out;
1593
1594 port = mptsas_get_port(phy_info);
1595 ioc = phy_to_ioc(phy_info->phy);
1596
1597 if (phy_info->sas_port_add_phy) {
1598
1599 if (!port) {
Eric Mooredc22f162006-07-06 11:23:14 -06001600 port = sas_port_alloc_num(dev);
Eric Moore547f9a22006-06-27 14:42:12 -06001601 if (!port) {
1602 error = -ENOMEM;
1603 goto out;
1604 }
1605 error = sas_port_add(port);
1606 if (error) {
1607 dfailprintk((MYIOC_s_ERR_FMT
1608 "%s: exit at line=%d\n", ioc->name,
1609 __FUNCTION__, __LINE__));
1610 goto out;
1611 }
1612 mptsas_set_port(phy_info, port);
Eric Mooredc22f162006-07-06 11:23:14 -06001613 dsaswideprintk((KERN_DEBUG
1614 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
1615 port, dev, port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06001616 }
1617 dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
1618 phy_info->phy_id));
1619 sas_port_add_phy(port, phy_info->phy);
1620 phy_info->sas_port_add_phy = 0;
1621 }
1622
1623 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
Moore, Erice6b2d762006-03-14 09:14:24 -07001624
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001625 struct sas_rphy *rphy;
James Bottomley2686de22006-06-30 12:54:02 -05001626 struct device *parent;
James Bottomleyf013db32006-03-18 14:54:36 -06001627 struct sas_identify identify;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001628
James Bottomley2686de22006-06-30 12:54:02 -05001629 parent = dev->parent->parent;
Moore, Erice6b2d762006-03-14 09:14:24 -07001630 /*
1631 * Let the hotplug_work thread handle processing
1632 * the adding/removing of devices that occur
1633 * after start of day.
1634 */
1635 if (ioc->sas_discovery_runtime &&
1636 mptsas_is_end_device(&phy_info->attached))
Eric Moore547f9a22006-06-27 14:42:12 -06001637 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001638
James Bottomleyf013db32006-03-18 14:54:36 -06001639 mptsas_parse_device_info(&identify, &phy_info->attached);
James Bottomley2686de22006-06-30 12:54:02 -05001640 if (scsi_is_host_device(parent)) {
1641 struct mptsas_portinfo *port_info;
1642 int i;
1643
1644 mutex_lock(&ioc->sas_topology_mutex);
1645 port_info = mptsas_find_portinfo_by_handle(ioc,
1646 ioc->handle);
1647 mutex_unlock(&ioc->sas_topology_mutex);
1648
1649 for (i = 0; i < port_info->num_phys; i++)
1650 if (port_info->phy_info[i].identify.sas_address ==
1651 identify.sas_address)
1652 goto out;
1653
1654 } else if (scsi_is_sas_rphy(parent)) {
1655 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
1656 if (identify.sas_address ==
1657 parent_rphy->identify.sas_address)
1658 goto out;
1659 }
1660
James Bottomleyf013db32006-03-18 14:54:36 -06001661 switch (identify.device_type) {
1662 case SAS_END_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001663 rphy = sas_end_device_alloc(port);
James Bottomleyf013db32006-03-18 14:54:36 -06001664 break;
1665 case SAS_EDGE_EXPANDER_DEVICE:
1666 case SAS_FANOUT_EXPANDER_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001667 rphy = sas_expander_alloc(port, identify.device_type);
James Bottomleyf013db32006-03-18 14:54:36 -06001668 break;
1669 default:
1670 rphy = NULL;
1671 break;
1672 }
Eric Moore547f9a22006-06-27 14:42:12 -06001673 if (!rphy) {
1674 dfailprintk((MYIOC_s_ERR_FMT
1675 "%s: exit at line=%d\n", ioc->name,
1676 __FUNCTION__, __LINE__));
1677 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001678 }
1679
Eric Moore547f9a22006-06-27 14:42:12 -06001680 rphy->identify = identify;
1681 error = sas_rphy_add(rphy);
1682 if (error) {
1683 dfailprintk((MYIOC_s_ERR_FMT
1684 "%s: exit at line=%d\n", ioc->name,
1685 __FUNCTION__, __LINE__));
1686 sas_rphy_free(rphy);
1687 goto out;
1688 }
1689 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001690 }
1691
Eric Moore547f9a22006-06-27 14:42:12 -06001692 out:
1693 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001694}
1695
1696static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001697mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001698{
Moore, Erice6b2d762006-03-14 09:14:24 -07001699 struct mptsas_portinfo *port_info, *hba;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001700 u32 handle = 0xFFFF;
1701 int error = -ENOMEM, i;
1702
Moore, Erice6b2d762006-03-14 09:14:24 -07001703 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
1704 if (! hba)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001705 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001706
Moore, Erice6b2d762006-03-14 09:14:24 -07001707 error = mptsas_sas_io_unit_pg0(ioc, hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001708 if (error)
1709 goto out_free_port_info;
1710
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001711 mutex_lock(&ioc->sas_topology_mutex);
James Bottomley2686de22006-06-30 12:54:02 -05001712 ioc->handle = hba->handle;
Moore, Erice6b2d762006-03-14 09:14:24 -07001713 port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
1714 if (!port_info) {
1715 port_info = hba;
1716 list_add_tail(&port_info->list, &ioc->sas_topology);
1717 } else {
1718 port_info->handle = hba->handle;
1719 for (i = 0; i < hba->num_phys; i++)
1720 port_info->phy_info[i].negotiated_link_rate =
1721 hba->phy_info[i].negotiated_link_rate;
Eric Moore547f9a22006-06-27 14:42:12 -06001722 kfree(hba->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001723 kfree(hba);
1724 hba = NULL;
1725 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001726 mutex_unlock(&ioc->sas_topology_mutex);
1727
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001728 for (i = 0; i < port_info->num_phys; i++) {
1729 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1730 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1731 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1732
1733 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1734 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1735 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001736 port_info->phy_info[i].identify.phy_id =
1737 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001738 handle = port_info->phy_info[i].identify.handle;
1739
Eric Moore547f9a22006-06-27 14:42:12 -06001740 if (port_info->phy_info[i].attached.handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001741 mptsas_sas_device_pg0(ioc,
1742 &port_info->phy_info[i].attached,
1743 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1744 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1745 port_info->phy_info[i].attached.handle);
Eric Moore547f9a22006-06-27 14:42:12 -06001746 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001747
Eric Moore547f9a22006-06-27 14:42:12 -06001748 mptsas_setup_wide_ports(ioc, port_info);
1749
1750 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001751 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Moore, Erice6b2d762006-03-14 09:14:24 -07001752 &port_info->phy_info[i], ioc->sas_index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001753
1754 return 0;
1755
1756 out_free_port_info:
Eric Moore547f9a22006-06-27 14:42:12 -06001757 kfree(hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001758 out:
1759 return error;
1760}
1761
1762static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001763mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001764{
Moore, Erice6b2d762006-03-14 09:14:24 -07001765 struct mptsas_portinfo *port_info, *p, *ex;
Eric Moore547f9a22006-06-27 14:42:12 -06001766 struct device *parent;
1767 struct sas_rphy *rphy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001768 int error = -ENOMEM, i, j;
1769
Moore, Erice6b2d762006-03-14 09:14:24 -07001770 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
1771 if (!ex)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001772 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001773
Moore, Erice6b2d762006-03-14 09:14:24 -07001774 error = mptsas_sas_expander_pg0(ioc, ex,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001775 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1776 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1777 if (error)
1778 goto out_free_port_info;
1779
Moore, Erice6b2d762006-03-14 09:14:24 -07001780 *handle = ex->handle;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001781
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001782 mutex_lock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07001783 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
1784 if (!port_info) {
1785 port_info = ex;
1786 list_add_tail(&port_info->list, &ioc->sas_topology);
1787 } else {
1788 port_info->handle = ex->handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001789 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001790 kfree(ex);
1791 ex = NULL;
1792 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001793 mutex_unlock(&ioc->sas_topology_mutex);
1794
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001795 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001796 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1797 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1798 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1799
1800 if (port_info->phy_info[i].identify.handle) {
1801 mptsas_sas_device_pg0(ioc,
1802 &port_info->phy_info[i].identify,
1803 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1804 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1805 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001806 port_info->phy_info[i].identify.phy_id =
1807 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001808 }
1809
1810 if (port_info->phy_info[i].attached.handle) {
1811 mptsas_sas_device_pg0(ioc,
1812 &port_info->phy_info[i].attached,
1813 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1814 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1815 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07001816 port_info->phy_info[i].attached.phy_id =
1817 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001818 }
Eric Moore547f9a22006-06-27 14:42:12 -06001819 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001820
Eric Moore547f9a22006-06-27 14:42:12 -06001821 parent = &ioc->sh->shost_gendev;
1822 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001823 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001824 list_for_each_entry(p, &ioc->sas_topology, list) {
1825 for (j = 0; j < p->num_phys; j++) {
Eric Moore547f9a22006-06-27 14:42:12 -06001826 if (port_info->phy_info[i].identify.handle !=
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001827 p->phy_info[j].attached.handle)
Eric Moore547f9a22006-06-27 14:42:12 -06001828 continue;
1829 rphy = mptsas_get_rphy(&p->phy_info[j]);
1830 parent = &rphy->dev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001831 }
1832 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001833 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06001834 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001835
Eric Moore547f9a22006-06-27 14:42:12 -06001836 mptsas_setup_wide_ports(ioc, port_info);
1837
1838 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001839 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
Moore, Erice6b2d762006-03-14 09:14:24 -07001840 ioc->sas_index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001841
1842 return 0;
1843
1844 out_free_port_info:
Moore, Erice6b2d762006-03-14 09:14:24 -07001845 if (ex) {
Eric Moore547f9a22006-06-27 14:42:12 -06001846 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001847 kfree(ex);
1848 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001849 out:
1850 return error;
1851}
1852
Moore, Erice6b2d762006-03-14 09:14:24 -07001853/*
1854 * mptsas_delete_expander_phys
1855 *
1856 *
1857 * This will traverse topology, and remove expanders
1858 * that are no longer present
1859 */
1860static void
1861mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1862{
1863 struct mptsas_portinfo buffer;
1864 struct mptsas_portinfo *port_info, *n, *parent;
Eric Moore547f9a22006-06-27 14:42:12 -06001865 struct mptsas_phyinfo *phy_info;
1866 struct scsi_target * starget;
1867 VirtTarget * vtarget;
1868 struct sas_port * port;
Moore, Erice6b2d762006-03-14 09:14:24 -07001869 int i;
Eric Moore547f9a22006-06-27 14:42:12 -06001870 u64 expander_sas_address;
Moore, Erice6b2d762006-03-14 09:14:24 -07001871
1872 mutex_lock(&ioc->sas_topology_mutex);
1873 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
1874
1875 if (port_info->phy_info &&
1876 (!(port_info->phy_info[0].identify.device_info &
1877 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
1878 continue;
1879
1880 if (mptsas_sas_expander_pg0(ioc, &buffer,
1881 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
1882 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
1883
1884 /*
Eric Moore547f9a22006-06-27 14:42:12 -06001885 * Issue target reset to all child end devices
1886 * then mark them deleted to prevent further
1887 * IO going to them.
1888 */
1889 phy_info = port_info->phy_info;
1890 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
1891 starget = mptsas_get_starget(phy_info);
1892 if (!starget)
1893 continue;
1894 vtarget = starget->hostdata;
1895 if(vtarget->deleted)
1896 continue;
1897 vtarget->deleted = 1;
1898 mptsas_target_reset(ioc, vtarget);
1899 sas_port_delete(mptsas_get_port(phy_info));
1900 mptsas_port_delete(phy_info->port_details);
1901 }
1902
1903 /*
Moore, Erice6b2d762006-03-14 09:14:24 -07001904 * Obtain the port_info instance to the parent port
1905 */
1906 parent = mptsas_find_portinfo_by_handle(ioc,
1907 port_info->phy_info[0].identify.handle_parent);
1908
1909 if (!parent)
1910 goto next_port;
1911
Eric Moore547f9a22006-06-27 14:42:12 -06001912 expander_sas_address =
1913 port_info->phy_info[0].identify.sas_address;
1914
Moore, Erice6b2d762006-03-14 09:14:24 -07001915 /*
1916 * Delete rphys in the parent that point
1917 * to this expander. The transport layer will
1918 * cleanup all the children.
1919 */
Eric Moore547f9a22006-06-27 14:42:12 -06001920 phy_info = parent->phy_info;
1921 for (i = 0; i < parent->num_phys; i++, phy_info++) {
1922 port = mptsas_get_port(phy_info);
1923 if (!port)
Moore, Erice6b2d762006-03-14 09:14:24 -07001924 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06001925 if (phy_info->attached.sas_address !=
1926 expander_sas_address)
1927 continue;
1928#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06001929 dev_printk(KERN_DEBUG, &port->dev,
1930 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06001931#endif
1932 sas_port_delete(port);
1933 mptsas_port_delete(phy_info->port_details);
Moore, Erice6b2d762006-03-14 09:14:24 -07001934 }
1935 next_port:
Eric Moore547f9a22006-06-27 14:42:12 -06001936
1937 phy_info = port_info->phy_info;
1938 for (i = 0; i < port_info->num_phys; i++, phy_info++)
1939 mptsas_port_delete(phy_info->port_details);
1940
Moore, Erice6b2d762006-03-14 09:14:24 -07001941 list_del(&port_info->list);
Eric Moore547f9a22006-06-27 14:42:12 -06001942 kfree(port_info->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001943 kfree(port_info);
1944 }
1945 /*
1946 * Free this memory allocated from inside
1947 * mptsas_sas_expander_pg0
1948 */
Eric Moore547f9a22006-06-27 14:42:12 -06001949 kfree(buffer.phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001950 }
1951 mutex_unlock(&ioc->sas_topology_mutex);
1952}
1953
1954/*
1955 * Start of day discovery
1956 */
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001957static void
1958mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1959{
1960 u32 handle = 0xFFFF;
Moore, Ericf44e5462006-03-14 09:14:21 -07001961 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001962
Moore, Erice6b2d762006-03-14 09:14:24 -07001963 mutex_lock(&ioc->sas_discovery_mutex);
1964 mptsas_probe_hba_phys(ioc);
1965 while (!mptsas_probe_expander_phys(ioc, &handle))
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001966 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07001967 /*
1968 Reporting RAID volumes.
1969 */
1970 if (!ioc->raid_data.pIocPg2)
1971 goto out;
1972 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1973 goto out;
1974 for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
James Bottomleye8bf3942006-07-11 17:49:34 -04001975 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
Moore, Ericf44e5462006-03-14 09:14:21 -07001976 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
1977 }
1978 out:
Moore, Erice6b2d762006-03-14 09:14:24 -07001979 mutex_unlock(&ioc->sas_discovery_mutex);
1980}
1981
1982/*
1983 * Work queue thread to handle Runtime discovery
1984 * Mere purpose is the hot add/delete of expanders
Eric Moore547f9a22006-06-27 14:42:12 -06001985 *(Mutex UNLOCKED)
Moore, Erice6b2d762006-03-14 09:14:24 -07001986 */
1987static void
Eric Moore547f9a22006-06-27 14:42:12 -06001988__mptsas_discovery_work(MPT_ADAPTER *ioc)
Moore, Erice6b2d762006-03-14 09:14:24 -07001989{
Moore, Erice6b2d762006-03-14 09:14:24 -07001990 u32 handle = 0xFFFF;
1991
Moore, Erice6b2d762006-03-14 09:14:24 -07001992 ioc->sas_discovery_runtime=1;
1993 mptsas_delete_expander_phys(ioc);
1994 mptsas_probe_hba_phys(ioc);
1995 while (!mptsas_probe_expander_phys(ioc, &handle))
1996 ;
Moore, Erice6b2d762006-03-14 09:14:24 -07001997 ioc->sas_discovery_runtime=0;
Eric Moore547f9a22006-06-27 14:42:12 -06001998}
1999
2000/*
2001 * Work queue thread to handle Runtime discovery
2002 * Mere purpose is the hot add/delete of expanders
2003 *(Mutex LOCKED)
2004 */
2005static void
2006mptsas_discovery_work(void * arg)
2007{
2008 struct mptsas_discovery_event *ev = arg;
2009 MPT_ADAPTER *ioc = ev->ioc;
2010
2011 mutex_lock(&ioc->sas_discovery_mutex);
2012 __mptsas_discovery_work(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002013 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002014 kfree(ev);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002015}
2016
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002017static struct mptsas_phyinfo *
Eric Moore547f9a22006-06-27 14:42:12 -06002018mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002019{
2020 struct mptsas_portinfo *port_info;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002021 struct mptsas_phyinfo *phy_info = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -06002022 int i;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002023
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002024 mutex_lock(&ioc->sas_topology_mutex);
2025 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2026 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002027 if (port_info->phy_info[i].attached.sas_address
2028 != sas_address)
2029 continue;
2030 if (!mptsas_is_end_device(
2031 &port_info->phy_info[i].attached))
2032 continue;
2033 phy_info = &port_info->phy_info[i];
2034 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002035 }
2036 }
2037 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002038 return phy_info;
2039}
2040
2041static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07002042mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002043{
2044 struct mptsas_portinfo *port_info;
2045 struct mptsas_phyinfo *phy_info = NULL;
2046 int i;
2047
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002048 mutex_lock(&ioc->sas_topology_mutex);
2049 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -06002050 for (i = 0; i < port_info->num_phys; i++) {
2051 if (port_info->phy_info[i].attached.id != id)
2052 continue;
2053 if (!mptsas_is_end_device(
2054 &port_info->phy_info[i].attached))
2055 continue;
2056 phy_info = &port_info->phy_info[i];
2057 break;
2058 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002059 }
2060 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002061 return phy_info;
2062}
2063
Moore, Eric4b766472006-03-14 09:14:12 -07002064/*
2065 * Work queue thread to clear the persitency table
2066 */
2067static void
Eric Moore547f9a22006-06-27 14:42:12 -06002068mptsas_persist_clear_table(void * arg)
Moore, Eric4b766472006-03-14 09:14:12 -07002069{
2070 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
2071
2072 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2073}
2074
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002075static void
Moore, Ericf44e5462006-03-14 09:14:21 -07002076mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2077{
2078 sdev->no_uld_attach = data ? 1 : 0;
2079 scsi_device_reprobe(sdev);
2080}
2081
2082static void
2083mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2084{
2085 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2086 mptsas_reprobe_lun);
2087}
2088
Moore, Erice6b2d762006-03-14 09:14:24 -07002089/*
2090 * Work queue thread to handle SAS hotplug events
2091 */
Moore, Ericf44e5462006-03-14 09:14:21 -07002092static void
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002093mptsas_hotplug_work(void *arg)
2094{
2095 struct mptsas_hotplug_event *ev = arg;
2096 MPT_ADAPTER *ioc = ev->ioc;
2097 struct mptsas_phyinfo *phy_info;
2098 struct sas_rphy *rphy;
Eric Moore547f9a22006-06-27 14:42:12 -06002099 struct sas_port *port;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002100 struct scsi_device *sdev;
Eric Moore547f9a22006-06-27 14:42:12 -06002101 struct scsi_target * starget;
James Bottomleyf013db32006-03-18 14:54:36 -06002102 struct sas_identify identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002103 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002104 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07002105 VirtTarget *vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -06002106 VirtDevice *vdevice;
2107
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002108
Moore, Erice6b2d762006-03-14 09:14:24 -07002109 mutex_lock(&ioc->sas_discovery_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002110 switch (ev->event_type) {
2111 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002112
Moore, Ericc73787ee2006-01-26 16:20:06 -07002113 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Moore, Erice6b2d762006-03-14 09:14:24 -07002114
Moore, Ericf44e5462006-03-14 09:14:21 -07002115 /*
2116 * Sanity checks, for non-existing phys and remote rphys.
2117 */
Eric Moore547f9a22006-06-27 14:42:12 -06002118 if (!phy_info || !phy_info->port_details) {
2119 dfailprintk((MYIOC_s_ERR_FMT
2120 "%s: exit at line=%d\n", ioc->name,
2121 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002122 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002123 }
2124 rphy = mptsas_get_rphy(phy_info);
2125 if (!rphy) {
2126 dfailprintk((MYIOC_s_ERR_FMT
2127 "%s: exit at line=%d\n", ioc->name,
2128 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002129 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002130 }
2131 port = mptsas_get_port(phy_info);
2132 if (!port) {
2133 dfailprintk((MYIOC_s_ERR_FMT
2134 "%s: exit at line=%d\n", ioc->name,
2135 __FUNCTION__, __LINE__));
2136 break;
2137 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002138
Eric Moore547f9a22006-06-27 14:42:12 -06002139 starget = mptsas_get_starget(phy_info);
2140 if (starget) {
2141 vtarget = starget->hostdata;
2142
2143 if (!vtarget) {
2144 dfailprintk((MYIOC_s_ERR_FMT
2145 "%s: exit at line=%d\n", ioc->name,
2146 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002147 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002148 }
2149
Moore, Ericf44e5462006-03-14 09:14:21 -07002150 /*
2151 * Handling RAID components
2152 */
2153 if (ev->phys_disk_num_valid) {
2154 vtarget->target_id = ev->phys_disk_num;
2155 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore547f9a22006-06-27 14:42:12 -06002156 mptsas_reprobe_target(starget, 1);
Moore, Ericf44e5462006-03-14 09:14:21 -07002157 break;
2158 }
Eric Moore547f9a22006-06-27 14:42:12 -06002159
2160 vtarget->deleted = 1;
2161 mptsas_target_reset(ioc, vtarget);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002162 }
2163
Moore, Ericc73787ee2006-01-26 16:20:06 -07002164 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2165 ds = "ssp";
2166 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2167 ds = "stp";
2168 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2169 ds = "sata";
2170
2171 printk(MYIOC_s_INFO_FMT
2172 "removing %s device, channel %d, id %d, phy %d\n",
2173 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
2174
Eric Moore547f9a22006-06-27 14:42:12 -06002175#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06002176 dev_printk(KERN_DEBUG, &port->dev,
2177 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002178#endif
2179 sas_port_delete(port);
2180 mptsas_port_delete(phy_info->port_details);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002181 break;
2182 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002183
Moore, Ericbd23e942006-04-17 12:43:04 -06002184 if (ev->phys_disk_num_valid)
2185 mpt_findImVolumes(ioc);
2186
Moore, Ericc73787ee2006-01-26 16:20:06 -07002187 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01002188 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07002189 */
Christoph Hellwige3094442006-02-16 13:25:36 +01002190 if (mptsas_sas_device_pg0(ioc, &sas_device,
2191 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
Eric Moore547f9a22006-06-27 14:42:12 -06002192 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
2193 dfailprintk((MYIOC_s_ERR_FMT
2194 "%s: exit at line=%d\n", ioc->name,
2195 __FUNCTION__, __LINE__));
Christoph Hellwige3094442006-02-16 13:25:36 +01002196 break;
Moore, Erice6b2d762006-03-14 09:14:24 -07002197 }
2198
Eric Moore547f9a22006-06-27 14:42:12 -06002199 ssleep(2);
2200 __mptsas_discovery_work(ioc);
Moore, Ericf44e5462006-03-14 09:14:21 -07002201
Eric Moore547f9a22006-06-27 14:42:12 -06002202 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2203 sas_device.sas_address);
2204
2205 if (!phy_info || !phy_info->port_details) {
2206 dfailprintk((MYIOC_s_ERR_FMT
2207 "%s: exit at line=%d\n", ioc->name,
2208 __FUNCTION__, __LINE__));
2209 break;
2210 }
2211
2212 starget = mptsas_get_starget(phy_info);
2213 if (starget) {
2214 vtarget = starget->hostdata;
2215
2216 if (!vtarget) {
2217 dfailprintk((MYIOC_s_ERR_FMT
2218 "%s: exit at line=%d\n", ioc->name,
2219 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002220 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002221 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002222 /*
2223 * Handling RAID components
2224 */
2225 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
2226 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
2227 vtarget->target_id = ev->id;
Eric Moore547f9a22006-06-27 14:42:12 -06002228 mptsas_reprobe_target(starget, 0);
Moore, Ericf44e5462006-03-14 09:14:21 -07002229 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002230 break;
2231 }
2232
Eric Moore547f9a22006-06-27 14:42:12 -06002233 if (mptsas_get_rphy(phy_info)) {
2234 dfailprintk((MYIOC_s_ERR_FMT
2235 "%s: exit at line=%d\n", ioc->name,
2236 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002237 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002238 }
2239 port = mptsas_get_port(phy_info);
2240 if (!port) {
2241 dfailprintk((MYIOC_s_ERR_FMT
2242 "%s: exit at line=%d\n", ioc->name,
2243 __FUNCTION__, __LINE__));
2244 break;
2245 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002246
Christoph Hellwige3094442006-02-16 13:25:36 +01002247 memcpy(&phy_info->attached, &sas_device,
2248 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002249
Moore, Ericc73787ee2006-01-26 16:20:06 -07002250 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2251 ds = "ssp";
2252 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2253 ds = "stp";
2254 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2255 ds = "sata";
2256
2257 printk(MYIOC_s_INFO_FMT
2258 "attaching %s device, channel %d, id %d, phy %d\n",
2259 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2260
James Bottomleyf013db32006-03-18 14:54:36 -06002261 mptsas_parse_device_info(&identify, &phy_info->attached);
Eric Moore547f9a22006-06-27 14:42:12 -06002262 rphy = sas_end_device_alloc(port);
2263 if (!rphy) {
2264 dfailprintk((MYIOC_s_ERR_FMT
2265 "%s: exit at line=%d\n", ioc->name,
2266 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002267 break; /* non-fatal: an rphy can be added later */
Eric Moore547f9a22006-06-27 14:42:12 -06002268 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002269
James Bottomleyf013db32006-03-18 14:54:36 -06002270 rphy->identify = identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002271 if (sas_rphy_add(rphy)) {
Eric Moore547f9a22006-06-27 14:42:12 -06002272 dfailprintk((MYIOC_s_ERR_FMT
2273 "%s: exit at line=%d\n", ioc->name,
2274 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002275 sas_rphy_free(rphy);
2276 break;
2277 }
Eric Moore547f9a22006-06-27 14:42:12 -06002278 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002279 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002280 case MPTSAS_ADD_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002281 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2282 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002283 if (sdev) {
2284 scsi_device_put(sdev);
2285 break;
2286 }
2287 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002288 "attaching raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002289 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2290 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002291 mpt_findImVolumes(ioc);
2292 break;
2293 case MPTSAS_DEL_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002294 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2295 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002296 if (!sdev)
2297 break;
2298 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002299 "removing raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002300 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
Eric Moore547f9a22006-06-27 14:42:12 -06002301 vdevice = sdev->hostdata;
2302 vdevice->vtarget->deleted = 1;
2303 mptsas_target_reset(ioc, vdevice->vtarget);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002304 scsi_remove_device(sdev);
2305 scsi_device_put(sdev);
2306 mpt_findImVolumes(ioc);
2307 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002308 case MPTSAS_IGNORE_EVENT:
2309 default:
2310 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002311 }
2312
Moore, Erice6b2d762006-03-14 09:14:24 -07002313 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002314 kfree(ev);
2315
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002316}
2317
2318static void
Eric Moore547f9a22006-06-27 14:42:12 -06002319mptsas_send_sas_event(MPT_ADAPTER *ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002320 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2321{
2322 struct mptsas_hotplug_event *ev;
2323 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2324 __le64 sas_address;
2325
2326 if ((device_info &
2327 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2328 MPI_SAS_DEVICE_INFO_STP_TARGET |
2329 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2330 return;
2331
Moore, Eric4b766472006-03-14 09:14:12 -07002332 switch (sas_event_data->ReasonCode) {
2333 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2334 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
Eric Moore547f9a22006-06-27 14:42:12 -06002335 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Eric4b766472006-03-14 09:14:12 -07002336 if (!ev) {
2337 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2338 break;
2339 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002340
Moore, Eric4b766472006-03-14 09:14:12 -07002341 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
2342 ev->ioc = ioc;
2343 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2344 ev->parent_handle =
2345 le16_to_cpu(sas_event_data->ParentDevHandle);
2346 ev->channel = sas_event_data->Bus;
2347 ev->id = sas_event_data->TargetID;
2348 ev->phy_id = sas_event_data->PhyNum;
2349 memcpy(&sas_address, &sas_event_data->SASAddress,
2350 sizeof(__le64));
2351 ev->sas_address = le64_to_cpu(sas_address);
2352 ev->device_info = device_info;
2353
2354 if (sas_event_data->ReasonCode &
2355 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2356 ev->event_type = MPTSAS_ADD_DEVICE;
2357 else
2358 ev->event_type = MPTSAS_DEL_DEVICE;
2359 schedule_work(&ev->work);
2360 break;
2361 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2362 /*
2363 * Persistent table is full.
2364 */
Eric Moore547f9a22006-06-27 14:42:12 -06002365 INIT_WORK(&ioc->sas_persist_task,
2366 mptsas_persist_clear_table, (void *)ioc);
2367 schedule_work(&ioc->sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002368 break;
2369 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
2370 /* TODO */
2371 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
2372 /* TODO */
2373 default:
2374 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002375 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002376}
2377
Moore, Ericc73787ee2006-01-26 16:20:06 -07002378static void
Eric Moore547f9a22006-06-27 14:42:12 -06002379mptsas_send_raid_event(MPT_ADAPTER *ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002380 EVENT_DATA_RAID *raid_event_data)
2381{
2382 struct mptsas_hotplug_event *ev;
Moore, Ericbd23e942006-04-17 12:43:04 -06002383 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2384 int state = (status >> 8) & 0xff;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002385
2386 if (ioc->bus_type != SAS)
2387 return;
2388
Eric Moore547f9a22006-06-27 14:42:12 -06002389 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002390 if (!ev) {
2391 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2392 return;
2393 }
2394
Moore, Ericc73787ee2006-01-26 16:20:06 -07002395 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
2396 ev->ioc = ioc;
2397 ev->id = raid_event_data->VolumeID;
Moore, Ericbd23e942006-04-17 12:43:04 -06002398 ev->event_type = MPTSAS_IGNORE_EVENT;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002399
2400 switch (raid_event_data->ReasonCode) {
2401 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
2402 ev->event_type = MPTSAS_ADD_DEVICE;
2403 break;
2404 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07002405 ioc->raid_data.isRaid = 1;
2406 ev->phys_disk_num_valid = 1;
2407 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002408 ev->event_type = MPTSAS_DEL_DEVICE;
2409 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002410 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2411 switch (state) {
2412 case MPI_PD_STATE_ONLINE:
2413 ioc->raid_data.isRaid = 1;
2414 ev->phys_disk_num_valid = 1;
2415 ev->phys_disk_num = raid_event_data->PhysDiskNum;
2416 ev->event_type = MPTSAS_ADD_DEVICE;
2417 break;
2418 case MPI_PD_STATE_MISSING:
2419 case MPI_PD_STATE_NOT_COMPATIBLE:
2420 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2421 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2422 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
2423 ev->event_type = MPTSAS_DEL_DEVICE;
2424 break;
2425 default:
2426 break;
2427 }
2428 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002429 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2430 ev->event_type = MPTSAS_DEL_RAID;
2431 break;
2432 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2433 ev->event_type = MPTSAS_ADD_RAID;
2434 break;
2435 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
Moore, Ericbd23e942006-04-17 12:43:04 -06002436 switch (state) {
2437 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2438 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2439 ev->event_type = MPTSAS_DEL_RAID;
2440 break;
2441 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2442 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2443 ev->event_type = MPTSAS_ADD_RAID;
2444 break;
2445 default:
2446 break;
2447 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002448 break;
2449 default:
2450 break;
2451 }
2452 schedule_work(&ev->work);
2453}
2454
Moore, Erice6b2d762006-03-14 09:14:24 -07002455static void
Eric Moore547f9a22006-06-27 14:42:12 -06002456mptsas_send_discovery_event(MPT_ADAPTER *ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002457 EVENT_DATA_SAS_DISCOVERY *discovery_data)
2458{
2459 struct mptsas_discovery_event *ev;
2460
2461 /*
2462 * DiscoveryStatus
2463 *
2464 * This flag will be non-zero when firmware
2465 * kicks off discovery, and return to zero
2466 * once its completed.
2467 */
2468 if (discovery_data->DiscoveryStatus)
2469 return;
2470
Eric Moore547f9a22006-06-27 14:42:12 -06002471 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Erice6b2d762006-03-14 09:14:24 -07002472 if (!ev)
2473 return;
Eric Moore547f9a22006-06-27 14:42:12 -06002474 INIT_WORK(&ev->work, mptsas_discovery_work, ev);
Moore, Erice6b2d762006-03-14 09:14:24 -07002475 ev->ioc = ioc;
2476 schedule_work(&ev->work);
2477};
2478
2479
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002480static int
2481mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
2482{
Moore, Ericc73787ee2006-01-26 16:20:06 -07002483 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002484 u8 event = le32_to_cpu(reply->Event) & 0xFF;
2485
2486 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002487 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002488
Moore, Erice6b2d762006-03-14 09:14:24 -07002489 /*
2490 * sas_discovery_ignore_events
2491 *
2492 * This flag is to prevent anymore processing of
2493 * sas events once mptsas_remove function is called.
2494 */
2495 if (ioc->sas_discovery_ignore_events) {
2496 rc = mptscsih_event_process(ioc, reply);
2497 goto out;
2498 }
2499
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002500 switch (event) {
2501 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
Eric Moore547f9a22006-06-27 14:42:12 -06002502 mptsas_send_sas_event(ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002503 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002504 break;
2505 case MPI_EVENT_INTEGRATED_RAID:
Eric Moore547f9a22006-06-27 14:42:12 -06002506 mptsas_send_raid_event(ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002507 (EVENT_DATA_RAID *)reply->Data);
2508 break;
Moore, Eric79de2782006-01-25 18:05:15 -07002509 case MPI_EVENT_PERSISTENT_TABLE_FULL:
Eric Moore547f9a22006-06-27 14:42:12 -06002510 INIT_WORK(&ioc->sas_persist_task,
2511 mptsas_persist_clear_table,
Moore, Eric79de2782006-01-25 18:05:15 -07002512 (void *)ioc);
Eric Moore547f9a22006-06-27 14:42:12 -06002513 schedule_work(&ioc->sas_persist_task);
Moore, Eric79de2782006-01-25 18:05:15 -07002514 break;
Moore, Eric4b766472006-03-14 09:14:12 -07002515 case MPI_EVENT_SAS_DISCOVERY:
Eric Moore547f9a22006-06-27 14:42:12 -06002516 mptsas_send_discovery_event(ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002517 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
2518 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002519 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002520 rc = mptscsih_event_process(ioc, reply);
2521 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002522 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002523 out:
2524
2525 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002526}
2527
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002528static int
2529mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2530{
2531 struct Scsi_Host *sh;
2532 MPT_SCSI_HOST *hd;
2533 MPT_ADAPTER *ioc;
2534 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002535 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002536 int numSGE = 0;
2537 int scale;
2538 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002539 int error=0;
2540 int r;
2541
2542 r = mpt_attach(pdev,id);
2543 if (r)
2544 return r;
2545
2546 ioc = pci_get_drvdata(pdev);
2547 ioc->DoneCtx = mptsasDoneCtx;
2548 ioc->TaskCtx = mptsasTaskCtx;
2549 ioc->InternalCtx = mptsasInternalCtx;
2550
2551 /* Added sanity check on readiness of the MPT adapter.
2552 */
2553 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
2554 printk(MYIOC_s_WARN_FMT
2555 "Skipping because it's not operational!\n",
2556 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002557 error = -ENODEV;
2558 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002559 }
2560
2561 if (!ioc->active) {
2562 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
2563 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002564 error = -ENODEV;
2565 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002566 }
2567
2568 /* Sanity check - ensure at least 1 port is INITIATOR capable
2569 */
2570 ioc_cap = 0;
2571 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
2572 if (ioc->pfacts[ii].ProtocolFlags &
2573 MPI_PORTFACTS_PROTOCOL_INITIATOR)
2574 ioc_cap++;
2575 }
2576
2577 if (!ioc_cap) {
2578 printk(MYIOC_s_WARN_FMT
2579 "Skipping ioc=%p because SCSI Initiator mode "
2580 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06002581 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002582 }
2583
2584 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
2585 if (!sh) {
2586 printk(MYIOC_s_WARN_FMT
2587 "Unable to register controller with SCSI subsystem\n",
2588 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002589 error = -1;
2590 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002591 }
2592
2593 spin_lock_irqsave(&ioc->FreeQlock, flags);
2594
2595 /* Attach the SCSI Host to the IOC structure
2596 */
2597 ioc->sh = sh;
2598
2599 sh->io_port = 0;
2600 sh->n_io_port = 0;
2601 sh->irq = 0;
2602
2603 /* set 16 byte cdb's */
2604 sh->max_cmd_len = 16;
2605
2606 sh->max_id = ioc->pfacts->MaxDevices + 1;
2607
2608 sh->transportt = mptsas_transport_template;
2609
2610 sh->max_lun = MPT_LAST_LUN + 1;
2611 sh->max_channel = 0;
2612 sh->this_id = ioc->pfacts[0].PortSCSIID;
2613
2614 /* Required entry.
2615 */
2616 sh->unique_id = ioc->id;
2617
2618 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002619 mutex_init(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07002620 mutex_init(&ioc->sas_discovery_mutex);
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01002621 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002622 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002623
2624 /* Verify that we won't exceed the maximum
2625 * number of chain buffers
2626 * We can optimize: ZZ = req_sz/sizeof(SGE)
2627 * For 32bit SGE's:
2628 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
2629 * + (req_sz - 64)/sizeof(SGE)
2630 * A slightly different algorithm is required for
2631 * 64bit SGEs.
2632 */
2633 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
2634 if (sizeof(dma_addr_t) == sizeof(u64)) {
2635 numSGE = (scale - 1) *
2636 (ioc->facts.MaxChainDepth-1) + scale +
2637 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
2638 sizeof(u32));
2639 } else {
2640 numSGE = 1 + (scale - 1) *
2641 (ioc->facts.MaxChainDepth-1) + scale +
2642 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
2643 sizeof(u32));
2644 }
2645
2646 if (numSGE < sh->sg_tablesize) {
2647 /* Reset this value */
2648 dprintk((MYIOC_s_INFO_FMT
2649 "Resetting sg_tablesize to %d from %d\n",
2650 ioc->name, numSGE, sh->sg_tablesize));
2651 sh->sg_tablesize = numSGE;
2652 }
2653
2654 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2655
2656 hd = (MPT_SCSI_HOST *) sh->hostdata;
2657 hd->ioc = ioc;
2658
2659 /* SCSI needs scsi_cmnd lookup table!
2660 * (with size equal to req_depth*PtrSz!)
2661 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002662 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
2663 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002664 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002665 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002666 }
2667
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002668 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
2669 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002670
2671 /* Allocate memory for the device structures.
2672 * A non-Null pointer at an offset
2673 * indicates a device exists.
2674 * max_id = 1 + maximum id (hosts.h)
2675 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002676 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
2677 if (!hd->Targets) {
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((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002683
2684 /* Clear the TM flags
2685 */
2686 hd->tmPending = 0;
2687 hd->tmState = TM_STATE_NONE;
2688 hd->resetPending = 0;
2689 hd->abortSCpnt = NULL;
2690
2691 /* Clear the pointer used to store
2692 * single-threaded commands, i.e., those
2693 * issued during a bus scan, dv and
2694 * configuration pages.
2695 */
2696 hd->cmdPtr = NULL;
2697
2698 /* Initialize this SCSI Hosts' timers
2699 * To use, set the timer expires field
2700 * and add_timer
2701 */
2702 init_timer(&hd->timer);
2703 hd->timer.data = (unsigned long) hd;
2704 hd->timer.function = mptscsih_timer_expired;
2705
2706 hd->mpt_pq_filter = mpt_pq_filter;
2707 ioc->sas_data.ptClear = mpt_pt_clear;
2708
2709 if (ioc->sas_data.ptClear==1) {
2710 mptbase_sas_persist_operation(
2711 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
2712 }
2713
2714 ddvprintk((MYIOC_s_INFO_FMT
2715 "mpt_pq_filter %x mpt_pq_filter %x\n",
2716 ioc->name,
2717 mpt_pq_filter,
2718 mpt_pq_filter));
2719
2720 init_waitqueue_head(&hd->scandv_waitq);
2721 hd->scandv_wait_done = 0;
2722 hd->last_queue_full = 0;
2723
2724 error = scsi_add_host(sh, &ioc->pcidev->dev);
2725 if (error) {
2726 dprintk((KERN_ERR MYNAM
2727 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002728 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002729 }
2730
2731 mptsas_scan_sas_topology(ioc);
2732
2733 return 0;
2734
Eric Moore547f9a22006-06-27 14:42:12 -06002735 out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002736
2737 mptscsih_remove(pdev);
2738 return error;
2739}
2740
2741static void __devexit mptsas_remove(struct pci_dev *pdev)
2742{
2743 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2744 struct mptsas_portinfo *p, *n;
Eric Moore547f9a22006-06-27 14:42:12 -06002745 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002746
Moore, Erice6b2d762006-03-14 09:14:24 -07002747 ioc->sas_discovery_ignore_events=1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002748 sas_remove_host(ioc->sh);
2749
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002750 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002751 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
2752 list_del(&p->list);
Eric Moore547f9a22006-06-27 14:42:12 -06002753 for (i = 0 ; i < p->num_phys ; i++)
2754 mptsas_port_delete(p->phy_info[i].port_details);
2755 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002756 kfree(p);
2757 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002758 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002759
2760 mptscsih_remove(pdev);
2761}
2762
2763static struct pci_device_id mptsas_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06002764 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002765 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002766 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002767 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002768 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002769 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002770 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002771 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002772 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002773 PCI_ANY_ID, PCI_ANY_ID },
2774 {0} /* Terminating entry */
2775};
2776MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
2777
2778
2779static struct pci_driver mptsas_driver = {
2780 .name = "mptsas",
2781 .id_table = mptsas_pci_table,
2782 .probe = mptsas_probe,
2783 .remove = __devexit_p(mptsas_remove),
2784 .shutdown = mptscsih_shutdown,
2785#ifdef CONFIG_PM
2786 .suspend = mptscsih_suspend,
2787 .resume = mptscsih_resume,
2788#endif
2789};
2790
2791static int __init
2792mptsas_init(void)
2793{
2794 show_mptmod_ver(my_NAME, my_VERSION);
2795
2796 mptsas_transport_template =
2797 sas_attach_transport(&mptsas_transport_functions);
2798 if (!mptsas_transport_template)
2799 return -ENODEV;
2800
2801 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2802 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2803 mptsasInternalCtx =
2804 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002805 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002806
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002807 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07002808 devtverboseprintk((KERN_INFO MYNAM
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002809 ": Registered for IOC event notifications\n"));
2810 }
2811
2812 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2813 dprintk((KERN_INFO MYNAM
2814 ": Registered for IOC reset notifications\n"));
2815 }
2816
2817 return pci_register_driver(&mptsas_driver);
2818}
2819
2820static void __exit
2821mptsas_exit(void)
2822{
2823 pci_unregister_driver(&mptsas_driver);
2824 sas_release_transport(mptsas_transport_template);
2825
2826 mpt_reset_deregister(mptsasDoneCtx);
2827 mpt_event_deregister(mptsasDoneCtx);
2828
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002829 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002830 mpt_deregister(mptsasInternalCtx);
2831 mpt_deregister(mptsasTaskCtx);
2832 mpt_deregister(mptsasDoneCtx);
2833}
2834
2835module_init(mptsas_init);
2836module_exit(mptsas_exit);