blob: 09e9a9d96410942dcfe21bb2d0484ee8f0956693 [file] [log] [blame]
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001/*
2 * linux/drivers/message/fusion/mptsas.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
Eric Moore9f4203b2007-01-04 20:47:47 -07006 * Copyright (c) 1999-2007 LSI Logic Corporation
Christoph Hellwig0c33b272005-09-09 16:27:19 +02007 * (mailto:mpt_linux_developer@lsil.com)
Eric Moore9f4203b2007-01-04 20:47:47 -07008 * Copyright (c) 2005-2007 Dell
Christoph Hellwig0c33b272005-09-09 16:27:19 +02009 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47#include <linux/module.h>
48#include <linux/kernel.h>
49#include <linux/init.h>
50#include <linux/errno.h>
51#include <linux/sched.h>
52#include <linux/workqueue.h>
Eric Moore547f9a22006-06-27 14:42:12 -060053#include <linux/delay.h> /* for mdelay */
Christoph Hellwig0c33b272005-09-09 16:27:19 +020054
Eric Moore547f9a22006-06-27 14:42:12 -060055#include <scsi/scsi.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020056#include <scsi/scsi_cmnd.h>
57#include <scsi/scsi_device.h>
58#include <scsi/scsi_host.h>
59#include <scsi/scsi_transport_sas.h>
Eric Moore547f9a22006-06-27 14:42:12 -060060#include <scsi/scsi_dbg.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020061
62#include "mptbase.h"
63#include "mptscsih.h"
64
65
66#define my_NAME "Fusion MPT SAS Host driver"
67#define my_VERSION MPT_LINUX_VERSION_COMMON
68#define MYNAM "mptsas"
69
James Bottomleye8bf3942006-07-11 17:49:34 -040070/*
71 * Reserved channel for integrated raid
72 */
73#define MPTSAS_RAID_CHANNEL 1
74
Christoph Hellwig0c33b272005-09-09 16:27:19 +020075MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
Eric Moore9f4203b2007-01-04 20:47:47 -070078MODULE_VERSION(my_VERSION);
Christoph Hellwig0c33b272005-09-09 16:27:19 +020079
Christoph Hellwig0c33b272005-09-09 16:27:19 +020080static int mpt_pt_clear;
81module_param(mpt_pt_clear, int, 0);
82MODULE_PARM_DESC(mpt_pt_clear,
Eric Mooreba856d32006-07-11 17:34:01 -060083 " Clear persistency table: enable=1 "
Christoph Hellwig0c33b272005-09-09 16:27:19 +020084 "(default=MPTSCSIH_PT_CLEAR=0)");
85
86static int mptsasDoneCtx = -1;
87static int mptsasTaskCtx = -1;
88static int mptsasInternalCtx = -1; /* Used only for internal commands */
Christoph Hellwigda4fa652005-10-19 20:01:42 +020089static int mptsasMgmtCtx = -1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020090
91
Christoph Hellwig9a28f492006-01-13 18:04:41 +010092enum mptsas_hotplug_action {
93 MPTSAS_ADD_DEVICE,
94 MPTSAS_DEL_DEVICE,
Moore, Ericc73787ee2006-01-26 16:20:06 -070095 MPTSAS_ADD_RAID,
96 MPTSAS_DEL_RAID,
Moore, Ericbd23e942006-04-17 12:43:04 -060097 MPTSAS_IGNORE_EVENT,
Christoph Hellwig9a28f492006-01-13 18:04:41 +010098};
99
100struct mptsas_hotplug_event {
101 struct work_struct work;
102 MPT_ADAPTER *ioc;
103 enum mptsas_hotplug_action event_type;
104 u64 sas_address;
105 u32 channel;
106 u32 id;
107 u32 device_info;
108 u16 handle;
109 u16 parent_handle;
110 u8 phy_id;
Moore, Ericf44e5462006-03-14 09:14:21 -0700111 u8 phys_disk_num;
112 u8 phys_disk_num_valid;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100113};
114
Moore, Erice6b2d762006-03-14 09:14:24 -0700115struct mptsas_discovery_event {
116 struct work_struct work;
117 MPT_ADAPTER *ioc;
118};
119
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200120/*
121 * SAS topology structures
122 *
123 * The MPT Fusion firmware interface spreads information about the
124 * SAS topology over many manufacture pages, thus we need some data
125 * structure to collect it and process it for the SAS transport class.
126 */
127
128struct mptsas_devinfo {
129 u16 handle; /* unique id to address this device */
Moore, Ericc73787ee2006-01-26 16:20:06 -0700130 u16 handle_parent; /* unique id to address parent device */
Christoph Hellwige3094442006-02-16 13:25:36 +0100131 u16 handle_enclosure; /* enclosure identifier of the enclosure */
132 u16 slot; /* physical slot in enclosure */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200133 u8 phy_id; /* phy number of parent device */
134 u8 port_id; /* sas physical port this device
135 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100136 u8 id; /* logical target id of this device */
137 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200138 u64 sas_address; /* WWN of this device,
139 SATA is assigned by HBA,expander */
140 u32 device_info; /* bitfield detailed info about this device */
141};
142
Eric Moore547f9a22006-06-27 14:42:12 -0600143/*
144 * Specific details on ports, wide/narrow
145 */
146struct mptsas_portinfo_details{
Eric Moore547f9a22006-06-27 14:42:12 -0600147 u16 num_phys; /* number of phys belong to this port */
148 u64 phy_bitmask; /* TODO, extend support for 255 phys */
149 struct sas_rphy *rphy; /* transport layer rphy object */
150 struct sas_port *port; /* transport layer port object */
151 struct scsi_target *starget;
152 struct mptsas_portinfo *port_info;
153};
154
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200155struct mptsas_phyinfo {
156 u8 phy_id; /* phy index */
Eric Moore547f9a22006-06-27 14:42:12 -0600157 u8 port_id; /* firmware port identifier */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200158 u8 negotiated_link_rate; /* nego'd link rate for this phy */
159 u8 hw_link_rate; /* hardware max/min phys link rate */
160 u8 programmed_link_rate; /* programmed max/min phy link rate */
Eric Moore547f9a22006-06-27 14:42:12 -0600161 u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200162 struct mptsas_devinfo identify; /* point to phy device info */
163 struct mptsas_devinfo attached; /* point to attached device info */
Eric Moore547f9a22006-06-27 14:42:12 -0600164 struct sas_phy *phy; /* transport layer phy object */
165 struct mptsas_portinfo *portinfo;
166 struct mptsas_portinfo_details * port_details;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200167};
168
169struct mptsas_portinfo {
170 struct list_head list;
171 u16 handle; /* unique id to address this */
Eric Moore547f9a22006-06-27 14:42:12 -0600172 u16 num_phys; /* number of phys */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200173 struct mptsas_phyinfo *phy_info;
174};
175
Christoph Hellwige3094442006-02-16 13:25:36 +0100176struct mptsas_enclosure {
177 u64 enclosure_logical_id; /* The WWN for the enclosure */
178 u16 enclosure_handle; /* unique id to address this */
179 u16 flags; /* details enclosure management */
180 u16 num_slot; /* num slots */
181 u16 start_slot; /* first slot */
182 u8 start_id; /* starting logical target id */
183 u8 start_channel; /* starting logical channel id */
184 u8 sep_id; /* SEP device logical target id */
185 u8 sep_channel; /* SEP channel logical channel id */
186};
187
Eric Moore547f9a22006-06-27 14:42:12 -0600188#ifdef MPT_DEBUG_SAS
Christoph Hellwigb5141122005-10-28 22:07:41 +0200189static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
190{
191 printk("---- IO UNIT PAGE 0 ------------\n");
192 printk("Handle=0x%X\n",
193 le16_to_cpu(phy_data->AttachedDeviceHandle));
194 printk("Controller Handle=0x%X\n",
195 le16_to_cpu(phy_data->ControllerDevHandle));
196 printk("Port=0x%X\n", phy_data->Port);
197 printk("Port Flags=0x%X\n", phy_data->PortFlags);
198 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
199 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
200 printk("Controller PHY Device Info=0x%X\n",
201 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
202 printk("DiscoveryStatus=0x%X\n",
203 le32_to_cpu(phy_data->DiscoveryStatus));
204 printk("\n");
205}
206
207static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
208{
209 __le64 sas_address;
210
211 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
212
213 printk("---- SAS PHY PAGE 0 ------------\n");
214 printk("Attached Device Handle=0x%X\n",
215 le16_to_cpu(pg0->AttachedDevHandle));
216 printk("SAS Address=0x%llX\n",
217 (unsigned long long)le64_to_cpu(sas_address));
218 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
219 printk("Attached Device Info=0x%X\n",
220 le32_to_cpu(pg0->AttachedDeviceInfo));
221 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
222 printk("Change Count=0x%X\n", pg0->ChangeCount);
223 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
224 printk("\n");
225}
226
227static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
228{
229 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200230 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
231 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200232 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200233 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
234 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
235 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200236}
237
238static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
239{
240 __le64 sas_address;
241
242 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
243
244 printk("---- SAS DEVICE PAGE 0 ---------\n");
245 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
Christoph Hellwige3094442006-02-16 13:25:36 +0100246 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200247 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
248 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
Eric Mooref99be432007-01-04 20:46:54 -0700249 printk("SAS Address=0x%llX\n", (unsigned long long)
250 le64_to_cpu(sas_address));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200251 printk("Target ID=0x%X\n", pg0->TargetID);
252 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200253 /* The PhyNum field specifies the PHY number of the parent
254 * device this device is linked to
255 */
256 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
257 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200258 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
259 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
260 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
261 printk("\n");
262}
263
264static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
265{
266 printk("---- SAS EXPANDER PAGE 1 ------------\n");
267
268 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200269 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200270 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
271 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
272 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
273 printk("Owner Device Handle=0x%X\n",
274 le16_to_cpu(pg1->OwnerDevHandle));
275 printk("Attached Device Handle=0x%X\n",
276 le16_to_cpu(pg1->AttachedDevHandle));
277}
278#else
279#define mptsas_print_phy_data(phy_data) do { } while (0)
280#define mptsas_print_phy_pg0(pg0) do { } while (0)
281#define mptsas_print_phy_pg1(pg1) do { } while (0)
282#define mptsas_print_device_pg0(pg0) do { } while (0)
283#define mptsas_print_expander_pg1(pg1) do { } while (0)
284#endif
285
Christoph Hellwige3094442006-02-16 13:25:36 +0100286static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
287{
288 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
289 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
290}
291
292static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
293{
294 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
295 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
296}
297
Moore, Erice6b2d762006-03-14 09:14:24 -0700298/*
299 * mptsas_find_portinfo_by_handle
300 *
301 * This function should be called with the sas_topology_mutex already held
302 */
303static struct mptsas_portinfo *
304mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
305{
306 struct mptsas_portinfo *port_info, *rc=NULL;
307 int i;
308
309 list_for_each_entry(port_info, &ioc->sas_topology, list)
310 for (i = 0; i < port_info->num_phys; i++)
311 if (port_info->phy_info[i].identify.handle == handle) {
312 rc = port_info;
313 goto out;
314 }
315 out:
316 return rc;
317}
318
Moore, Ericbd23e942006-04-17 12:43:04 -0600319/*
320 * Returns true if there is a scsi end device
321 */
322static inline int
323mptsas_is_end_device(struct mptsas_devinfo * attached)
324{
Eric Moore547f9a22006-06-27 14:42:12 -0600325 if ((attached->sas_address) &&
Moore, Ericbd23e942006-04-17 12:43:04 -0600326 (attached->device_info &
327 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
328 ((attached->device_info &
329 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
330 (attached->device_info &
331 MPI_SAS_DEVICE_INFO_STP_TARGET) |
332 (attached->device_info &
333 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
334 return 1;
335 else
336 return 0;
337}
338
Eric Moore547f9a22006-06-27 14:42:12 -0600339/* no mutex */
Eric Moore376ac832006-06-29 17:36:26 -0600340static void
Eric Moore547f9a22006-06-27 14:42:12 -0600341mptsas_port_delete(struct mptsas_portinfo_details * port_details)
342{
343 struct mptsas_portinfo *port_info;
344 struct mptsas_phyinfo *phy_info;
345 u8 i;
346
347 if (!port_details)
348 return;
349
350 port_info = port_details->port_info;
351 phy_info = port_info->phy_info;
352
Eric Mooredc22f162006-07-06 11:23:14 -0600353 dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
Eric Mooref99be432007-01-04 20:46:54 -0700354 "bitmask=0x%016llX\n", __FUNCTION__, port_details,
355 port_details->num_phys, (unsigned long long)
356 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600357
358 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
359 if(phy_info->port_details != port_details)
360 continue;
361 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
362 phy_info->port_details = NULL;
363 }
364 kfree(port_details);
365}
366
367static inline struct sas_rphy *
368mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
369{
370 if (phy_info->port_details)
371 return phy_info->port_details->rphy;
372 else
373 return NULL;
374}
375
376static inline void
377mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
378{
379 if (phy_info->port_details) {
380 phy_info->port_details->rphy = rphy;
381 dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
382 }
383
384#ifdef MPT_DEBUG_SAS_WIDE
385 if (rphy) {
386 dev_printk(KERN_DEBUG, &rphy->dev, "add:");
387 printk("rphy=%p release=%p\n",
388 rphy, rphy->dev.release);
389 }
390#endif
391}
392
393static inline struct sas_port *
394mptsas_get_port(struct mptsas_phyinfo *phy_info)
395{
396 if (phy_info->port_details)
397 return phy_info->port_details->port;
398 else
399 return NULL;
400}
401
402static inline void
403mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port)
404{
405 if (phy_info->port_details)
406 phy_info->port_details->port = port;
407
408#ifdef MPT_DEBUG_SAS_WIDE
409 if (port) {
410 dev_printk(KERN_DEBUG, &port->dev, "add: ");
411 printk("port=%p release=%p\n",
412 port, port->dev.release);
413 }
414#endif
415}
416
417static inline struct scsi_target *
418mptsas_get_starget(struct mptsas_phyinfo *phy_info)
419{
420 if (phy_info->port_details)
421 return phy_info->port_details->starget;
422 else
423 return NULL;
424}
425
426static inline void
427mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
428starget)
429{
430 if (phy_info->port_details)
431 phy_info->port_details->starget = starget;
432}
433
434
435/*
436 * mptsas_setup_wide_ports
437 *
438 * Updates for new and existing narrow/wide port configuration
439 * in the sas_topology
440 */
Eric Moore376ac832006-06-29 17:36:26 -0600441static void
Eric Moore547f9a22006-06-27 14:42:12 -0600442mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
443{
444 struct mptsas_portinfo_details * port_details;
445 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
446 u64 sas_address;
447 int i, j;
448
449 mutex_lock(&ioc->sas_topology_mutex);
450
451 phy_info = port_info->phy_info;
452 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
453 if (phy_info->attached.handle)
454 continue;
455 port_details = phy_info->port_details;
456 if (!port_details)
457 continue;
458 if (port_details->num_phys < 2)
459 continue;
460 /*
461 * Removing a phy from a port, letting the last
462 * phy be removed by firmware events.
463 */
464 dsaswideprintk((KERN_DEBUG
Eric Mooredc22f162006-07-06 11:23:14 -0600465 "%s: [%p]: deleting phy = %d\n",
466 __FUNCTION__, port_details, i));
Eric Moore547f9a22006-06-27 14:42:12 -0600467 port_details->num_phys--;
468 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
469 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
470 sas_port_delete_phy(port_details->port, phy_info->phy);
471 phy_info->port_details = NULL;
472 }
473
474 /*
475 * Populate and refresh the tree
476 */
477 phy_info = port_info->phy_info;
478 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
479 sas_address = phy_info->attached.sas_address;
480 dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
Eric Mooref99be432007-01-04 20:46:54 -0700481 i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600482 if (!sas_address)
483 continue;
484 port_details = phy_info->port_details;
485 /*
486 * Forming a port
487 */
488 if (!port_details) {
489 port_details = kzalloc(sizeof(*port_details),
490 GFP_KERNEL);
491 if (!port_details)
492 goto out;
493 port_details->num_phys = 1;
494 port_details->port_info = port_info;
Eric Moore547f9a22006-06-27 14:42:12 -0600495 if (phy_info->phy_id < 64 )
496 port_details->phy_bitmask |=
497 (1 << phy_info->phy_id);
498 phy_info->sas_port_add_phy=1;
499 dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
Eric Mooref99be432007-01-04 20:46:54 -0700500 "phy_id=%d sas_address=0x%018llX\n",
501 i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600502 phy_info->port_details = port_details;
503 }
504
505 if (i == port_info->num_phys - 1)
506 continue;
507 phy_info_cmp = &port_info->phy_info[i + 1];
508 for (j = i + 1 ; j < port_info->num_phys ; j++,
509 phy_info_cmp++) {
510 if (!phy_info_cmp->attached.sas_address)
511 continue;
512 if (sas_address != phy_info_cmp->attached.sas_address)
513 continue;
514 if (phy_info_cmp->port_details == port_details )
515 continue;
516 dsaswideprintk((KERN_DEBUG
Eric Mooref99be432007-01-04 20:46:54 -0700517 "\t\tphy_id=%d sas_address=0x%018llX\n",
518 j, (unsigned long long)
519 phy_info_cmp->attached.sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600520 if (phy_info_cmp->port_details) {
521 port_details->rphy =
522 mptsas_get_rphy(phy_info_cmp);
523 port_details->port =
524 mptsas_get_port(phy_info_cmp);
525 port_details->starget =
526 mptsas_get_starget(phy_info_cmp);
Eric Moore547f9a22006-06-27 14:42:12 -0600527 port_details->num_phys =
528 phy_info_cmp->port_details->num_phys;
Eric Moore547f9a22006-06-27 14:42:12 -0600529 if (!phy_info_cmp->port_details->num_phys)
530 kfree(phy_info_cmp->port_details);
531 } else
532 phy_info_cmp->sas_port_add_phy=1;
533 /*
534 * Adding a phy to a port
535 */
536 phy_info_cmp->port_details = port_details;
537 if (phy_info_cmp->phy_id < 64 )
538 port_details->phy_bitmask |=
539 (1 << phy_info_cmp->phy_id);
540 port_details->num_phys++;
541 }
542 }
543
544 out:
545
546#ifdef MPT_DEBUG_SAS_WIDE
547 for (i = 0; i < port_info->num_phys; i++) {
548 port_details = port_info->phy_info[i].port_details;
549 if (!port_details)
550 continue;
551 dsaswideprintk((KERN_DEBUG
Eric Mooref99be432007-01-04 20:46:54 -0700552 "%s: [%p]: phy_id=%02d num_phys=%02d "
553 "bitmask=0x%016llX\n", __FUNCTION__,
554 port_details, i, port_details->num_phys,
555 (unsigned long long)port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600556 dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
557 port_details->port, port_details->rphy));
558 }
559 dsaswideprintk((KERN_DEBUG"\n"));
560#endif
561 mutex_unlock(&ioc->sas_topology_mutex);
562}
563
564static void
565mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
566{
567 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
568
569 if (mptscsih_TMHandler(hd,
570 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
571 vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) {
572 hd->tmPending = 0;
573 hd->tmState = TM_STATE_NONE;
574 printk(MYIOC_s_WARN_FMT
575 "Error processing TaskMgmt id=%d TARGET_RESET\n",
576 ioc->name, vtarget->target_id);
577 }
578}
579
Christoph Hellwige3094442006-02-16 13:25:36 +0100580static int
Moore, Eric52435432006-03-14 09:14:15 -0700581mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
Christoph Hellwige3094442006-02-16 13:25:36 +0100582 u32 form, u32 form_specific)
583{
584 ConfigExtendedPageHeader_t hdr;
585 CONFIGPARMS cfg;
586 SasEnclosurePage0_t *buffer;
587 dma_addr_t dma_handle;
588 int error;
589 __le64 le_identifier;
590
591 memset(&hdr, 0, sizeof(hdr));
592 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
593 hdr.PageNumber = 0;
594 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
595 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
596
597 cfg.cfghdr.ehdr = &hdr;
598 cfg.physAddr = -1;
599 cfg.pageAddr = form + form_specific;
600 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
601 cfg.dir = 0; /* read */
602 cfg.timeout = 10;
603
604 error = mpt_config(ioc, &cfg);
605 if (error)
606 goto out;
607 if (!hdr.ExtPageLength) {
608 error = -ENXIO;
609 goto out;
610 }
611
612 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
613 &dma_handle);
614 if (!buffer) {
615 error = -ENOMEM;
616 goto out;
617 }
618
619 cfg.physAddr = dma_handle;
620 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
621
622 error = mpt_config(ioc, &cfg);
623 if (error)
624 goto out_free_consistent;
625
626 /* save config data */
627 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
628 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
629 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
630 enclosure->flags = le16_to_cpu(buffer->Flags);
631 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
632 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
633 enclosure->start_id = buffer->StartTargetID;
634 enclosure->start_channel = buffer->StartBus;
635 enclosure->sep_id = buffer->SEPTargetID;
636 enclosure->sep_channel = buffer->SEPBus;
637
638 out_free_consistent:
639 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
640 buffer, dma_handle);
641 out:
642 return error;
643}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200644
James Bottomleyf013db32006-03-18 14:54:36 -0600645static int
646mptsas_slave_configure(struct scsi_device *sdev)
647{
Moore, Eric3c0c25b2006-04-13 16:08:17 -0600648
James Bottomleye8bf3942006-07-11 17:49:34 -0400649 if (sdev->channel == MPTSAS_RAID_CHANNEL)
650 goto out;
James Bottomleyf013db32006-03-18 14:54:36 -0600651
James Bottomleye8bf3942006-07-11 17:49:34 -0400652 sas_read_port_mode_page(sdev);
653
654 out:
James Bottomleyf013db32006-03-18 14:54:36 -0600655 return mptscsih_slave_configure(sdev);
656}
657
Eric Moore547f9a22006-06-27 14:42:12 -0600658static int
659mptsas_target_alloc(struct scsi_target *starget)
660{
661 struct Scsi_Host *host = dev_to_shost(&starget->dev);
662 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
663 VirtTarget *vtarget;
664 u32 target_id;
665 u32 channel;
666 struct sas_rphy *rphy;
667 struct mptsas_portinfo *p;
668 int i;
669
670 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
671 if (!vtarget)
672 return -ENOMEM;
673
674 vtarget->starget = starget;
675 vtarget->ioc_id = hd->ioc->id;
676 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
677
678 target_id = starget->id;
679 channel = 0;
680
681 hd->Targets[target_id] = vtarget;
682
James Bottomleye8bf3942006-07-11 17:49:34 -0400683 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -0600684 goto out;
685
686 rphy = dev_to_rphy(starget->dev.parent);
687 mutex_lock(&hd->ioc->sas_topology_mutex);
688 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
689 for (i = 0; i < p->num_phys; i++) {
690 if (p->phy_info[i].attached.sas_address !=
691 rphy->identify.sas_address)
692 continue;
693 target_id = p->phy_info[i].attached.id;
694 channel = p->phy_info[i].attached.channel;
695 mptsas_set_starget(&p->phy_info[i], starget);
696
697 /*
698 * Exposing hidden raid components
699 */
700 if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
701 target_id = mptscsih_raid_id_to_num(hd,
702 target_id);
703 vtarget->tflags |=
704 MPT_TARGET_FLAGS_RAID_COMPONENT;
705 }
706 mutex_unlock(&hd->ioc->sas_topology_mutex);
707 goto out;
708 }
709 }
710 mutex_unlock(&hd->ioc->sas_topology_mutex);
711
712 kfree(vtarget);
713 return -ENXIO;
714
715 out:
716 vtarget->target_id = target_id;
717 vtarget->bus_id = channel;
718 starget->hostdata = vtarget;
719 return 0;
720}
721
722static void
723mptsas_target_destroy(struct scsi_target *starget)
724{
725 struct Scsi_Host *host = dev_to_shost(&starget->dev);
726 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
727 struct sas_rphy *rphy;
728 struct mptsas_portinfo *p;
729 int i;
730
731 if (!starget->hostdata)
732 return;
733
James Bottomleye8bf3942006-07-11 17:49:34 -0400734 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -0600735 goto out;
736
737 rphy = dev_to_rphy(starget->dev.parent);
738 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
739 for (i = 0; i < p->num_phys; i++) {
740 if (p->phy_info[i].attached.sas_address !=
741 rphy->identify.sas_address)
742 continue;
743 mptsas_set_starget(&p->phy_info[i], NULL);
744 goto out;
745 }
746 }
747
748 out:
749 kfree(starget->hostdata);
750 starget->hostdata = NULL;
751}
752
753
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200754static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700755mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200756{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700757 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200758 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
759 struct sas_rphy *rphy;
760 struct mptsas_portinfo *p;
761 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700762 struct scsi_target *starget;
Eric Moore547f9a22006-06-27 14:42:12 -0600763 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200764
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100765 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200766 if (!vdev) {
Eric Moore547f9a22006-06-27 14:42:12 -0600767 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200768 hd->ioc->name, sizeof(VirtDevice));
769 return -ENOMEM;
770 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700771 starget = scsi_target(sdev);
Eric Moore547f9a22006-06-27 14:42:12 -0600772 vdev->vtarget = starget->hostdata;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200773
James Bottomleye8bf3942006-07-11 17:49:34 -0400774 if (sdev->channel == MPTSAS_RAID_CHANNEL)
Moore, Eric816aa902006-01-13 16:25:20 -0700775 goto out;
Moore, Eric816aa902006-01-13 16:25:20 -0700776
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700777 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100778 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200779 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
780 for (i = 0; i < p->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -0600781 if (p->phy_info[i].attached.sas_address !=
782 rphy->identify.sas_address)
783 continue;
784 vdev->lun = sdev->lun;
785 /*
786 * Exposing hidden raid components
787 */
788 if (mptscsih_is_phys_disk(hd->ioc,
789 p->phy_info[i].attached.id))
790 sdev->no_uld_attach = 1;
791 mutex_unlock(&hd->ioc->sas_topology_mutex);
792 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200793 }
794 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100795 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200796
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200797 kfree(vdev);
Christoph Hellwig23f236e2006-01-30 19:00:43 +0100798 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200799
800 out:
Eric Moore547f9a22006-06-27 14:42:12 -0600801 vdev->vtarget->num_luns++;
802 sdev->hostdata = vdev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200803 return 0;
804}
805
Eric Moore547f9a22006-06-27 14:42:12 -0600806static int
807mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100808{
Eric Moore547f9a22006-06-27 14:42:12 -0600809 VirtDevice *vdev = SCpnt->device->hostdata;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100810
Eric Moore547f9a22006-06-27 14:42:12 -0600811// scsi_print_command(SCpnt);
812 if (vdev->vtarget->deleted) {
813 SCpnt->result = DID_NO_CONNECT << 16;
814 done(SCpnt);
815 return 0;
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700816 }
Eric Moore547f9a22006-06-27 14:42:12 -0600817
818 return mptscsih_qcmd(SCpnt,done);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100819}
820
Eric Moore547f9a22006-06-27 14:42:12 -0600821
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200822static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700823 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200824 .proc_name = "mptsas",
825 .proc_info = mptscsih_proc_info,
826 .name = "MPT SPI Host",
827 .info = mptscsih_info,
Eric Moore547f9a22006-06-27 14:42:12 -0600828 .queuecommand = mptsas_qcmd,
829 .target_alloc = mptsas_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200830 .slave_alloc = mptsas_slave_alloc,
James Bottomleyf013db32006-03-18 14:54:36 -0600831 .slave_configure = mptsas_slave_configure,
Eric Moore547f9a22006-06-27 14:42:12 -0600832 .target_destroy = mptsas_target_destroy,
833 .slave_destroy = mptscsih_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200834 .change_queue_depth = mptscsih_change_queue_depth,
835 .eh_abort_handler = mptscsih_abort,
836 .eh_device_reset_handler = mptscsih_dev_reset,
837 .eh_bus_reset_handler = mptscsih_bus_reset,
838 .eh_host_reset_handler = mptscsih_host_reset,
839 .bios_param = mptscsih_bios_param,
840 .can_queue = MPT_FC_CAN_QUEUE,
841 .this_id = -1,
842 .sg_tablesize = MPT_SCSI_SG_DEPTH,
843 .max_sectors = 8192,
844 .cmd_per_lun = 7,
845 .use_clustering = ENABLE_CLUSTERING,
846};
847
Christoph Hellwigb5141122005-10-28 22:07:41 +0200848static int mptsas_get_linkerrors(struct sas_phy *phy)
849{
850 MPT_ADAPTER *ioc = phy_to_ioc(phy);
851 ConfigExtendedPageHeader_t hdr;
852 CONFIGPARMS cfg;
853 SasPhyPage1_t *buffer;
854 dma_addr_t dma_handle;
855 int error;
856
James Bottomleyf4ad7b52006-08-25 13:48:18 -0500857 /* FIXME: only have link errors on local phys */
858 if (!scsi_is_sas_phy_local(phy))
859 return -EINVAL;
860
Christoph Hellwigb5141122005-10-28 22:07:41 +0200861 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
James Bottomleyf4ad7b52006-08-25 13:48:18 -0500933 /* FIXME: fusion doesn't allow non-local phy reset */
934 if (!scsi_is_sas_phy_local(phy))
935 return -EINVAL;
936
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200937 /* not implemented for expanders */
938 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
939 return -ENXIO;
940
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100941 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200942 goto out;
943
944 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
945 if (!mf) {
946 error = -ENOMEM;
947 goto out_unlock;
948 }
949
950 hdr = (MPIHeader_t *) mf;
951 req = (SasIoUnitControlRequest_t *)mf;
952 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
953 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
954 req->MsgContext = hdr->MsgContext;
955 req->Operation = hard_reset ?
956 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
957 req->PhyNum = phy->identify.phy_identifier;
958
959 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
960
961 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
962 10 * HZ);
963 if (!timeleft) {
964 /* On timeout reset the board */
965 mpt_free_msg_frame(ioc, mf);
966 mpt_HardResetHandler(ioc, CAN_SLEEP);
967 error = -ETIMEDOUT;
968 goto out_unlock;
969 }
970
971 /* a reply frame is expected */
972 if ((ioc->sas_mgmt.status &
973 MPT_IOCTL_STATUS_RF_VALID) == 0) {
974 error = -ENXIO;
975 goto out_unlock;
976 }
977
978 /* process the completed Reply Message Frame */
979 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
980 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
981 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
982 __FUNCTION__,
983 reply->IOCStatus,
984 reply->IOCLogInfo);
985 error = -ENXIO;
986 goto out_unlock;
987 }
988
989 error = 0;
990
991 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100992 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200993 out:
994 return error;
995}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200996
Christoph Hellwige3094442006-02-16 13:25:36 +0100997static int
998mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
999{
1000 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1001 int i, error;
1002 struct mptsas_portinfo *p;
1003 struct mptsas_enclosure enclosure_info;
1004 u64 enclosure_handle;
1005
1006 mutex_lock(&ioc->sas_topology_mutex);
1007 list_for_each_entry(p, &ioc->sas_topology, list) {
1008 for (i = 0; i < p->num_phys; i++) {
1009 if (p->phy_info[i].attached.sas_address ==
1010 rphy->identify.sas_address) {
1011 enclosure_handle = p->phy_info[i].
1012 attached.handle_enclosure;
1013 goto found_info;
1014 }
1015 }
1016 }
1017 mutex_unlock(&ioc->sas_topology_mutex);
1018 return -ENXIO;
1019
1020 found_info:
1021 mutex_unlock(&ioc->sas_topology_mutex);
1022 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -07001023 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +01001024 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1025 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1026 if (!error)
1027 *identifier = enclosure_info.enclosure_logical_id;
1028 return error;
1029}
1030
1031static int
1032mptsas_get_bay_identifier(struct sas_rphy *rphy)
1033{
1034 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1035 struct mptsas_portinfo *p;
1036 int i, rc;
1037
1038 mutex_lock(&ioc->sas_topology_mutex);
1039 list_for_each_entry(p, &ioc->sas_topology, list) {
1040 for (i = 0; i < p->num_phys; i++) {
1041 if (p->phy_info[i].attached.sas_address ==
1042 rphy->identify.sas_address) {
1043 rc = p->phy_info[i].attached.slot;
1044 goto out;
1045 }
1046 }
1047 }
1048 rc = -ENXIO;
1049 out:
1050 mutex_unlock(&ioc->sas_topology_mutex);
1051 return rc;
1052}
1053
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001054static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +02001055 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +01001056 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1057 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001058 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001059};
1060
1061static struct scsi_transport_template *mptsas_transport_template;
1062
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001063static int
1064mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1065{
1066 ConfigExtendedPageHeader_t hdr;
1067 CONFIGPARMS cfg;
1068 SasIOUnitPage0_t *buffer;
1069 dma_addr_t dma_handle;
1070 int error, i;
1071
1072 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1073 hdr.ExtPageLength = 0;
1074 hdr.PageNumber = 0;
1075 hdr.Reserved1 = 0;
1076 hdr.Reserved2 = 0;
1077 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1078 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1079
1080 cfg.cfghdr.ehdr = &hdr;
1081 cfg.physAddr = -1;
1082 cfg.pageAddr = 0;
1083 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1084 cfg.dir = 0; /* read */
1085 cfg.timeout = 10;
1086
1087 error = mpt_config(ioc, &cfg);
1088 if (error)
1089 goto out;
1090 if (!hdr.ExtPageLength) {
1091 error = -ENXIO;
1092 goto out;
1093 }
1094
1095 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1096 &dma_handle);
1097 if (!buffer) {
1098 error = -ENOMEM;
1099 goto out;
1100 }
1101
1102 cfg.physAddr = dma_handle;
1103 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1104
1105 error = mpt_config(ioc, &cfg);
1106 if (error)
1107 goto out_free_consistent;
1108
1109 port_info->num_phys = buffer->NumPhys;
1110 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001111 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001112 if (!port_info->phy_info) {
1113 error = -ENOMEM;
1114 goto out_free_consistent;
1115 }
1116
Moore, Ericdb9c9172006-03-14 09:14:18 -07001117 if (port_info->num_phys)
1118 port_info->handle =
1119 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001120 for (i = 0; i < port_info->num_phys; i++) {
1121 mptsas_print_phy_data(&buffer->PhyData[i]);
1122 port_info->phy_info[i].phy_id = i;
1123 port_info->phy_info[i].port_id =
1124 buffer->PhyData[i].Port;
1125 port_info->phy_info[i].negotiated_link_rate =
1126 buffer->PhyData[i].NegotiatedLinkRate;
Eric Moore547f9a22006-06-27 14:42:12 -06001127 port_info->phy_info[i].portinfo = port_info;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001128 }
1129
1130 out_free_consistent:
1131 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1132 buffer, dma_handle);
1133 out:
1134 return error;
1135}
1136
1137static int
1138mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1139 u32 form, u32 form_specific)
1140{
1141 ConfigExtendedPageHeader_t hdr;
1142 CONFIGPARMS cfg;
1143 SasPhyPage0_t *buffer;
1144 dma_addr_t dma_handle;
1145 int error;
1146
1147 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1148 hdr.ExtPageLength = 0;
1149 hdr.PageNumber = 0;
1150 hdr.Reserved1 = 0;
1151 hdr.Reserved2 = 0;
1152 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1153 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1154
1155 cfg.cfghdr.ehdr = &hdr;
1156 cfg.dir = 0; /* read */
1157 cfg.timeout = 10;
1158
1159 /* Get Phy Pg 0 for each Phy. */
1160 cfg.physAddr = -1;
1161 cfg.pageAddr = form + form_specific;
1162 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1163
1164 error = mpt_config(ioc, &cfg);
1165 if (error)
1166 goto out;
1167
1168 if (!hdr.ExtPageLength) {
1169 error = -ENXIO;
1170 goto out;
1171 }
1172
1173 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1174 &dma_handle);
1175 if (!buffer) {
1176 error = -ENOMEM;
1177 goto out;
1178 }
1179
1180 cfg.physAddr = dma_handle;
1181 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1182
1183 error = mpt_config(ioc, &cfg);
1184 if (error)
1185 goto out_free_consistent;
1186
1187 mptsas_print_phy_pg0(buffer);
1188
1189 phy_info->hw_link_rate = buffer->HwLinkRate;
1190 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1191 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1192 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1193
1194 out_free_consistent:
1195 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1196 buffer, dma_handle);
1197 out:
1198 return error;
1199}
1200
1201static int
1202mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1203 u32 form, u32 form_specific)
1204{
1205 ConfigExtendedPageHeader_t hdr;
1206 CONFIGPARMS cfg;
1207 SasDevicePage0_t *buffer;
1208 dma_addr_t dma_handle;
1209 __le64 sas_address;
Moore, Ericbd23e942006-04-17 12:43:04 -06001210 int error=0;
1211
1212 if (ioc->sas_discovery_runtime &&
1213 mptsas_is_end_device(device_info))
1214 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001215
1216 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1217 hdr.ExtPageLength = 0;
1218 hdr.PageNumber = 0;
1219 hdr.Reserved1 = 0;
1220 hdr.Reserved2 = 0;
1221 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1222 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1223
1224 cfg.cfghdr.ehdr = &hdr;
1225 cfg.pageAddr = form + form_specific;
1226 cfg.physAddr = -1;
1227 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1228 cfg.dir = 0; /* read */
1229 cfg.timeout = 10;
1230
Moore, Ericdb9c9172006-03-14 09:14:18 -07001231 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001232 error = mpt_config(ioc, &cfg);
1233 if (error)
1234 goto out;
1235 if (!hdr.ExtPageLength) {
1236 error = -ENXIO;
1237 goto out;
1238 }
1239
1240 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1241 &dma_handle);
1242 if (!buffer) {
1243 error = -ENOMEM;
1244 goto out;
1245 }
1246
1247 cfg.physAddr = dma_handle;
1248 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1249
1250 error = mpt_config(ioc, &cfg);
1251 if (error)
1252 goto out_free_consistent;
1253
1254 mptsas_print_device_pg0(buffer);
1255
1256 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001257 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +01001258 device_info->handle_enclosure =
1259 le16_to_cpu(buffer->EnclosureHandle);
1260 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001261 device_info->phy_id = buffer->PhyNum;
1262 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001263 device_info->id = buffer->TargetID;
1264 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001265 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1266 device_info->sas_address = le64_to_cpu(sas_address);
1267 device_info->device_info =
1268 le32_to_cpu(buffer->DeviceInfo);
1269
1270 out_free_consistent:
1271 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1272 buffer, dma_handle);
1273 out:
1274 return error;
1275}
1276
1277static int
1278mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1279 u32 form, u32 form_specific)
1280{
1281 ConfigExtendedPageHeader_t hdr;
1282 CONFIGPARMS cfg;
1283 SasExpanderPage0_t *buffer;
1284 dma_addr_t dma_handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001285 int i, error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001286
1287 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1288 hdr.ExtPageLength = 0;
1289 hdr.PageNumber = 0;
1290 hdr.Reserved1 = 0;
1291 hdr.Reserved2 = 0;
1292 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1293 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1294
1295 cfg.cfghdr.ehdr = &hdr;
1296 cfg.physAddr = -1;
1297 cfg.pageAddr = form + form_specific;
1298 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1299 cfg.dir = 0; /* read */
1300 cfg.timeout = 10;
1301
Moore, Ericdb9c9172006-03-14 09:14:18 -07001302 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001303 error = mpt_config(ioc, &cfg);
1304 if (error)
1305 goto out;
1306
1307 if (!hdr.ExtPageLength) {
1308 error = -ENXIO;
1309 goto out;
1310 }
1311
1312 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1313 &dma_handle);
1314 if (!buffer) {
1315 error = -ENOMEM;
1316 goto out;
1317 }
1318
1319 cfg.physAddr = dma_handle;
1320 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1321
1322 error = mpt_config(ioc, &cfg);
1323 if (error)
1324 goto out_free_consistent;
1325
1326 /* save config data */
1327 port_info->num_phys = buffer->NumPhys;
1328 port_info->handle = le16_to_cpu(buffer->DevHandle);
1329 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001330 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001331 if (!port_info->phy_info) {
1332 error = -ENOMEM;
1333 goto out_free_consistent;
1334 }
1335
Eric Moore547f9a22006-06-27 14:42:12 -06001336 for (i = 0; i < port_info->num_phys; i++)
1337 port_info->phy_info[i].portinfo = port_info;
1338
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001339 out_free_consistent:
1340 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1341 buffer, dma_handle);
1342 out:
1343 return error;
1344}
1345
1346static int
1347mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1348 u32 form, u32 form_specific)
1349{
1350 ConfigExtendedPageHeader_t hdr;
1351 CONFIGPARMS cfg;
1352 SasExpanderPage1_t *buffer;
1353 dma_addr_t dma_handle;
Moore, Ericbd23e942006-04-17 12:43:04 -06001354 int error=0;
1355
1356 if (ioc->sas_discovery_runtime &&
1357 mptsas_is_end_device(&phy_info->attached))
1358 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001359
1360 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1361 hdr.ExtPageLength = 0;
1362 hdr.PageNumber = 1;
1363 hdr.Reserved1 = 0;
1364 hdr.Reserved2 = 0;
1365 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1366 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1367
1368 cfg.cfghdr.ehdr = &hdr;
1369 cfg.physAddr = -1;
1370 cfg.pageAddr = form + form_specific;
1371 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1372 cfg.dir = 0; /* read */
1373 cfg.timeout = 10;
1374
1375 error = mpt_config(ioc, &cfg);
1376 if (error)
1377 goto out;
1378
1379 if (!hdr.ExtPageLength) {
1380 error = -ENXIO;
1381 goto out;
1382 }
1383
1384 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1385 &dma_handle);
1386 if (!buffer) {
1387 error = -ENOMEM;
1388 goto out;
1389 }
1390
1391 cfg.physAddr = dma_handle;
1392 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1393
1394 error = mpt_config(ioc, &cfg);
1395 if (error)
1396 goto out_free_consistent;
1397
1398
1399 mptsas_print_expander_pg1(buffer);
1400
1401 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001402 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001403 phy_info->port_id = buffer->PhysicalPort;
1404 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1405 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1406 phy_info->hw_link_rate = buffer->HwLinkRate;
1407 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1408 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1409
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001410 out_free_consistent:
1411 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1412 buffer, dma_handle);
1413 out:
1414 return error;
1415}
1416
1417static void
1418mptsas_parse_device_info(struct sas_identify *identify,
1419 struct mptsas_devinfo *device_info)
1420{
1421 u16 protocols;
1422
1423 identify->sas_address = device_info->sas_address;
1424 identify->phy_identifier = device_info->phy_id;
1425
1426 /*
1427 * Fill in Phy Initiator Port Protocol.
1428 * Bits 6:3, more than one bit can be set, fall through cases.
1429 */
1430 protocols = device_info->device_info & 0x78;
1431 identify->initiator_port_protocols = 0;
1432 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1433 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1434 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1435 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1436 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1437 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1438 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1439 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1440
1441 /*
1442 * Fill in Phy Target Port Protocol.
1443 * Bits 10:7, more than one bit can be set, fall through cases.
1444 */
1445 protocols = device_info->device_info & 0x780;
1446 identify->target_port_protocols = 0;
1447 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1448 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1449 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1450 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1451 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1452 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1453 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1454 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1455
1456 /*
1457 * Fill in Attached device type.
1458 */
1459 switch (device_info->device_info &
1460 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1461 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1462 identify->device_type = SAS_PHY_UNUSED;
1463 break;
1464 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1465 identify->device_type = SAS_END_DEVICE;
1466 break;
1467 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1468 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1469 break;
1470 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1471 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1472 break;
1473 }
1474}
1475
1476static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001477 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001478{
Moore, Erice6b2d762006-03-14 09:14:24 -07001479 MPT_ADAPTER *ioc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001480 struct sas_phy *phy;
Eric Moore547f9a22006-06-27 14:42:12 -06001481 struct sas_port *port;
1482 int error = 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001483
Eric Moore547f9a22006-06-27 14:42:12 -06001484 if (!dev) {
1485 error = -ENODEV;
1486 goto out;
1487 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001488
1489 if (!phy_info->phy) {
1490 phy = sas_phy_alloc(dev, index);
Eric Moore547f9a22006-06-27 14:42:12 -06001491 if (!phy) {
1492 error = -ENOMEM;
1493 goto out;
1494 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001495 } else
1496 phy = phy_info->phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001497
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001498 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001499
1500 /*
1501 * Set Negotiated link rate.
1502 */
1503 switch (phy_info->negotiated_link_rate) {
1504 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001505 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001506 break;
1507 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001508 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001509 break;
1510 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001511 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001512 break;
1513 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001514 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001515 break;
1516 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1517 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1518 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001519 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001520 break;
1521 }
1522
1523 /*
1524 * Set Max hardware link rate.
1525 */
1526 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1527 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001528 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001529 break;
1530 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001531 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001532 break;
1533 default:
1534 break;
1535 }
1536
1537 /*
1538 * Set Max programmed link rate.
1539 */
1540 switch (phy_info->programmed_link_rate &
1541 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1542 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001543 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001544 break;
1545 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001546 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001547 break;
1548 default:
1549 break;
1550 }
1551
1552 /*
1553 * Set Min hardware link rate.
1554 */
1555 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1556 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001557 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001558 break;
1559 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001560 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001561 break;
1562 default:
1563 break;
1564 }
1565
1566 /*
1567 * Set Min programmed link rate.
1568 */
1569 switch (phy_info->programmed_link_rate &
1570 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1571 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001572 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001573 break;
1574 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001575 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001576 break;
1577 default:
1578 break;
1579 }
1580
Moore, Erice6b2d762006-03-14 09:14:24 -07001581 if (!phy_info->phy) {
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001582
Moore, Erice6b2d762006-03-14 09:14:24 -07001583 error = sas_phy_add(phy);
1584 if (error) {
1585 sas_phy_free(phy);
Eric Moore547f9a22006-06-27 14:42:12 -06001586 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001587 }
1588 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001589 }
1590
Eric Moore547f9a22006-06-27 14:42:12 -06001591 if (!phy_info->attached.handle ||
1592 !phy_info->port_details)
1593 goto out;
1594
1595 port = mptsas_get_port(phy_info);
1596 ioc = phy_to_ioc(phy_info->phy);
1597
1598 if (phy_info->sas_port_add_phy) {
1599
1600 if (!port) {
Eric Mooredc22f162006-07-06 11:23:14 -06001601 port = sas_port_alloc_num(dev);
Eric Moore547f9a22006-06-27 14:42:12 -06001602 if (!port) {
1603 error = -ENOMEM;
1604 goto out;
1605 }
1606 error = sas_port_add(port);
1607 if (error) {
1608 dfailprintk((MYIOC_s_ERR_FMT
1609 "%s: exit at line=%d\n", ioc->name,
1610 __FUNCTION__, __LINE__));
1611 goto out;
1612 }
1613 mptsas_set_port(phy_info, port);
Eric Mooredc22f162006-07-06 11:23:14 -06001614 dsaswideprintk((KERN_DEBUG
1615 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
1616 port, dev, port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06001617 }
1618 dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
1619 phy_info->phy_id));
1620 sas_port_add_phy(port, phy_info->phy);
1621 phy_info->sas_port_add_phy = 0;
1622 }
1623
1624 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
Moore, Erice6b2d762006-03-14 09:14:24 -07001625
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001626 struct sas_rphy *rphy;
James Bottomley2686de22006-06-30 12:54:02 -05001627 struct device *parent;
James Bottomleyf013db32006-03-18 14:54:36 -06001628 struct sas_identify identify;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001629
James Bottomley2686de22006-06-30 12:54:02 -05001630 parent = dev->parent->parent;
Moore, Erice6b2d762006-03-14 09:14:24 -07001631 /*
1632 * Let the hotplug_work thread handle processing
1633 * the adding/removing of devices that occur
1634 * after start of day.
1635 */
1636 if (ioc->sas_discovery_runtime &&
1637 mptsas_is_end_device(&phy_info->attached))
Eric Moore547f9a22006-06-27 14:42:12 -06001638 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001639
James Bottomleyf013db32006-03-18 14:54:36 -06001640 mptsas_parse_device_info(&identify, &phy_info->attached);
James Bottomley2686de22006-06-30 12:54:02 -05001641 if (scsi_is_host_device(parent)) {
1642 struct mptsas_portinfo *port_info;
1643 int i;
1644
1645 mutex_lock(&ioc->sas_topology_mutex);
1646 port_info = mptsas_find_portinfo_by_handle(ioc,
1647 ioc->handle);
1648 mutex_unlock(&ioc->sas_topology_mutex);
1649
1650 for (i = 0; i < port_info->num_phys; i++)
1651 if (port_info->phy_info[i].identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001652 identify.sas_address) {
1653 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001654 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001655 }
James Bottomley2686de22006-06-30 12:54:02 -05001656
1657 } else if (scsi_is_sas_rphy(parent)) {
1658 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
1659 if (identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001660 parent_rphy->identify.sas_address) {
1661 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001662 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001663 }
James Bottomley2686de22006-06-30 12:54:02 -05001664 }
1665
James Bottomleyf013db32006-03-18 14:54:36 -06001666 switch (identify.device_type) {
1667 case SAS_END_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001668 rphy = sas_end_device_alloc(port);
James Bottomleyf013db32006-03-18 14:54:36 -06001669 break;
1670 case SAS_EDGE_EXPANDER_DEVICE:
1671 case SAS_FANOUT_EXPANDER_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001672 rphy = sas_expander_alloc(port, identify.device_type);
James Bottomleyf013db32006-03-18 14:54:36 -06001673 break;
1674 default:
1675 rphy = NULL;
1676 break;
1677 }
Eric Moore547f9a22006-06-27 14:42:12 -06001678 if (!rphy) {
1679 dfailprintk((MYIOC_s_ERR_FMT
1680 "%s: exit at line=%d\n", ioc->name,
1681 __FUNCTION__, __LINE__));
1682 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001683 }
1684
Eric Moore547f9a22006-06-27 14:42:12 -06001685 rphy->identify = identify;
1686 error = sas_rphy_add(rphy);
1687 if (error) {
1688 dfailprintk((MYIOC_s_ERR_FMT
1689 "%s: exit at line=%d\n", ioc->name,
1690 __FUNCTION__, __LINE__));
1691 sas_rphy_free(rphy);
1692 goto out;
1693 }
1694 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001695 }
1696
Eric Moore547f9a22006-06-27 14:42:12 -06001697 out:
1698 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001699}
1700
1701static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001702mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001703{
Moore, Erice6b2d762006-03-14 09:14:24 -07001704 struct mptsas_portinfo *port_info, *hba;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001705 u32 handle = 0xFFFF;
1706 int error = -ENOMEM, i;
1707
Moore, Erice6b2d762006-03-14 09:14:24 -07001708 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
1709 if (! hba)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001710 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001711
Moore, Erice6b2d762006-03-14 09:14:24 -07001712 error = mptsas_sas_io_unit_pg0(ioc, hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001713 if (error)
1714 goto out_free_port_info;
1715
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001716 mutex_lock(&ioc->sas_topology_mutex);
James Bottomley2686de22006-06-30 12:54:02 -05001717 ioc->handle = hba->handle;
Moore, Erice6b2d762006-03-14 09:14:24 -07001718 port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
1719 if (!port_info) {
1720 port_info = hba;
1721 list_add_tail(&port_info->list, &ioc->sas_topology);
1722 } else {
1723 port_info->handle = hba->handle;
1724 for (i = 0; i < hba->num_phys; i++)
1725 port_info->phy_info[i].negotiated_link_rate =
1726 hba->phy_info[i].negotiated_link_rate;
Eric Moore547f9a22006-06-27 14:42:12 -06001727 kfree(hba->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001728 kfree(hba);
1729 hba = NULL;
1730 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001731 mutex_unlock(&ioc->sas_topology_mutex);
1732
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001733 for (i = 0; i < port_info->num_phys; i++) {
1734 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1735 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1736 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1737
1738 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1739 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1740 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001741 port_info->phy_info[i].identify.phy_id =
1742 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001743 handle = port_info->phy_info[i].identify.handle;
1744
Eric Moore547f9a22006-06-27 14:42:12 -06001745 if (port_info->phy_info[i].attached.handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001746 mptsas_sas_device_pg0(ioc,
1747 &port_info->phy_info[i].attached,
1748 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1749 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1750 port_info->phy_info[i].attached.handle);
Eric Moore547f9a22006-06-27 14:42:12 -06001751 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001752
Eric Moore547f9a22006-06-27 14:42:12 -06001753 mptsas_setup_wide_ports(ioc, port_info);
1754
1755 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001756 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Moore, Erice6b2d762006-03-14 09:14:24 -07001757 &port_info->phy_info[i], ioc->sas_index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001758
1759 return 0;
1760
1761 out_free_port_info:
Eric Moore547f9a22006-06-27 14:42:12 -06001762 kfree(hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001763 out:
1764 return error;
1765}
1766
1767static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001768mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001769{
Moore, Erice6b2d762006-03-14 09:14:24 -07001770 struct mptsas_portinfo *port_info, *p, *ex;
Eric Moore547f9a22006-06-27 14:42:12 -06001771 struct device *parent;
1772 struct sas_rphy *rphy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001773 int error = -ENOMEM, i, j;
1774
Moore, Erice6b2d762006-03-14 09:14:24 -07001775 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
1776 if (!ex)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001777 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001778
Moore, Erice6b2d762006-03-14 09:14:24 -07001779 error = mptsas_sas_expander_pg0(ioc, ex,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001780 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1781 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1782 if (error)
1783 goto out_free_port_info;
1784
Moore, Erice6b2d762006-03-14 09:14:24 -07001785 *handle = ex->handle;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001786
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001787 mutex_lock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07001788 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
1789 if (!port_info) {
1790 port_info = ex;
1791 list_add_tail(&port_info->list, &ioc->sas_topology);
1792 } else {
1793 port_info->handle = ex->handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001794 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001795 kfree(ex);
1796 ex = NULL;
1797 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001798 mutex_unlock(&ioc->sas_topology_mutex);
1799
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001800 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001801 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1802 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1803 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1804
1805 if (port_info->phy_info[i].identify.handle) {
1806 mptsas_sas_device_pg0(ioc,
1807 &port_info->phy_info[i].identify,
1808 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1809 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1810 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001811 port_info->phy_info[i].identify.phy_id =
1812 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001813 }
1814
1815 if (port_info->phy_info[i].attached.handle) {
1816 mptsas_sas_device_pg0(ioc,
1817 &port_info->phy_info[i].attached,
1818 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1819 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1820 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07001821 port_info->phy_info[i].attached.phy_id =
1822 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001823 }
Eric Moore547f9a22006-06-27 14:42:12 -06001824 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001825
Eric Moore547f9a22006-06-27 14:42:12 -06001826 parent = &ioc->sh->shost_gendev;
1827 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001828 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001829 list_for_each_entry(p, &ioc->sas_topology, list) {
1830 for (j = 0; j < p->num_phys; j++) {
Eric Moore547f9a22006-06-27 14:42:12 -06001831 if (port_info->phy_info[i].identify.handle !=
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001832 p->phy_info[j].attached.handle)
Eric Moore547f9a22006-06-27 14:42:12 -06001833 continue;
1834 rphy = mptsas_get_rphy(&p->phy_info[j]);
1835 parent = &rphy->dev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001836 }
1837 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001838 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06001839 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001840
Eric Moore547f9a22006-06-27 14:42:12 -06001841 mptsas_setup_wide_ports(ioc, port_info);
1842
1843 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001844 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
Moore, Erice6b2d762006-03-14 09:14:24 -07001845 ioc->sas_index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001846
1847 return 0;
1848
1849 out_free_port_info:
Moore, Erice6b2d762006-03-14 09:14:24 -07001850 if (ex) {
Eric Moore547f9a22006-06-27 14:42:12 -06001851 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001852 kfree(ex);
1853 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001854 out:
1855 return error;
1856}
1857
Moore, Erice6b2d762006-03-14 09:14:24 -07001858/*
1859 * mptsas_delete_expander_phys
1860 *
1861 *
1862 * This will traverse topology, and remove expanders
1863 * that are no longer present
1864 */
1865static void
1866mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1867{
1868 struct mptsas_portinfo buffer;
1869 struct mptsas_portinfo *port_info, *n, *parent;
Eric Moore547f9a22006-06-27 14:42:12 -06001870 struct mptsas_phyinfo *phy_info;
1871 struct scsi_target * starget;
1872 VirtTarget * vtarget;
1873 struct sas_port * port;
Moore, Erice6b2d762006-03-14 09:14:24 -07001874 int i;
Eric Moore547f9a22006-06-27 14:42:12 -06001875 u64 expander_sas_address;
Moore, Erice6b2d762006-03-14 09:14:24 -07001876
1877 mutex_lock(&ioc->sas_topology_mutex);
1878 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
1879
1880 if (port_info->phy_info &&
1881 (!(port_info->phy_info[0].identify.device_info &
1882 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
1883 continue;
1884
1885 if (mptsas_sas_expander_pg0(ioc, &buffer,
1886 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
1887 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
1888
1889 /*
Eric Moore547f9a22006-06-27 14:42:12 -06001890 * Issue target reset to all child end devices
1891 * then mark them deleted to prevent further
1892 * IO going to them.
1893 */
1894 phy_info = port_info->phy_info;
1895 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
1896 starget = mptsas_get_starget(phy_info);
1897 if (!starget)
1898 continue;
1899 vtarget = starget->hostdata;
1900 if(vtarget->deleted)
1901 continue;
1902 vtarget->deleted = 1;
1903 mptsas_target_reset(ioc, vtarget);
1904 sas_port_delete(mptsas_get_port(phy_info));
1905 mptsas_port_delete(phy_info->port_details);
1906 }
1907
1908 /*
Moore, Erice6b2d762006-03-14 09:14:24 -07001909 * Obtain the port_info instance to the parent port
1910 */
1911 parent = mptsas_find_portinfo_by_handle(ioc,
1912 port_info->phy_info[0].identify.handle_parent);
1913
1914 if (!parent)
1915 goto next_port;
1916
Eric Moore547f9a22006-06-27 14:42:12 -06001917 expander_sas_address =
1918 port_info->phy_info[0].identify.sas_address;
1919
Moore, Erice6b2d762006-03-14 09:14:24 -07001920 /*
1921 * Delete rphys in the parent that point
1922 * to this expander. The transport layer will
1923 * cleanup all the children.
1924 */
Eric Moore547f9a22006-06-27 14:42:12 -06001925 phy_info = parent->phy_info;
1926 for (i = 0; i < parent->num_phys; i++, phy_info++) {
1927 port = mptsas_get_port(phy_info);
1928 if (!port)
Moore, Erice6b2d762006-03-14 09:14:24 -07001929 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06001930 if (phy_info->attached.sas_address !=
1931 expander_sas_address)
1932 continue;
1933#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06001934 dev_printk(KERN_DEBUG, &port->dev,
1935 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06001936#endif
1937 sas_port_delete(port);
1938 mptsas_port_delete(phy_info->port_details);
Moore, Erice6b2d762006-03-14 09:14:24 -07001939 }
1940 next_port:
Eric Moore547f9a22006-06-27 14:42:12 -06001941
1942 phy_info = port_info->phy_info;
1943 for (i = 0; i < port_info->num_phys; i++, phy_info++)
1944 mptsas_port_delete(phy_info->port_details);
1945
Moore, Erice6b2d762006-03-14 09:14:24 -07001946 list_del(&port_info->list);
Eric Moore547f9a22006-06-27 14:42:12 -06001947 kfree(port_info->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001948 kfree(port_info);
1949 }
1950 /*
1951 * Free this memory allocated from inside
1952 * mptsas_sas_expander_pg0
1953 */
Eric Moore547f9a22006-06-27 14:42:12 -06001954 kfree(buffer.phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001955 }
1956 mutex_unlock(&ioc->sas_topology_mutex);
1957}
1958
1959/*
1960 * Start of day discovery
1961 */
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001962static void
1963mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1964{
1965 u32 handle = 0xFFFF;
Moore, Ericf44e5462006-03-14 09:14:21 -07001966 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001967
Moore, Erice6b2d762006-03-14 09:14:24 -07001968 mutex_lock(&ioc->sas_discovery_mutex);
1969 mptsas_probe_hba_phys(ioc);
1970 while (!mptsas_probe_expander_phys(ioc, &handle))
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001971 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07001972 /*
1973 Reporting RAID volumes.
1974 */
1975 if (!ioc->raid_data.pIocPg2)
1976 goto out;
1977 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1978 goto out;
1979 for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
James Bottomleye8bf3942006-07-11 17:49:34 -04001980 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
Moore, Ericf44e5462006-03-14 09:14:21 -07001981 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
1982 }
1983 out:
Moore, Erice6b2d762006-03-14 09:14:24 -07001984 mutex_unlock(&ioc->sas_discovery_mutex);
1985}
1986
1987/*
1988 * Work queue thread to handle Runtime discovery
1989 * Mere purpose is the hot add/delete of expanders
Eric Moore547f9a22006-06-27 14:42:12 -06001990 *(Mutex UNLOCKED)
Moore, Erice6b2d762006-03-14 09:14:24 -07001991 */
1992static void
Eric Moore547f9a22006-06-27 14:42:12 -06001993__mptsas_discovery_work(MPT_ADAPTER *ioc)
Moore, Erice6b2d762006-03-14 09:14:24 -07001994{
Moore, Erice6b2d762006-03-14 09:14:24 -07001995 u32 handle = 0xFFFF;
1996
Moore, Erice6b2d762006-03-14 09:14:24 -07001997 ioc->sas_discovery_runtime=1;
1998 mptsas_delete_expander_phys(ioc);
1999 mptsas_probe_hba_phys(ioc);
2000 while (!mptsas_probe_expander_phys(ioc, &handle))
2001 ;
Moore, Erice6b2d762006-03-14 09:14:24 -07002002 ioc->sas_discovery_runtime=0;
Eric Moore547f9a22006-06-27 14:42:12 -06002003}
2004
2005/*
2006 * Work queue thread to handle Runtime discovery
2007 * Mere purpose is the hot add/delete of expanders
2008 *(Mutex LOCKED)
2009 */
2010static void
David Howellsc4028952006-11-22 14:57:56 +00002011mptsas_discovery_work(struct work_struct *work)
Eric Moore547f9a22006-06-27 14:42:12 -06002012{
David Howellsc4028952006-11-22 14:57:56 +00002013 struct mptsas_discovery_event *ev =
2014 container_of(work, struct mptsas_discovery_event, work);
Eric Moore547f9a22006-06-27 14:42:12 -06002015 MPT_ADAPTER *ioc = ev->ioc;
2016
2017 mutex_lock(&ioc->sas_discovery_mutex);
2018 __mptsas_discovery_work(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002019 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002020 kfree(ev);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002021}
2022
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002023static struct mptsas_phyinfo *
Eric Moore547f9a22006-06-27 14:42:12 -06002024mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002025{
2026 struct mptsas_portinfo *port_info;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002027 struct mptsas_phyinfo *phy_info = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -06002028 int i;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002029
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002030 mutex_lock(&ioc->sas_topology_mutex);
2031 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2032 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002033 if (port_info->phy_info[i].attached.sas_address
2034 != sas_address)
2035 continue;
2036 if (!mptsas_is_end_device(
2037 &port_info->phy_info[i].attached))
2038 continue;
2039 phy_info = &port_info->phy_info[i];
2040 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002041 }
2042 }
2043 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002044 return phy_info;
2045}
2046
2047static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07002048mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002049{
2050 struct mptsas_portinfo *port_info;
2051 struct mptsas_phyinfo *phy_info = NULL;
2052 int i;
2053
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002054 mutex_lock(&ioc->sas_topology_mutex);
2055 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -06002056 for (i = 0; i < port_info->num_phys; i++) {
2057 if (port_info->phy_info[i].attached.id != id)
2058 continue;
2059 if (!mptsas_is_end_device(
2060 &port_info->phy_info[i].attached))
2061 continue;
2062 phy_info = &port_info->phy_info[i];
2063 break;
2064 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002065 }
2066 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002067 return phy_info;
2068}
2069
Moore, Eric4b766472006-03-14 09:14:12 -07002070/*
2071 * Work queue thread to clear the persitency table
2072 */
2073static void
David Howellsc4028952006-11-22 14:57:56 +00002074mptsas_persist_clear_table(struct work_struct *work)
Moore, Eric4b766472006-03-14 09:14:12 -07002075{
David Howellsc4028952006-11-22 14:57:56 +00002076 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002077
2078 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2079}
2080
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002081static void
Moore, Ericf44e5462006-03-14 09:14:21 -07002082mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2083{
Eric Mooref99be432007-01-04 20:46:54 -07002084 int rc;
2085
Moore, Ericf44e5462006-03-14 09:14:21 -07002086 sdev->no_uld_attach = data ? 1 : 0;
Eric Mooref99be432007-01-04 20:46:54 -07002087 rc = scsi_device_reprobe(sdev);
Moore, Ericf44e5462006-03-14 09:14:21 -07002088}
2089
2090static void
2091mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2092{
2093 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2094 mptsas_reprobe_lun);
2095}
2096
Moore, Erice6b2d762006-03-14 09:14:24 -07002097/*
2098 * Work queue thread to handle SAS hotplug events
2099 */
Moore, Ericf44e5462006-03-14 09:14:21 -07002100static void
David Howellsc4028952006-11-22 14:57:56 +00002101mptsas_hotplug_work(struct work_struct *work)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002102{
David Howellsc4028952006-11-22 14:57:56 +00002103 struct mptsas_hotplug_event *ev =
2104 container_of(work, struct mptsas_hotplug_event, work);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002105 MPT_ADAPTER *ioc = ev->ioc;
2106 struct mptsas_phyinfo *phy_info;
2107 struct sas_rphy *rphy;
Eric Moore547f9a22006-06-27 14:42:12 -06002108 struct sas_port *port;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002109 struct scsi_device *sdev;
Eric Moore547f9a22006-06-27 14:42:12 -06002110 struct scsi_target * starget;
James Bottomleyf013db32006-03-18 14:54:36 -06002111 struct sas_identify identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002112 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002113 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07002114 VirtTarget *vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -06002115 VirtDevice *vdevice;
2116
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002117
Moore, Erice6b2d762006-03-14 09:14:24 -07002118 mutex_lock(&ioc->sas_discovery_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002119 switch (ev->event_type) {
2120 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002121
Moore, Ericc73787ee2006-01-26 16:20:06 -07002122 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Moore, Erice6b2d762006-03-14 09:14:24 -07002123
Moore, Ericf44e5462006-03-14 09:14:21 -07002124 /*
2125 * Sanity checks, for non-existing phys and remote rphys.
2126 */
Eric Moore547f9a22006-06-27 14:42:12 -06002127 if (!phy_info || !phy_info->port_details) {
2128 dfailprintk((MYIOC_s_ERR_FMT
2129 "%s: exit at line=%d\n", ioc->name,
2130 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002131 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002132 }
2133 rphy = mptsas_get_rphy(phy_info);
2134 if (!rphy) {
2135 dfailprintk((MYIOC_s_ERR_FMT
2136 "%s: exit at line=%d\n", ioc->name,
2137 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002138 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002139 }
2140 port = mptsas_get_port(phy_info);
2141 if (!port) {
2142 dfailprintk((MYIOC_s_ERR_FMT
2143 "%s: exit at line=%d\n", ioc->name,
2144 __FUNCTION__, __LINE__));
2145 break;
2146 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002147
Eric Moore547f9a22006-06-27 14:42:12 -06002148 starget = mptsas_get_starget(phy_info);
2149 if (starget) {
2150 vtarget = starget->hostdata;
2151
2152 if (!vtarget) {
2153 dfailprintk((MYIOC_s_ERR_FMT
2154 "%s: exit at line=%d\n", ioc->name,
2155 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002156 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002157 }
2158
Moore, Ericf44e5462006-03-14 09:14:21 -07002159 /*
2160 * Handling RAID components
2161 */
2162 if (ev->phys_disk_num_valid) {
2163 vtarget->target_id = ev->phys_disk_num;
2164 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore547f9a22006-06-27 14:42:12 -06002165 mptsas_reprobe_target(starget, 1);
Moore, Ericf44e5462006-03-14 09:14:21 -07002166 break;
2167 }
Eric Moore547f9a22006-06-27 14:42:12 -06002168
2169 vtarget->deleted = 1;
2170 mptsas_target_reset(ioc, vtarget);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002171 }
2172
Moore, Ericc73787ee2006-01-26 16:20:06 -07002173 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2174 ds = "ssp";
2175 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2176 ds = "stp";
2177 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2178 ds = "sata";
2179
2180 printk(MYIOC_s_INFO_FMT
2181 "removing %s device, channel %d, id %d, phy %d\n",
2182 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
2183
Eric Moore547f9a22006-06-27 14:42:12 -06002184#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06002185 dev_printk(KERN_DEBUG, &port->dev,
2186 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002187#endif
2188 sas_port_delete(port);
2189 mptsas_port_delete(phy_info->port_details);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002190 break;
2191 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002192
Moore, Ericbd23e942006-04-17 12:43:04 -06002193 if (ev->phys_disk_num_valid)
2194 mpt_findImVolumes(ioc);
2195
Moore, Ericc73787ee2006-01-26 16:20:06 -07002196 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01002197 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07002198 */
Christoph Hellwige3094442006-02-16 13:25:36 +01002199 if (mptsas_sas_device_pg0(ioc, &sas_device,
2200 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
Eric Moore547f9a22006-06-27 14:42:12 -06002201 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
2202 dfailprintk((MYIOC_s_ERR_FMT
2203 "%s: exit at line=%d\n", ioc->name,
2204 __FUNCTION__, __LINE__));
Christoph Hellwige3094442006-02-16 13:25:36 +01002205 break;
Moore, Erice6b2d762006-03-14 09:14:24 -07002206 }
2207
Eric Moore547f9a22006-06-27 14:42:12 -06002208 ssleep(2);
2209 __mptsas_discovery_work(ioc);
Moore, Ericf44e5462006-03-14 09:14:21 -07002210
Eric Moore547f9a22006-06-27 14:42:12 -06002211 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2212 sas_device.sas_address);
2213
2214 if (!phy_info || !phy_info->port_details) {
2215 dfailprintk((MYIOC_s_ERR_FMT
2216 "%s: exit at line=%d\n", ioc->name,
2217 __FUNCTION__, __LINE__));
2218 break;
2219 }
2220
2221 starget = mptsas_get_starget(phy_info);
2222 if (starget) {
2223 vtarget = starget->hostdata;
2224
2225 if (!vtarget) {
2226 dfailprintk((MYIOC_s_ERR_FMT
2227 "%s: exit at line=%d\n", ioc->name,
2228 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002229 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002230 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002231 /*
2232 * Handling RAID components
2233 */
2234 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
2235 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
2236 vtarget->target_id = ev->id;
Eric Moore547f9a22006-06-27 14:42:12 -06002237 mptsas_reprobe_target(starget, 0);
Moore, Ericf44e5462006-03-14 09:14:21 -07002238 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002239 break;
2240 }
2241
Eric Moore547f9a22006-06-27 14:42:12 -06002242 if (mptsas_get_rphy(phy_info)) {
2243 dfailprintk((MYIOC_s_ERR_FMT
2244 "%s: exit at line=%d\n", ioc->name,
2245 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002246 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002247 }
2248 port = mptsas_get_port(phy_info);
2249 if (!port) {
2250 dfailprintk((MYIOC_s_ERR_FMT
2251 "%s: exit at line=%d\n", ioc->name,
2252 __FUNCTION__, __LINE__));
2253 break;
2254 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002255
Christoph Hellwige3094442006-02-16 13:25:36 +01002256 memcpy(&phy_info->attached, &sas_device,
2257 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002258
Moore, Ericc73787ee2006-01-26 16:20:06 -07002259 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2260 ds = "ssp";
2261 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2262 ds = "stp";
2263 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2264 ds = "sata";
2265
2266 printk(MYIOC_s_INFO_FMT
2267 "attaching %s device, channel %d, id %d, phy %d\n",
2268 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2269
James Bottomleyf013db32006-03-18 14:54:36 -06002270 mptsas_parse_device_info(&identify, &phy_info->attached);
Eric Moore547f9a22006-06-27 14:42:12 -06002271 rphy = sas_end_device_alloc(port);
2272 if (!rphy) {
2273 dfailprintk((MYIOC_s_ERR_FMT
2274 "%s: exit at line=%d\n", ioc->name,
2275 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002276 break; /* non-fatal: an rphy can be added later */
Eric Moore547f9a22006-06-27 14:42:12 -06002277 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002278
James Bottomleyf013db32006-03-18 14:54:36 -06002279 rphy->identify = identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002280 if (sas_rphy_add(rphy)) {
Eric Moore547f9a22006-06-27 14:42:12 -06002281 dfailprintk((MYIOC_s_ERR_FMT
2282 "%s: exit at line=%d\n", ioc->name,
2283 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002284 sas_rphy_free(rphy);
2285 break;
2286 }
Eric Moore547f9a22006-06-27 14:42:12 -06002287 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002288 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002289 case MPTSAS_ADD_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002290 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2291 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002292 if (sdev) {
2293 scsi_device_put(sdev);
2294 break;
2295 }
2296 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002297 "attaching raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002298 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2299 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002300 mpt_findImVolumes(ioc);
2301 break;
2302 case MPTSAS_DEL_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002303 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2304 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002305 if (!sdev)
2306 break;
2307 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002308 "removing raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002309 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
Eric Moore547f9a22006-06-27 14:42:12 -06002310 vdevice = sdev->hostdata;
2311 vdevice->vtarget->deleted = 1;
2312 mptsas_target_reset(ioc, vdevice->vtarget);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002313 scsi_remove_device(sdev);
2314 scsi_device_put(sdev);
2315 mpt_findImVolumes(ioc);
2316 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002317 case MPTSAS_IGNORE_EVENT:
2318 default:
2319 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002320 }
2321
Moore, Erice6b2d762006-03-14 09:14:24 -07002322 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002323 kfree(ev);
2324
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002325}
2326
2327static void
Eric Moore547f9a22006-06-27 14:42:12 -06002328mptsas_send_sas_event(MPT_ADAPTER *ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002329 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2330{
2331 struct mptsas_hotplug_event *ev;
2332 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2333 __le64 sas_address;
2334
2335 if ((device_info &
2336 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2337 MPI_SAS_DEVICE_INFO_STP_TARGET |
2338 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2339 return;
2340
Moore, Eric4b766472006-03-14 09:14:12 -07002341 switch (sas_event_data->ReasonCode) {
2342 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2343 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
Eric Moore547f9a22006-06-27 14:42:12 -06002344 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Eric4b766472006-03-14 09:14:12 -07002345 if (!ev) {
2346 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2347 break;
2348 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002349
David Howellsc4028952006-11-22 14:57:56 +00002350 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Eric4b766472006-03-14 09:14:12 -07002351 ev->ioc = ioc;
2352 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2353 ev->parent_handle =
2354 le16_to_cpu(sas_event_data->ParentDevHandle);
2355 ev->channel = sas_event_data->Bus;
2356 ev->id = sas_event_data->TargetID;
2357 ev->phy_id = sas_event_data->PhyNum;
2358 memcpy(&sas_address, &sas_event_data->SASAddress,
2359 sizeof(__le64));
2360 ev->sas_address = le64_to_cpu(sas_address);
2361 ev->device_info = device_info;
2362
2363 if (sas_event_data->ReasonCode &
2364 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2365 ev->event_type = MPTSAS_ADD_DEVICE;
2366 else
2367 ev->event_type = MPTSAS_DEL_DEVICE;
2368 schedule_work(&ev->work);
2369 break;
2370 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2371 /*
2372 * Persistent table is full.
2373 */
Eric Moore547f9a22006-06-27 14:42:12 -06002374 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00002375 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06002376 schedule_work(&ioc->sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002377 break;
2378 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
2379 /* TODO */
2380 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
2381 /* TODO */
2382 default:
2383 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002384 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002385}
2386
Moore, Ericc73787ee2006-01-26 16:20:06 -07002387static void
Eric Moore547f9a22006-06-27 14:42:12 -06002388mptsas_send_raid_event(MPT_ADAPTER *ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002389 EVENT_DATA_RAID *raid_event_data)
2390{
2391 struct mptsas_hotplug_event *ev;
Moore, Ericbd23e942006-04-17 12:43:04 -06002392 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2393 int state = (status >> 8) & 0xff;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002394
2395 if (ioc->bus_type != SAS)
2396 return;
2397
Eric Moore547f9a22006-06-27 14:42:12 -06002398 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002399 if (!ev) {
2400 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2401 return;
2402 }
2403
David Howellsc4028952006-11-22 14:57:56 +00002404 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002405 ev->ioc = ioc;
2406 ev->id = raid_event_data->VolumeID;
Moore, Ericbd23e942006-04-17 12:43:04 -06002407 ev->event_type = MPTSAS_IGNORE_EVENT;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002408
2409 switch (raid_event_data->ReasonCode) {
2410 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
2411 ev->event_type = MPTSAS_ADD_DEVICE;
2412 break;
2413 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07002414 ioc->raid_data.isRaid = 1;
2415 ev->phys_disk_num_valid = 1;
2416 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002417 ev->event_type = MPTSAS_DEL_DEVICE;
2418 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002419 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2420 switch (state) {
2421 case MPI_PD_STATE_ONLINE:
2422 ioc->raid_data.isRaid = 1;
2423 ev->phys_disk_num_valid = 1;
2424 ev->phys_disk_num = raid_event_data->PhysDiskNum;
2425 ev->event_type = MPTSAS_ADD_DEVICE;
2426 break;
2427 case MPI_PD_STATE_MISSING:
2428 case MPI_PD_STATE_NOT_COMPATIBLE:
2429 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2430 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2431 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
2432 ev->event_type = MPTSAS_DEL_DEVICE;
2433 break;
2434 default:
2435 break;
2436 }
2437 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002438 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2439 ev->event_type = MPTSAS_DEL_RAID;
2440 break;
2441 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2442 ev->event_type = MPTSAS_ADD_RAID;
2443 break;
2444 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
Moore, Ericbd23e942006-04-17 12:43:04 -06002445 switch (state) {
2446 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2447 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2448 ev->event_type = MPTSAS_DEL_RAID;
2449 break;
2450 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2451 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2452 ev->event_type = MPTSAS_ADD_RAID;
2453 break;
2454 default:
2455 break;
2456 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002457 break;
2458 default:
2459 break;
2460 }
2461 schedule_work(&ev->work);
2462}
2463
Moore, Erice6b2d762006-03-14 09:14:24 -07002464static void
Eric Moore547f9a22006-06-27 14:42:12 -06002465mptsas_send_discovery_event(MPT_ADAPTER *ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002466 EVENT_DATA_SAS_DISCOVERY *discovery_data)
2467{
2468 struct mptsas_discovery_event *ev;
2469
2470 /*
2471 * DiscoveryStatus
2472 *
2473 * This flag will be non-zero when firmware
2474 * kicks off discovery, and return to zero
2475 * once its completed.
2476 */
2477 if (discovery_data->DiscoveryStatus)
2478 return;
2479
Eric Moore547f9a22006-06-27 14:42:12 -06002480 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Erice6b2d762006-03-14 09:14:24 -07002481 if (!ev)
2482 return;
David Howellsc4028952006-11-22 14:57:56 +00002483 INIT_WORK(&ev->work, mptsas_discovery_work);
Moore, Erice6b2d762006-03-14 09:14:24 -07002484 ev->ioc = ioc;
2485 schedule_work(&ev->work);
2486};
2487
2488
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002489static int
2490mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
2491{
Moore, Ericc73787ee2006-01-26 16:20:06 -07002492 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002493 u8 event = le32_to_cpu(reply->Event) & 0xFF;
2494
2495 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002496 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002497
Moore, Erice6b2d762006-03-14 09:14:24 -07002498 /*
2499 * sas_discovery_ignore_events
2500 *
2501 * This flag is to prevent anymore processing of
2502 * sas events once mptsas_remove function is called.
2503 */
2504 if (ioc->sas_discovery_ignore_events) {
2505 rc = mptscsih_event_process(ioc, reply);
2506 goto out;
2507 }
2508
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002509 switch (event) {
2510 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
Eric Moore547f9a22006-06-27 14:42:12 -06002511 mptsas_send_sas_event(ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002512 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002513 break;
2514 case MPI_EVENT_INTEGRATED_RAID:
Eric Moore547f9a22006-06-27 14:42:12 -06002515 mptsas_send_raid_event(ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002516 (EVENT_DATA_RAID *)reply->Data);
2517 break;
Moore, Eric79de2782006-01-25 18:05:15 -07002518 case MPI_EVENT_PERSISTENT_TABLE_FULL:
Eric Moore547f9a22006-06-27 14:42:12 -06002519 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00002520 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06002521 schedule_work(&ioc->sas_persist_task);
Moore, Eric79de2782006-01-25 18:05:15 -07002522 break;
Moore, Eric4b766472006-03-14 09:14:12 -07002523 case MPI_EVENT_SAS_DISCOVERY:
Eric Moore547f9a22006-06-27 14:42:12 -06002524 mptsas_send_discovery_event(ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002525 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
2526 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002527 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002528 rc = mptscsih_event_process(ioc, reply);
2529 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002530 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002531 out:
2532
2533 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002534}
2535
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002536static int
2537mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2538{
2539 struct Scsi_Host *sh;
2540 MPT_SCSI_HOST *hd;
2541 MPT_ADAPTER *ioc;
2542 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002543 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002544 int numSGE = 0;
2545 int scale;
2546 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002547 int error=0;
2548 int r;
2549
2550 r = mpt_attach(pdev,id);
2551 if (r)
2552 return r;
2553
2554 ioc = pci_get_drvdata(pdev);
2555 ioc->DoneCtx = mptsasDoneCtx;
2556 ioc->TaskCtx = mptsasTaskCtx;
2557 ioc->InternalCtx = mptsasInternalCtx;
2558
2559 /* Added sanity check on readiness of the MPT adapter.
2560 */
2561 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
2562 printk(MYIOC_s_WARN_FMT
2563 "Skipping because it's not operational!\n",
2564 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002565 error = -ENODEV;
2566 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002567 }
2568
2569 if (!ioc->active) {
2570 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
2571 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002572 error = -ENODEV;
2573 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002574 }
2575
2576 /* Sanity check - ensure at least 1 port is INITIATOR capable
2577 */
2578 ioc_cap = 0;
2579 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
2580 if (ioc->pfacts[ii].ProtocolFlags &
2581 MPI_PORTFACTS_PROTOCOL_INITIATOR)
2582 ioc_cap++;
2583 }
2584
2585 if (!ioc_cap) {
2586 printk(MYIOC_s_WARN_FMT
2587 "Skipping ioc=%p because SCSI Initiator mode "
2588 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06002589 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002590 }
2591
2592 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
2593 if (!sh) {
2594 printk(MYIOC_s_WARN_FMT
2595 "Unable to register controller with SCSI subsystem\n",
2596 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002597 error = -1;
2598 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002599 }
2600
2601 spin_lock_irqsave(&ioc->FreeQlock, flags);
2602
2603 /* Attach the SCSI Host to the IOC structure
2604 */
2605 ioc->sh = sh;
2606
2607 sh->io_port = 0;
2608 sh->n_io_port = 0;
2609 sh->irq = 0;
2610
2611 /* set 16 byte cdb's */
2612 sh->max_cmd_len = 16;
2613
2614 sh->max_id = ioc->pfacts->MaxDevices + 1;
2615
2616 sh->transportt = mptsas_transport_template;
2617
2618 sh->max_lun = MPT_LAST_LUN + 1;
2619 sh->max_channel = 0;
2620 sh->this_id = ioc->pfacts[0].PortSCSIID;
2621
2622 /* Required entry.
2623 */
2624 sh->unique_id = ioc->id;
2625
2626 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002627 mutex_init(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07002628 mutex_init(&ioc->sas_discovery_mutex);
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01002629 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002630 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002631
2632 /* Verify that we won't exceed the maximum
2633 * number of chain buffers
2634 * We can optimize: ZZ = req_sz/sizeof(SGE)
2635 * For 32bit SGE's:
2636 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
2637 * + (req_sz - 64)/sizeof(SGE)
2638 * A slightly different algorithm is required for
2639 * 64bit SGEs.
2640 */
2641 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
2642 if (sizeof(dma_addr_t) == sizeof(u64)) {
2643 numSGE = (scale - 1) *
2644 (ioc->facts.MaxChainDepth-1) + scale +
2645 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
2646 sizeof(u32));
2647 } else {
2648 numSGE = 1 + (scale - 1) *
2649 (ioc->facts.MaxChainDepth-1) + scale +
2650 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
2651 sizeof(u32));
2652 }
2653
2654 if (numSGE < sh->sg_tablesize) {
2655 /* Reset this value */
2656 dprintk((MYIOC_s_INFO_FMT
2657 "Resetting sg_tablesize to %d from %d\n",
2658 ioc->name, numSGE, sh->sg_tablesize));
2659 sh->sg_tablesize = numSGE;
2660 }
2661
2662 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2663
2664 hd = (MPT_SCSI_HOST *) sh->hostdata;
2665 hd->ioc = ioc;
2666
2667 /* SCSI needs scsi_cmnd lookup table!
2668 * (with size equal to req_depth*PtrSz!)
2669 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002670 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
2671 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002672 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002673 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002674 }
2675
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002676 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
2677 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002678
2679 /* Allocate memory for the device structures.
2680 * A non-Null pointer at an offset
2681 * indicates a device exists.
2682 * max_id = 1 + maximum id (hosts.h)
2683 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002684 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
2685 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002686 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002687 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002688 }
2689
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002690 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002691
2692 /* Clear the TM flags
2693 */
2694 hd->tmPending = 0;
2695 hd->tmState = TM_STATE_NONE;
2696 hd->resetPending = 0;
2697 hd->abortSCpnt = NULL;
2698
2699 /* Clear the pointer used to store
2700 * single-threaded commands, i.e., those
2701 * issued during a bus scan, dv and
2702 * configuration pages.
2703 */
2704 hd->cmdPtr = NULL;
2705
2706 /* Initialize this SCSI Hosts' timers
2707 * To use, set the timer expires field
2708 * and add_timer
2709 */
2710 init_timer(&hd->timer);
2711 hd->timer.data = (unsigned long) hd;
2712 hd->timer.function = mptscsih_timer_expired;
2713
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002714 ioc->sas_data.ptClear = mpt_pt_clear;
2715
2716 if (ioc->sas_data.ptClear==1) {
2717 mptbase_sas_persist_operation(
2718 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
2719 }
2720
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002721 init_waitqueue_head(&hd->scandv_waitq);
2722 hd->scandv_wait_done = 0;
2723 hd->last_queue_full = 0;
2724
2725 error = scsi_add_host(sh, &ioc->pcidev->dev);
2726 if (error) {
2727 dprintk((KERN_ERR MYNAM
2728 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002729 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002730 }
2731
2732 mptsas_scan_sas_topology(ioc);
2733
2734 return 0;
2735
Eric Moore547f9a22006-06-27 14:42:12 -06002736 out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002737
2738 mptscsih_remove(pdev);
2739 return error;
2740}
2741
2742static void __devexit mptsas_remove(struct pci_dev *pdev)
2743{
2744 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2745 struct mptsas_portinfo *p, *n;
Eric Moore547f9a22006-06-27 14:42:12 -06002746 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002747
Moore, Erice6b2d762006-03-14 09:14:24 -07002748 ioc->sas_discovery_ignore_events=1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002749 sas_remove_host(ioc->sh);
2750
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002751 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002752 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
2753 list_del(&p->list);
Eric Moore547f9a22006-06-27 14:42:12 -06002754 for (i = 0 ; i < p->num_phys ; i++)
2755 mptsas_port_delete(p->phy_info[i].port_details);
2756 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002757 kfree(p);
2758 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002759 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002760
2761 mptscsih_remove(pdev);
2762}
2763
2764static struct pci_device_id mptsas_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06002765 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002766 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002767 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002768 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002769 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002770 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002771 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002772 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002773 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002774 PCI_ANY_ID, PCI_ANY_ID },
2775 {0} /* Terminating entry */
2776};
2777MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
2778
2779
2780static struct pci_driver mptsas_driver = {
2781 .name = "mptsas",
2782 .id_table = mptsas_pci_table,
2783 .probe = mptsas_probe,
2784 .remove = __devexit_p(mptsas_remove),
2785 .shutdown = mptscsih_shutdown,
2786#ifdef CONFIG_PM
2787 .suspend = mptscsih_suspend,
2788 .resume = mptscsih_resume,
2789#endif
2790};
2791
2792static int __init
2793mptsas_init(void)
2794{
2795 show_mptmod_ver(my_NAME, my_VERSION);
2796
2797 mptsas_transport_template =
2798 sas_attach_transport(&mptsas_transport_functions);
2799 if (!mptsas_transport_template)
2800 return -ENODEV;
2801
2802 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2803 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2804 mptsasInternalCtx =
2805 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002806 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002807
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002808 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07002809 devtverboseprintk((KERN_INFO MYNAM
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002810 ": Registered for IOC event notifications\n"));
2811 }
2812
2813 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2814 dprintk((KERN_INFO MYNAM
2815 ": Registered for IOC reset notifications\n"));
2816 }
2817
2818 return pci_register_driver(&mptsas_driver);
2819}
2820
2821static void __exit
2822mptsas_exit(void)
2823{
2824 pci_unregister_driver(&mptsas_driver);
2825 sas_release_transport(mptsas_transport_template);
2826
2827 mpt_reset_deregister(mptsasDoneCtx);
2828 mpt_event_deregister(mptsasDoneCtx);
2829
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002830 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002831 mpt_deregister(mptsasInternalCtx);
2832 mpt_deregister(mptsasTaskCtx);
2833 mpt_deregister(mptsasDoneCtx);
2834}
2835
2836module_init(mptsas_init);
2837module_exit(mptsas_exit);