[SCSI] mptsas : Sanity check for phyinfo is added
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / message / fusion / mptsas.c
blobf744f0fc949124fd06181ece3d8bd287bb8c9cb2
1 /*
2 * linux/drivers/message/fusion/mptsas.c
3 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
6 * Copyright (c) 1999-2008 LSI Corporation
7 * (mailto:DL-MPTFusionLinux@lsi.com)
8 */
9 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; version 2 of the License.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 NO WARRANTY
21 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
22 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
23 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
24 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
25 solely responsible for determining the appropriateness of using and
26 distributing the Program and assumes all risks associated with its
27 exercise of rights under this Agreement, including but not limited to
28 the risks and costs of program errors, damage to or loss of data,
29 programs or equipment, and unavailability or interruption of operations.
31 DISCLAIMER OF LIABILITY
32 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
33 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
35 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
38 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46 #include <linux/module.h>
47 #include <linux/kernel.h>
48 #include <linux/init.h>
49 #include <linux/errno.h>
50 #include <linux/jiffies.h>
51 #include <linux/workqueue.h>
52 #include <linux/delay.h> /* for mdelay */
54 #include <scsi/scsi.h>
55 #include <scsi/scsi_cmnd.h>
56 #include <scsi/scsi_device.h>
57 #include <scsi/scsi_host.h>
58 #include <scsi/scsi_transport_sas.h>
59 #include <scsi/scsi_dbg.h>
61 #include "mptbase.h"
62 #include "mptscsih.h"
63 #include "mptsas.h"
66 #define my_NAME "Fusion MPT SAS Host driver"
67 #define my_VERSION MPT_LINUX_VERSION_COMMON
68 #define MYNAM "mptsas"
71 * Reserved channel for integrated raid
73 #define MPTSAS_RAID_CHANNEL 1
75 #define SAS_CONFIG_PAGE_TIMEOUT 30
76 MODULE_AUTHOR(MODULEAUTHOR);
77 MODULE_DESCRIPTION(my_NAME);
78 MODULE_LICENSE("GPL");
79 MODULE_VERSION(my_VERSION);
81 static int mpt_pt_clear;
82 module_param(mpt_pt_clear, int, 0);
83 MODULE_PARM_DESC(mpt_pt_clear,
84 " Clear persistency table: enable=1 "
85 "(default=MPTSCSIH_PT_CLEAR=0)");
87 /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
88 #define MPTSAS_MAX_LUN (16895)
89 static int max_lun = MPTSAS_MAX_LUN;
90 module_param(max_lun, int, 0);
91 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
93 static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
94 static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
95 static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
96 static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
97 static u8 mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
99 static void mptsas_firmware_event_work(struct work_struct *work);
100 static void mptsas_send_sas_event(struct fw_event_work *fw_event);
101 static void mptsas_send_raid_event(struct fw_event_work *fw_event);
102 static void mptsas_send_ir2_event(struct fw_event_work *fw_event);
103 static void mptsas_parse_device_info(struct sas_identify *identify,
104 struct mptsas_devinfo *device_info);
105 static inline void mptsas_set_rphy(MPT_ADAPTER *ioc,
106 struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy);
107 static struct mptsas_phyinfo *mptsas_find_phyinfo_by_sas_address
108 (MPT_ADAPTER *ioc, u64 sas_address);
109 static int mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
110 struct mptsas_devinfo *device_info, u32 form, u32 form_specific);
111 static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc,
112 struct mptsas_enclosure *enclosure, u32 form, u32 form_specific);
113 static int mptsas_add_end_device(MPT_ADAPTER *ioc,
114 struct mptsas_phyinfo *phy_info);
115 static void mptsas_del_end_device(MPT_ADAPTER *ioc,
116 struct mptsas_phyinfo *phy_info);
117 static void mptsas_send_link_status_event(struct fw_event_work *fw_event);
118 static struct mptsas_portinfo *mptsas_find_portinfo_by_sas_address
119 (MPT_ADAPTER *ioc, u64 sas_address);
120 static void mptsas_expander_delete(MPT_ADAPTER *ioc,
121 struct mptsas_portinfo *port_info, u8 force);
122 static void mptsas_send_expander_event(struct fw_event_work *fw_event);
123 static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
124 static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
125 static void mptsas_broadcast_primative_work(struct fw_event_work *fw_event);
126 static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event);
127 static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);
129 static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
130 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
132 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
133 "---- IO UNIT PAGE 0 ------------\n", ioc->name));
134 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
135 ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
136 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
137 ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
138 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
139 ioc->name, phy_data->Port));
140 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
141 ioc->name, phy_data->PortFlags));
142 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
143 ioc->name, phy_data->PhyFlags));
144 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
145 ioc->name, phy_data->NegotiatedLinkRate));
146 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
147 "Controller PHY Device Info=0x%X\n", ioc->name,
148 le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
149 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
150 ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
153 static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
155 __le64 sas_address;
157 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
159 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
160 "---- SAS PHY PAGE 0 ------------\n", ioc->name));
161 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
162 "Attached Device Handle=0x%X\n", ioc->name,
163 le16_to_cpu(pg0->AttachedDevHandle)));
164 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
165 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
166 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
167 "Attached PHY Identifier=0x%X\n", ioc->name,
168 pg0->AttachedPhyIdentifier));
169 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
170 ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
171 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
172 ioc->name, pg0->ProgrammedLinkRate));
173 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
174 ioc->name, pg0->ChangeCount));
175 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
176 ioc->name, le32_to_cpu(pg0->PhyInfo)));
179 static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
181 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
182 "---- SAS PHY PAGE 1 ------------\n", ioc->name));
183 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
184 ioc->name, pg1->InvalidDwordCount));
185 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
186 "Running Disparity Error Count=0x%x\n", ioc->name,
187 pg1->RunningDisparityErrorCount));
188 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
189 "Loss Dword Synch Count=0x%x\n", ioc->name,
190 pg1->LossDwordSynchCount));
191 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
192 "PHY Reset Problem Count=0x%x\n\n", ioc->name,
193 pg1->PhyResetProblemCount));
196 static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
198 __le64 sas_address;
200 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
202 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
203 "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
204 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
205 ioc->name, le16_to_cpu(pg0->DevHandle)));
206 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
207 ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
208 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
209 ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
210 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
211 ioc->name, le16_to_cpu(pg0->Slot)));
212 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
213 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
214 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
215 ioc->name, pg0->TargetID));
216 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
217 ioc->name, pg0->Bus));
218 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
219 ioc->name, pg0->PhyNum));
220 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
221 ioc->name, le16_to_cpu(pg0->AccessStatus)));
222 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
223 ioc->name, le32_to_cpu(pg0->DeviceInfo)));
224 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
225 ioc->name, le16_to_cpu(pg0->Flags)));
226 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
227 ioc->name, pg0->PhysicalPort));
230 static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
232 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
233 "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
234 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
235 ioc->name, pg1->PhysicalPort));
236 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
237 ioc->name, pg1->PhyIdentifier));
238 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
239 ioc->name, pg1->NegotiatedLinkRate));
240 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
241 ioc->name, pg1->ProgrammedLinkRate));
242 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
243 ioc->name, pg1->HwLinkRate));
244 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
245 ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
246 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
247 "Attached Device Handle=0x%X\n\n", ioc->name,
248 le16_to_cpu(pg1->AttachedDevHandle)));
251 /* inhibit sas firmware event handling */
252 static void
253 mptsas_fw_event_off(MPT_ADAPTER *ioc)
255 unsigned long flags;
257 spin_lock_irqsave(&ioc->fw_event_lock, flags);
258 ioc->fw_events_off = 1;
259 ioc->sas_discovery_quiesce_io = 0;
260 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
264 /* enable sas firmware event handling */
265 static void
266 mptsas_fw_event_on(MPT_ADAPTER *ioc)
268 unsigned long flags;
270 spin_lock_irqsave(&ioc->fw_event_lock, flags);
271 ioc->fw_events_off = 0;
272 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
275 /* queue a sas firmware event */
276 static void
277 mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
278 unsigned long delay)
280 unsigned long flags;
282 spin_lock_irqsave(&ioc->fw_event_lock, flags);
283 list_add_tail(&fw_event->list, &ioc->fw_event_list);
284 INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
285 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n",
286 ioc->name, __func__, fw_event));
287 queue_delayed_work(ioc->fw_event_q, &fw_event->work,
288 delay);
289 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
292 /* requeue a sas firmware event */
293 static void
294 mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
295 unsigned long delay)
297 unsigned long flags;
298 spin_lock_irqsave(&ioc->fw_event_lock, flags);
299 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
300 "(fw_event=0x%p)\n", ioc->name, __func__, fw_event));
301 fw_event->retries++;
302 queue_delayed_work(ioc->fw_event_q, &fw_event->work,
303 msecs_to_jiffies(delay));
304 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
307 /* free memory assoicated to a sas firmware event */
308 static void
309 mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
311 unsigned long flags;
313 spin_lock_irqsave(&ioc->fw_event_lock, flags);
314 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n",
315 ioc->name, __func__, fw_event));
316 list_del(&fw_event->list);
317 kfree(fw_event);
318 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
321 /* walk the firmware event queue, and either stop or wait for
322 * outstanding events to complete */
323 static void
324 mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
326 struct fw_event_work *fw_event, *next;
327 struct mptsas_target_reset_event *target_reset_list, *n;
328 u8 flush_q;
329 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
331 /* flush the target_reset_list */
332 if (!list_empty(&hd->target_reset_list)) {
333 list_for_each_entry_safe(target_reset_list, n,
334 &hd->target_reset_list, list) {
335 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
336 "%s: removing target reset for id=%d\n",
337 ioc->name, __func__,
338 target_reset_list->sas_event_data.TargetID));
339 list_del(&target_reset_list->list);
340 kfree(target_reset_list);
344 if (list_empty(&ioc->fw_event_list) ||
345 !ioc->fw_event_q || in_interrupt())
346 return;
348 flush_q = 0;
349 list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
350 if (cancel_delayed_work(&fw_event->work))
351 mptsas_free_fw_event(ioc, fw_event);
352 else
353 flush_q = 1;
355 if (flush_q)
356 flush_workqueue(ioc->fw_event_q);
360 static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
362 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
363 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
366 static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
368 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
369 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
373 * mptsas_find_portinfo_by_handle
375 * This function should be called with the sas_topology_mutex already held
377 static struct mptsas_portinfo *
378 mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
380 struct mptsas_portinfo *port_info, *rc=NULL;
381 int i;
383 list_for_each_entry(port_info, &ioc->sas_topology, list)
384 for (i = 0; i < port_info->num_phys; i++)
385 if (port_info->phy_info[i].identify.handle == handle) {
386 rc = port_info;
387 goto out;
389 out:
390 return rc;
394 * mptsas_find_portinfo_by_sas_address -
395 * @ioc: Pointer to MPT_ADAPTER structure
396 * @handle:
398 * This function should be called with the sas_topology_mutex already held
401 static struct mptsas_portinfo *
402 mptsas_find_portinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
404 struct mptsas_portinfo *port_info, *rc = NULL;
405 int i;
407 if (sas_address >= ioc->hba_port_sas_addr &&
408 sas_address < (ioc->hba_port_sas_addr +
409 ioc->hba_port_num_phy))
410 return ioc->hba_port_info;
412 mutex_lock(&ioc->sas_topology_mutex);
413 list_for_each_entry(port_info, &ioc->sas_topology, list)
414 for (i = 0; i < port_info->num_phys; i++)
415 if (port_info->phy_info[i].identify.sas_address ==
416 sas_address) {
417 rc = port_info;
418 goto out;
420 out:
421 mutex_unlock(&ioc->sas_topology_mutex);
422 return rc;
426 * Returns true if there is a scsi end device
428 static inline int
429 mptsas_is_end_device(struct mptsas_devinfo * attached)
431 if ((attached->sas_address) &&
432 (attached->device_info &
433 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
434 ((attached->device_info &
435 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
436 (attached->device_info &
437 MPI_SAS_DEVICE_INFO_STP_TARGET) |
438 (attached->device_info &
439 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
440 return 1;
441 else
442 return 0;
445 /* no mutex */
446 static void
447 mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
449 struct mptsas_portinfo *port_info;
450 struct mptsas_phyinfo *phy_info;
451 u8 i;
453 if (!port_details)
454 return;
456 port_info = port_details->port_info;
457 phy_info = port_info->phy_info;
459 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
460 "bitmask=0x%016llX\n", ioc->name, __func__, port_details,
461 port_details->num_phys, (unsigned long long)
462 port_details->phy_bitmask));
464 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
465 if(phy_info->port_details != port_details)
466 continue;
467 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
468 mptsas_set_rphy(ioc, phy_info, NULL);
469 phy_info->port_details = NULL;
471 kfree(port_details);
474 static inline struct sas_rphy *
475 mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
477 if (phy_info->port_details)
478 return phy_info->port_details->rphy;
479 else
480 return NULL;
483 static inline void
484 mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
486 if (phy_info->port_details) {
487 phy_info->port_details->rphy = rphy;
488 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
489 ioc->name, rphy));
492 if (rphy) {
493 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
494 &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
495 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
496 ioc->name, rphy, rphy->dev.release));
500 static inline struct sas_port *
501 mptsas_get_port(struct mptsas_phyinfo *phy_info)
503 if (phy_info->port_details)
504 return phy_info->port_details->port;
505 else
506 return NULL;
509 static inline void
510 mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
512 if (phy_info->port_details)
513 phy_info->port_details->port = port;
515 if (port) {
516 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
517 &port->dev, MYIOC_s_FMT "add:", ioc->name));
518 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
519 ioc->name, port, port->dev.release));
523 static inline struct scsi_target *
524 mptsas_get_starget(struct mptsas_phyinfo *phy_info)
526 if (phy_info->port_details)
527 return phy_info->port_details->starget;
528 else
529 return NULL;
532 static inline void
533 mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
534 starget)
536 if (phy_info->port_details)
537 phy_info->port_details->starget = starget;
541 * mptsas_add_device_component -
542 * @ioc: Pointer to MPT_ADAPTER structure
543 * @channel: fw mapped id's
544 * @id:
545 * @sas_address:
546 * @device_info:
549 static void
550 mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
551 u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id)
553 struct mptsas_device_info *sas_info, *next;
554 struct scsi_device *sdev;
555 struct scsi_target *starget;
556 struct sas_rphy *rphy;
559 * Delete all matching devices out of the list
561 mutex_lock(&ioc->sas_device_info_mutex);
562 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
563 list) {
564 if (!sas_info->is_logical_volume &&
565 (sas_info->sas_address == sas_address ||
566 (sas_info->fw.channel == channel &&
567 sas_info->fw.id == id))) {
568 list_del(&sas_info->list);
569 kfree(sas_info);
573 sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
574 if (!sas_info)
575 goto out;
578 * Set Firmware mapping
580 sas_info->fw.id = id;
581 sas_info->fw.channel = channel;
583 sas_info->sas_address = sas_address;
584 sas_info->device_info = device_info;
585 sas_info->slot = slot;
586 sas_info->enclosure_logical_id = enclosure_logical_id;
587 INIT_LIST_HEAD(&sas_info->list);
588 list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
591 * Set OS mapping
593 shost_for_each_device(sdev, ioc->sh) {
594 starget = scsi_target(sdev);
595 rphy = dev_to_rphy(starget->dev.parent);
596 if (rphy->identify.sas_address == sas_address) {
597 sas_info->os.id = starget->id;
598 sas_info->os.channel = starget->channel;
602 out:
603 mutex_unlock(&ioc->sas_device_info_mutex);
604 return;
608 * mptsas_add_device_component_by_fw -
609 * @ioc: Pointer to MPT_ADAPTER structure
610 * @channel: fw mapped id's
611 * @id:
614 static void
615 mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
617 struct mptsas_devinfo sas_device;
618 struct mptsas_enclosure enclosure_info;
619 int rc;
621 rc = mptsas_sas_device_pg0(ioc, &sas_device,
622 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
623 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
624 (channel << 8) + id);
625 if (rc)
626 return;
628 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
629 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
630 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
631 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
632 sas_device.handle_enclosure);
634 mptsas_add_device_component(ioc, sas_device.channel,
635 sas_device.id, sas_device.sas_address, sas_device.device_info,
636 sas_device.slot, enclosure_info.enclosure_logical_id);
640 * mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding each individual device to list
641 * @ioc: Pointer to MPT_ADAPTER structure
642 * @channel: fw mapped id's
643 * @id:
646 static void
647 mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc,
648 struct scsi_target *starget)
650 CONFIGPARMS cfg;
651 ConfigPageHeader_t hdr;
652 dma_addr_t dma_handle;
653 pRaidVolumePage0_t buffer = NULL;
654 int i;
655 RaidPhysDiskPage0_t phys_disk;
656 struct mptsas_device_info *sas_info, *next;
658 memset(&cfg, 0 , sizeof(CONFIGPARMS));
659 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
660 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
661 /* assumption that all volumes on channel = 0 */
662 cfg.pageAddr = starget->id;
663 cfg.cfghdr.hdr = &hdr;
664 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
665 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
667 if (mpt_config(ioc, &cfg) != 0)
668 goto out;
670 if (!hdr.PageLength)
671 goto out;
673 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
674 &dma_handle);
676 if (!buffer)
677 goto out;
679 cfg.physAddr = dma_handle;
680 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
682 if (mpt_config(ioc, &cfg) != 0)
683 goto out;
685 if (!buffer->NumPhysDisks)
686 goto out;
689 * Adding entry for hidden components
691 for (i = 0; i < buffer->NumPhysDisks; i++) {
693 if (mpt_raid_phys_disk_pg0(ioc,
694 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
695 continue;
697 mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus,
698 phys_disk.PhysDiskID);
700 mutex_lock(&ioc->sas_device_info_mutex);
701 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
702 list) {
703 if (!sas_info->is_logical_volume &&
704 (sas_info->fw.channel == phys_disk.PhysDiskBus &&
705 sas_info->fw.id == phys_disk.PhysDiskID)) {
706 sas_info->is_hidden_raid_component = 1;
707 sas_info->volume_id = starget->id;
710 mutex_unlock(&ioc->sas_device_info_mutex);
715 * Delete all matching devices out of the list
717 mutex_lock(&ioc->sas_device_info_mutex);
718 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
719 list) {
720 if (sas_info->is_logical_volume && sas_info->fw.id ==
721 starget->id) {
722 list_del(&sas_info->list);
723 kfree(sas_info);
727 sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
728 if (sas_info) {
729 sas_info->fw.id = starget->id;
730 sas_info->os.id = starget->id;
731 sas_info->os.channel = starget->channel;
732 sas_info->is_logical_volume = 1;
733 INIT_LIST_HEAD(&sas_info->list);
734 list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
736 mutex_unlock(&ioc->sas_device_info_mutex);
738 out:
739 if (buffer)
740 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
741 dma_handle);
745 * mptsas_add_device_component_starget -
746 * @ioc: Pointer to MPT_ADAPTER structure
747 * @starget:
750 static void
751 mptsas_add_device_component_starget(MPT_ADAPTER *ioc,
752 struct scsi_target *starget)
754 VirtTarget *vtarget;
755 struct sas_rphy *rphy;
756 struct mptsas_phyinfo *phy_info = NULL;
757 struct mptsas_enclosure enclosure_info;
759 rphy = dev_to_rphy(starget->dev.parent);
760 vtarget = starget->hostdata;
761 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
762 rphy->identify.sas_address);
763 if (!phy_info)
764 return;
766 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
767 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
768 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
769 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
770 phy_info->attached.handle_enclosure);
772 mptsas_add_device_component(ioc, phy_info->attached.channel,
773 phy_info->attached.id, phy_info->attached.sas_address,
774 phy_info->attached.device_info,
775 phy_info->attached.slot, enclosure_info.enclosure_logical_id);
779 * mptsas_del_device_component_by_os - Once a device has been removed, we mark the entry in the list as being cached
780 * @ioc: Pointer to MPT_ADAPTER structure
781 * @channel: os mapped id's
782 * @id:
785 static void
786 mptsas_del_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
788 struct mptsas_device_info *sas_info, *next;
791 * Set is_cached flag
793 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
794 list) {
795 if (sas_info->os.channel == channel && sas_info->os.id == id)
796 sas_info->is_cached = 1;
801 * mptsas_del_device_components - Cleaning the list
802 * @ioc: Pointer to MPT_ADAPTER structure
805 static void
806 mptsas_del_device_components(MPT_ADAPTER *ioc)
808 struct mptsas_device_info *sas_info, *next;
810 mutex_lock(&ioc->sas_device_info_mutex);
811 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
812 list) {
813 list_del(&sas_info->list);
814 kfree(sas_info);
816 mutex_unlock(&ioc->sas_device_info_mutex);
821 * mptsas_setup_wide_ports
823 * Updates for new and existing narrow/wide port configuration
824 * in the sas_topology
826 static void
827 mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
829 struct mptsas_portinfo_details * port_details;
830 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
831 u64 sas_address;
832 int i, j;
834 mutex_lock(&ioc->sas_topology_mutex);
836 phy_info = port_info->phy_info;
837 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
838 if (phy_info->attached.handle)
839 continue;
840 port_details = phy_info->port_details;
841 if (!port_details)
842 continue;
843 if (port_details->num_phys < 2)
844 continue;
846 * Removing a phy from a port, letting the last
847 * phy be removed by firmware events.
849 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
850 "%s: [%p]: deleting phy = %d\n",
851 ioc->name, __func__, port_details, i));
852 port_details->num_phys--;
853 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
854 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
855 if (phy_info->phy) {
856 devtprintk(ioc, dev_printk(KERN_DEBUG,
857 &phy_info->phy->dev, MYIOC_s_FMT
858 "delete phy %d, phy-obj (0x%p)\n", ioc->name,
859 phy_info->phy_id, phy_info->phy));
860 sas_port_delete_phy(port_details->port, phy_info->phy);
862 phy_info->port_details = NULL;
866 * Populate and refresh the tree
868 phy_info = port_info->phy_info;
869 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
870 sas_address = phy_info->attached.sas_address;
871 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
872 ioc->name, i, (unsigned long long)sas_address));
873 if (!sas_address)
874 continue;
875 port_details = phy_info->port_details;
877 * Forming a port
879 if (!port_details) {
880 port_details = kzalloc(sizeof(struct
881 mptsas_portinfo_details), GFP_KERNEL);
882 if (!port_details)
883 goto out;
884 port_details->num_phys = 1;
885 port_details->port_info = port_info;
886 if (phy_info->phy_id < 64 )
887 port_details->phy_bitmask |=
888 (1 << phy_info->phy_id);
889 phy_info->sas_port_add_phy=1;
890 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
891 "phy_id=%d sas_address=0x%018llX\n",
892 ioc->name, i, (unsigned long long)sas_address));
893 phy_info->port_details = port_details;
896 if (i == port_info->num_phys - 1)
897 continue;
898 phy_info_cmp = &port_info->phy_info[i + 1];
899 for (j = i + 1 ; j < port_info->num_phys ; j++,
900 phy_info_cmp++) {
901 if (!phy_info_cmp->attached.sas_address)
902 continue;
903 if (sas_address != phy_info_cmp->attached.sas_address)
904 continue;
905 if (phy_info_cmp->port_details == port_details )
906 continue;
907 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
908 "\t\tphy_id=%d sas_address=0x%018llX\n",
909 ioc->name, j, (unsigned long long)
910 phy_info_cmp->attached.sas_address));
911 if (phy_info_cmp->port_details) {
912 port_details->rphy =
913 mptsas_get_rphy(phy_info_cmp);
914 port_details->port =
915 mptsas_get_port(phy_info_cmp);
916 port_details->starget =
917 mptsas_get_starget(phy_info_cmp);
918 port_details->num_phys =
919 phy_info_cmp->port_details->num_phys;
920 if (!phy_info_cmp->port_details->num_phys)
921 kfree(phy_info_cmp->port_details);
922 } else
923 phy_info_cmp->sas_port_add_phy=1;
925 * Adding a phy to a port
927 phy_info_cmp->port_details = port_details;
928 if (phy_info_cmp->phy_id < 64 )
929 port_details->phy_bitmask |=
930 (1 << phy_info_cmp->phy_id);
931 port_details->num_phys++;
935 out:
937 for (i = 0; i < port_info->num_phys; i++) {
938 port_details = port_info->phy_info[i].port_details;
939 if (!port_details)
940 continue;
941 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
942 "%s: [%p]: phy_id=%02d num_phys=%02d "
943 "bitmask=0x%016llX\n", ioc->name, __func__,
944 port_details, i, port_details->num_phys,
945 (unsigned long long)port_details->phy_bitmask));
946 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
947 ioc->name, port_details->port, port_details->rphy));
949 dsaswideprintk(ioc, printk("\n"));
950 mutex_unlock(&ioc->sas_topology_mutex);
954 * csmisas_find_vtarget
956 * @ioc
957 * @volume_id
958 * @volume_bus
961 static VirtTarget *
962 mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
964 struct scsi_device *sdev;
965 VirtDevice *vdevice;
966 VirtTarget *vtarget = NULL;
968 shost_for_each_device(sdev, ioc->sh) {
969 vdevice = sdev->hostdata;
970 if ((vdevice == NULL) ||
971 (vdevice->vtarget == NULL))
972 continue;
973 if ((vdevice->vtarget->tflags &
974 MPT_TARGET_FLAGS_RAID_COMPONENT ||
975 vdevice->vtarget->raidVolume))
976 continue;
977 if (vdevice->vtarget->id == id &&
978 vdevice->vtarget->channel == channel)
979 vtarget = vdevice->vtarget;
981 return vtarget;
984 static void
985 mptsas_queue_device_delete(MPT_ADAPTER *ioc,
986 MpiEventDataSasDeviceStatusChange_t *sas_event_data)
988 struct fw_event_work *fw_event;
989 int sz;
991 sz = offsetof(struct fw_event_work, event_data) +
992 sizeof(MpiEventDataSasDeviceStatusChange_t);
993 fw_event = kzalloc(sz, GFP_ATOMIC);
994 if (!fw_event) {
995 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
996 ioc->name, __func__, __LINE__);
997 return;
999 memcpy(fw_event->event_data, sas_event_data,
1000 sizeof(MpiEventDataSasDeviceStatusChange_t));
1001 fw_event->event = MPI_EVENT_SAS_DEVICE_STATUS_CHANGE;
1002 fw_event->ioc = ioc;
1003 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
1006 static void
1007 mptsas_queue_rescan(MPT_ADAPTER *ioc)
1009 struct fw_event_work *fw_event;
1010 int sz;
1012 sz = offsetof(struct fw_event_work, event_data);
1013 fw_event = kzalloc(sz, GFP_ATOMIC);
1014 if (!fw_event) {
1015 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
1016 ioc->name, __func__, __LINE__);
1017 return;
1019 fw_event->event = -1;
1020 fw_event->ioc = ioc;
1021 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
1026 * mptsas_target_reset
1028 * Issues TARGET_RESET to end device using handshaking method
1030 * @ioc
1031 * @channel
1032 * @id
1034 * Returns (1) success
1035 * (0) failure
1038 static int
1039 mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
1041 MPT_FRAME_HDR *mf;
1042 SCSITaskMgmt_t *pScsiTm;
1043 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0)
1044 return 0;
1047 mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
1048 if (mf == NULL) {
1049 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
1050 "%s, no msg frames @%d!!\n", ioc->name,
1051 __func__, __LINE__));
1052 goto out_fail;
1055 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
1056 ioc->name, mf));
1058 /* Format the Request
1060 pScsiTm = (SCSITaskMgmt_t *) mf;
1061 memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
1062 pScsiTm->TargetID = id;
1063 pScsiTm->Bus = channel;
1064 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1065 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
1066 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
1068 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
1070 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1071 "TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
1072 ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
1074 mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
1076 return 1;
1078 out_fail:
1080 mpt_clear_taskmgmt_in_progress_flag(ioc);
1081 return 0;
1085 * mptsas_target_reset_queue
1087 * Receive request for TARGET_RESET after recieving an firmware
1088 * event NOT_RESPONDING_EVENT, then put command in link list
1089 * and queue if task_queue already in use.
1091 * @ioc
1092 * @sas_event_data
1095 static void
1096 mptsas_target_reset_queue(MPT_ADAPTER *ioc,
1097 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1099 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
1100 VirtTarget *vtarget = NULL;
1101 struct mptsas_target_reset_event *target_reset_list;
1102 u8 id, channel;
1104 id = sas_event_data->TargetID;
1105 channel = sas_event_data->Bus;
1107 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
1108 return;
1110 vtarget->deleted = 1; /* block IO */
1112 target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
1113 GFP_ATOMIC);
1114 if (!target_reset_list) {
1115 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
1116 "%s, failed to allocate mem @%d..!!\n",
1117 ioc->name, __func__, __LINE__));
1118 return;
1121 memcpy(&target_reset_list->sas_event_data, sas_event_data,
1122 sizeof(*sas_event_data));
1123 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
1125 target_reset_list->time_count = jiffies;
1127 if (mptsas_target_reset(ioc, channel, id)) {
1128 target_reset_list->target_reset_issued = 1;
1133 * mptsas_taskmgmt_complete - complete SAS task management function
1134 * @ioc: Pointer to MPT_ADAPTER structure
1136 * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, enable work
1137 * queue to finish off removing device from upper layers. then send next
1138 * TARGET_RESET in the queue.
1140 static int
1141 mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
1143 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
1144 struct list_head *head = &hd->target_reset_list;
1145 u8 id, channel;
1146 struct mptsas_target_reset_event *target_reset_list;
1147 SCSITaskMgmtReply_t *pScsiTmReply;
1149 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: "
1150 "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
1152 pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
1153 if (pScsiTmReply) {
1154 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1155 "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
1156 "\ttask_type = 0x%02X, iocstatus = 0x%04X "
1157 "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
1158 "term_cmnds = %d\n", ioc->name,
1159 pScsiTmReply->Bus, pScsiTmReply->TargetID,
1160 pScsiTmReply->TaskType,
1161 le16_to_cpu(pScsiTmReply->IOCStatus),
1162 le32_to_cpu(pScsiTmReply->IOCLogInfo),
1163 pScsiTmReply->ResponseCode,
1164 le32_to_cpu(pScsiTmReply->TerminationCount)));
1166 if (pScsiTmReply->ResponseCode)
1167 mptscsih_taskmgmt_response_code(ioc,
1168 pScsiTmReply->ResponseCode);
1171 if (pScsiTmReply && (pScsiTmReply->TaskType ==
1172 MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
1173 MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
1174 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
1175 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
1176 memcpy(ioc->taskmgmt_cmds.reply, mr,
1177 min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
1178 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
1179 ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
1180 complete(&ioc->taskmgmt_cmds.done);
1181 return 1;
1183 return 0;
1186 mpt_clear_taskmgmt_in_progress_flag(ioc);
1188 if (list_empty(head))
1189 return 1;
1191 target_reset_list = list_entry(head->next,
1192 struct mptsas_target_reset_event, list);
1194 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1195 "TaskMgmt: completed (%d seconds)\n",
1196 ioc->name, jiffies_to_msecs(jiffies -
1197 target_reset_list->time_count)/1000));
1199 id = pScsiTmReply->TargetID;
1200 channel = pScsiTmReply->Bus;
1201 target_reset_list->time_count = jiffies;
1204 * retry target reset
1206 if (!target_reset_list->target_reset_issued) {
1207 if (mptsas_target_reset(ioc, channel, id))
1208 target_reset_list->target_reset_issued = 1;
1209 return 1;
1213 * enable work queue to remove device from upper layers
1215 list_del(&target_reset_list->list);
1216 if ((mptsas_find_vtarget(ioc, channel, id)) && !ioc->fw_events_off)
1217 mptsas_queue_device_delete(ioc,
1218 &target_reset_list->sas_event_data);
1222 * issue target reset to next device in the queue
1225 head = &hd->target_reset_list;
1226 if (list_empty(head))
1227 return 1;
1229 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
1230 list);
1232 id = target_reset_list->sas_event_data.TargetID;
1233 channel = target_reset_list->sas_event_data.Bus;
1234 target_reset_list->time_count = jiffies;
1236 if (mptsas_target_reset(ioc, channel, id))
1237 target_reset_list->target_reset_issued = 1;
1239 return 1;
1243 * mptscsih_ioc_reset
1245 * @ioc
1246 * @reset_phase
1249 static int
1250 mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1252 MPT_SCSI_HOST *hd;
1253 int rc;
1255 rc = mptscsih_ioc_reset(ioc, reset_phase);
1256 if ((ioc->bus_type != SAS) || (!rc))
1257 return rc;
1259 hd = shost_priv(ioc->sh);
1260 if (!hd->ioc)
1261 goto out;
1263 switch (reset_phase) {
1264 case MPT_IOC_SETUP_RESET:
1265 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1266 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
1267 mptsas_fw_event_off(ioc);
1268 break;
1269 case MPT_IOC_PRE_RESET:
1270 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1271 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
1272 break;
1273 case MPT_IOC_POST_RESET:
1274 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1275 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
1276 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
1277 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET;
1278 complete(&ioc->sas_mgmt.done);
1280 mptsas_cleanup_fw_event_q(ioc);
1281 mptsas_queue_rescan(ioc);
1282 mptsas_fw_event_on(ioc);
1283 break;
1284 default:
1285 break;
1288 out:
1289 return rc;
1294 * enum device_state -
1295 * @DEVICE_RETRY: need to retry the TUR
1296 * @DEVICE_ERROR: TUR return error, don't add device
1297 * @DEVICE_READY: device can be added
1300 enum device_state{
1301 DEVICE_RETRY,
1302 DEVICE_ERROR,
1303 DEVICE_READY,
1306 static int
1307 mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
1308 u32 form, u32 form_specific)
1310 ConfigExtendedPageHeader_t hdr;
1311 CONFIGPARMS cfg;
1312 SasEnclosurePage0_t *buffer;
1313 dma_addr_t dma_handle;
1314 int error;
1315 __le64 le_identifier;
1317 memset(&hdr, 0, sizeof(hdr));
1318 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
1319 hdr.PageNumber = 0;
1320 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1321 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
1323 cfg.cfghdr.ehdr = &hdr;
1324 cfg.physAddr = -1;
1325 cfg.pageAddr = form + form_specific;
1326 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1327 cfg.dir = 0; /* read */
1328 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
1330 error = mpt_config(ioc, &cfg);
1331 if (error)
1332 goto out;
1333 if (!hdr.ExtPageLength) {
1334 error = -ENXIO;
1335 goto out;
1338 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1339 &dma_handle);
1340 if (!buffer) {
1341 error = -ENOMEM;
1342 goto out;
1345 cfg.physAddr = dma_handle;
1346 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1348 error = mpt_config(ioc, &cfg);
1349 if (error)
1350 goto out_free_consistent;
1352 /* save config data */
1353 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
1354 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
1355 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
1356 enclosure->flags = le16_to_cpu(buffer->Flags);
1357 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
1358 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
1359 enclosure->start_id = buffer->StartTargetID;
1360 enclosure->start_channel = buffer->StartBus;
1361 enclosure->sep_id = buffer->SEPTargetID;
1362 enclosure->sep_channel = buffer->SEPBus;
1364 out_free_consistent:
1365 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1366 buffer, dma_handle);
1367 out:
1368 return error;
1372 * mptsas_add_end_device - report a new end device to sas transport layer
1373 * @ioc: Pointer to MPT_ADAPTER structure
1374 * @phy_info: decribes attached device
1376 * return (0) success (1) failure
1379 static int
1380 mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1382 struct sas_rphy *rphy;
1383 struct sas_port *port;
1384 struct sas_identify identify;
1385 char *ds = NULL;
1386 u8 fw_id;
1388 if (!phy_info) {
1389 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1390 "%s: exit at line=%d\n", ioc->name,
1391 __func__, __LINE__));
1392 return 1;
1395 fw_id = phy_info->attached.id;
1397 if (mptsas_get_rphy(phy_info)) {
1398 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1399 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1400 __func__, fw_id, __LINE__));
1401 return 2;
1404 port = mptsas_get_port(phy_info);
1405 if (!port) {
1406 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1407 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1408 __func__, fw_id, __LINE__));
1409 return 3;
1412 if (phy_info->attached.device_info &
1413 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1414 ds = "ssp";
1415 if (phy_info->attached.device_info &
1416 MPI_SAS_DEVICE_INFO_STP_TARGET)
1417 ds = "stp";
1418 if (phy_info->attached.device_info &
1419 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1420 ds = "sata";
1422 printk(MYIOC_s_INFO_FMT "attaching %s device: fw_channel %d, fw_id %d,"
1423 " phy %d, sas_addr 0x%llx\n", ioc->name, ds,
1424 phy_info->attached.channel, phy_info->attached.id,
1425 phy_info->attached.phy_id, (unsigned long long)
1426 phy_info->attached.sas_address);
1428 mptsas_parse_device_info(&identify, &phy_info->attached);
1429 rphy = sas_end_device_alloc(port);
1430 if (!rphy) {
1431 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1432 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1433 __func__, fw_id, __LINE__));
1434 return 5; /* non-fatal: an rphy can be added later */
1437 rphy->identify = identify;
1438 if (sas_rphy_add(rphy)) {
1439 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1440 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1441 __func__, fw_id, __LINE__));
1442 sas_rphy_free(rphy);
1443 return 6;
1445 mptsas_set_rphy(ioc, phy_info, rphy);
1446 return 0;
1450 * mptsas_del_end_device - report a deleted end device to sas transport layer
1451 * @ioc: Pointer to MPT_ADAPTER structure
1452 * @phy_info: decribes attached device
1455 static void
1456 mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1458 struct sas_rphy *rphy;
1459 struct sas_port *port;
1460 struct mptsas_portinfo *port_info;
1461 struct mptsas_phyinfo *phy_info_parent;
1462 int i;
1463 char *ds = NULL;
1464 u8 fw_id;
1465 u64 sas_address;
1467 if (!phy_info)
1468 return;
1470 fw_id = phy_info->attached.id;
1471 sas_address = phy_info->attached.sas_address;
1473 if (!phy_info->port_details) {
1474 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1475 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1476 __func__, fw_id, __LINE__));
1477 return;
1479 rphy = mptsas_get_rphy(phy_info);
1480 if (!rphy) {
1481 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1482 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1483 __func__, fw_id, __LINE__));
1484 return;
1487 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR
1488 || phy_info->attached.device_info
1489 & MPI_SAS_DEVICE_INFO_SMP_INITIATOR
1490 || phy_info->attached.device_info
1491 & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1492 ds = "initiator";
1493 if (phy_info->attached.device_info &
1494 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1495 ds = "ssp";
1496 if (phy_info->attached.device_info &
1497 MPI_SAS_DEVICE_INFO_STP_TARGET)
1498 ds = "stp";
1499 if (phy_info->attached.device_info &
1500 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1501 ds = "sata";
1503 dev_printk(KERN_DEBUG, &rphy->dev, MYIOC_s_FMT
1504 "removing %s device: fw_channel %d, fw_id %d, phy %d,"
1505 "sas_addr 0x%llx\n", ioc->name, ds, phy_info->attached.channel,
1506 phy_info->attached.id, phy_info->attached.phy_id,
1507 (unsigned long long) sas_address);
1509 port = mptsas_get_port(phy_info);
1510 if (!port) {
1511 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1512 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1513 __func__, fw_id, __LINE__));
1514 return;
1516 port_info = phy_info->portinfo;
1517 phy_info_parent = port_info->phy_info;
1518 for (i = 0; i < port_info->num_phys; i++, phy_info_parent++) {
1519 if (!phy_info_parent->phy)
1520 continue;
1521 if (phy_info_parent->attached.sas_address !=
1522 sas_address)
1523 continue;
1524 dev_printk(KERN_DEBUG, &phy_info_parent->phy->dev,
1525 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n",
1526 ioc->name, phy_info_parent->phy_id,
1527 phy_info_parent->phy);
1528 sas_port_delete_phy(port, phy_info_parent->phy);
1531 dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
1532 "delete port %d, sas_addr (0x%llx)\n", ioc->name,
1533 port->port_identifier, (unsigned long long)sas_address);
1534 sas_port_delete(port);
1535 mptsas_set_port(ioc, phy_info, NULL);
1536 mptsas_port_delete(ioc, phy_info->port_details);
1539 struct mptsas_phyinfo *
1540 mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
1541 struct mptsas_devinfo *sas_device)
1543 struct mptsas_phyinfo *phy_info;
1544 struct mptsas_portinfo *port_info;
1545 int i;
1547 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
1548 sas_device->sas_address);
1549 if (!phy_info)
1550 goto out;
1551 port_info = phy_info->portinfo;
1552 if (!port_info)
1553 goto out;
1554 mutex_lock(&ioc->sas_topology_mutex);
1555 for (i = 0; i < port_info->num_phys; i++) {
1556 if (port_info->phy_info[i].attached.sas_address !=
1557 sas_device->sas_address)
1558 continue;
1559 port_info->phy_info[i].attached.channel = sas_device->channel;
1560 port_info->phy_info[i].attached.id = sas_device->id;
1561 port_info->phy_info[i].attached.sas_address =
1562 sas_device->sas_address;
1563 port_info->phy_info[i].attached.handle = sas_device->handle;
1564 port_info->phy_info[i].attached.handle_parent =
1565 sas_device->handle_parent;
1566 port_info->phy_info[i].attached.handle_enclosure =
1567 sas_device->handle_enclosure;
1569 mutex_unlock(&ioc->sas_topology_mutex);
1570 out:
1571 return phy_info;
1575 * mptsas_firmware_event_work - work thread for processing fw events
1576 * @work: work queue payload containing info describing the event
1577 * Context: user
1580 static void
1581 mptsas_firmware_event_work(struct work_struct *work)
1583 struct fw_event_work *fw_event =
1584 container_of(work, struct fw_event_work, work.work);
1585 MPT_ADAPTER *ioc = fw_event->ioc;
1587 /* special rescan topology handling */
1588 if (fw_event->event == -1) {
1589 if (ioc->in_rescan) {
1590 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1591 "%s: rescan ignored as it is in progress\n",
1592 ioc->name, __func__));
1593 return;
1595 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: rescan after "
1596 "reset\n", ioc->name, __func__));
1597 ioc->in_rescan = 1;
1598 mptsas_not_responding_devices(ioc);
1599 mptsas_scan_sas_topology(ioc);
1600 ioc->in_rescan = 0;
1601 mptsas_free_fw_event(ioc, fw_event);
1602 return;
1605 /* events handling turned off during host reset */
1606 if (ioc->fw_events_off) {
1607 mptsas_free_fw_event(ioc, fw_event);
1608 return;
1611 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_event=(0x%p), "
1612 "event = (0x%02x)\n", ioc->name, __func__, fw_event,
1613 (fw_event->event & 0xFF)));
1615 switch (fw_event->event) {
1616 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1617 mptsas_send_sas_event(fw_event);
1618 break;
1619 case MPI_EVENT_INTEGRATED_RAID:
1620 mptsas_send_raid_event(fw_event);
1621 break;
1622 case MPI_EVENT_IR2:
1623 mptsas_send_ir2_event(fw_event);
1624 break;
1625 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1626 mptbase_sas_persist_operation(ioc,
1627 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1628 mptsas_free_fw_event(ioc, fw_event);
1629 break;
1630 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
1631 mptsas_broadcast_primative_work(fw_event);
1632 break;
1633 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
1634 mptsas_send_expander_event(fw_event);
1635 break;
1636 case MPI_EVENT_SAS_PHY_LINK_STATUS:
1637 mptsas_send_link_status_event(fw_event);
1638 break;
1639 case MPI_EVENT_QUEUE_FULL:
1640 mptsas_handle_queue_full_event(fw_event);
1641 break;
1647 static int
1648 mptsas_slave_configure(struct scsi_device *sdev)
1650 struct Scsi_Host *host = sdev->host;
1651 MPT_SCSI_HOST *hd = shost_priv(host);
1652 MPT_ADAPTER *ioc = hd->ioc;
1653 VirtDevice *vdevice = sdev->hostdata;
1655 if (vdevice->vtarget->deleted) {
1656 sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n");
1657 vdevice->vtarget->deleted = 0;
1661 * RAID volumes placed beyond the last expected port.
1662 * Ignore sending sas mode pages in that case..
1664 if (sdev->channel == MPTSAS_RAID_CHANNEL) {
1665 mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev));
1666 goto out;
1669 sas_read_port_mode_page(sdev);
1671 mptsas_add_device_component_starget(ioc, scsi_target(sdev));
1673 out:
1674 return mptscsih_slave_configure(sdev);
1677 static int
1678 mptsas_target_alloc(struct scsi_target *starget)
1680 struct Scsi_Host *host = dev_to_shost(&starget->dev);
1681 MPT_SCSI_HOST *hd = shost_priv(host);
1682 VirtTarget *vtarget;
1683 u8 id, channel;
1684 struct sas_rphy *rphy;
1685 struct mptsas_portinfo *p;
1686 int i;
1687 MPT_ADAPTER *ioc = hd->ioc;
1689 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
1690 if (!vtarget)
1691 return -ENOMEM;
1693 vtarget->starget = starget;
1694 vtarget->ioc_id = ioc->id;
1695 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
1696 id = starget->id;
1697 channel = 0;
1700 * RAID volumes placed beyond the last expected port.
1702 if (starget->channel == MPTSAS_RAID_CHANNEL) {
1703 if (!ioc->raid_data.pIocPg2) {
1704 kfree(vtarget);
1705 return -ENXIO;
1707 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
1708 if (id == ioc->raid_data.pIocPg2->
1709 RaidVolume[i].VolumeID) {
1710 channel = ioc->raid_data.pIocPg2->
1711 RaidVolume[i].VolumeBus;
1714 vtarget->raidVolume = 1;
1715 goto out;
1718 rphy = dev_to_rphy(starget->dev.parent);
1719 mutex_lock(&ioc->sas_topology_mutex);
1720 list_for_each_entry(p, &ioc->sas_topology, list) {
1721 for (i = 0; i < p->num_phys; i++) {
1722 if (p->phy_info[i].attached.sas_address !=
1723 rphy->identify.sas_address)
1724 continue;
1725 id = p->phy_info[i].attached.id;
1726 channel = p->phy_info[i].attached.channel;
1727 mptsas_set_starget(&p->phy_info[i], starget);
1730 * Exposing hidden raid components
1732 if (mptscsih_is_phys_disk(ioc, channel, id)) {
1733 id = mptscsih_raid_id_to_num(ioc,
1734 channel, id);
1735 vtarget->tflags |=
1736 MPT_TARGET_FLAGS_RAID_COMPONENT;
1737 p->phy_info[i].attached.phys_disk_num = id;
1739 mutex_unlock(&ioc->sas_topology_mutex);
1740 goto out;
1743 mutex_unlock(&ioc->sas_topology_mutex);
1745 kfree(vtarget);
1746 return -ENXIO;
1748 out:
1749 vtarget->id = id;
1750 vtarget->channel = channel;
1751 starget->hostdata = vtarget;
1752 return 0;
1755 static void
1756 mptsas_target_destroy(struct scsi_target *starget)
1758 struct Scsi_Host *host = dev_to_shost(&starget->dev);
1759 MPT_SCSI_HOST *hd = shost_priv(host);
1760 struct sas_rphy *rphy;
1761 struct mptsas_portinfo *p;
1762 int i;
1763 MPT_ADAPTER *ioc = hd->ioc;
1764 VirtTarget *vtarget;
1766 if (!starget->hostdata)
1767 return;
1769 vtarget = starget->hostdata;
1771 mptsas_del_device_component_by_os(ioc, starget->channel,
1772 starget->id);
1775 if (starget->channel == MPTSAS_RAID_CHANNEL)
1776 goto out;
1778 rphy = dev_to_rphy(starget->dev.parent);
1779 list_for_each_entry(p, &ioc->sas_topology, list) {
1780 for (i = 0; i < p->num_phys; i++) {
1781 if (p->phy_info[i].attached.sas_address !=
1782 rphy->identify.sas_address)
1783 continue;
1785 starget_printk(KERN_INFO, starget, MYIOC_s_FMT
1786 "delete device: fw_channel %d, fw_id %d, phy %d, "
1787 "sas_addr 0x%llx\n", ioc->name,
1788 p->phy_info[i].attached.channel,
1789 p->phy_info[i].attached.id,
1790 p->phy_info[i].attached.phy_id, (unsigned long long)
1791 p->phy_info[i].attached.sas_address);
1793 mptsas_set_starget(&p->phy_info[i], NULL);
1797 out:
1798 vtarget->starget = NULL;
1799 kfree(starget->hostdata);
1800 starget->hostdata = NULL;
1804 static int
1805 mptsas_slave_alloc(struct scsi_device *sdev)
1807 struct Scsi_Host *host = sdev->host;
1808 MPT_SCSI_HOST *hd = shost_priv(host);
1809 struct sas_rphy *rphy;
1810 struct mptsas_portinfo *p;
1811 VirtDevice *vdevice;
1812 struct scsi_target *starget;
1813 int i;
1814 MPT_ADAPTER *ioc = hd->ioc;
1816 vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
1817 if (!vdevice) {
1818 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
1819 ioc->name, sizeof(VirtDevice));
1820 return -ENOMEM;
1822 starget = scsi_target(sdev);
1823 vdevice->vtarget = starget->hostdata;
1825 if (sdev->channel == MPTSAS_RAID_CHANNEL)
1826 goto out;
1828 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
1829 mutex_lock(&ioc->sas_topology_mutex);
1830 list_for_each_entry(p, &ioc->sas_topology, list) {
1831 for (i = 0; i < p->num_phys; i++) {
1832 if (p->phy_info[i].attached.sas_address !=
1833 rphy->identify.sas_address)
1834 continue;
1835 vdevice->lun = sdev->lun;
1837 * Exposing hidden raid components
1839 if (mptscsih_is_phys_disk(ioc,
1840 p->phy_info[i].attached.channel,
1841 p->phy_info[i].attached.id))
1842 sdev->no_uld_attach = 1;
1843 mutex_unlock(&ioc->sas_topology_mutex);
1844 goto out;
1847 mutex_unlock(&ioc->sas_topology_mutex);
1849 kfree(vdevice);
1850 return -ENXIO;
1852 out:
1853 vdevice->vtarget->num_luns++;
1854 sdev->hostdata = vdevice;
1855 return 0;
1858 static int
1859 mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1861 MPT_SCSI_HOST *hd;
1862 MPT_ADAPTER *ioc;
1863 VirtDevice *vdevice = SCpnt->device->hostdata;
1865 if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
1866 SCpnt->result = DID_NO_CONNECT << 16;
1867 done(SCpnt);
1868 return 0;
1871 hd = shost_priv(SCpnt->device->host);
1872 ioc = hd->ioc;
1874 if (ioc->sas_discovery_quiesce_io)
1875 return SCSI_MLQUEUE_HOST_BUSY;
1877 // scsi_print_command(SCpnt);
1879 return mptscsih_qcmd(SCpnt,done);
1883 static struct scsi_host_template mptsas_driver_template = {
1884 .module = THIS_MODULE,
1885 .proc_name = "mptsas",
1886 .proc_info = mptscsih_proc_info,
1887 .name = "MPT SPI Host",
1888 .info = mptscsih_info,
1889 .queuecommand = mptsas_qcmd,
1890 .target_alloc = mptsas_target_alloc,
1891 .slave_alloc = mptsas_slave_alloc,
1892 .slave_configure = mptsas_slave_configure,
1893 .target_destroy = mptsas_target_destroy,
1894 .slave_destroy = mptscsih_slave_destroy,
1895 .change_queue_depth = mptscsih_change_queue_depth,
1896 .eh_abort_handler = mptscsih_abort,
1897 .eh_device_reset_handler = mptscsih_dev_reset,
1898 .eh_bus_reset_handler = mptscsih_bus_reset,
1899 .eh_host_reset_handler = mptscsih_host_reset,
1900 .bios_param = mptscsih_bios_param,
1901 .can_queue = MPT_SAS_CAN_QUEUE,
1902 .this_id = -1,
1903 .sg_tablesize = MPT_SCSI_SG_DEPTH,
1904 .max_sectors = 8192,
1905 .cmd_per_lun = 7,
1906 .use_clustering = ENABLE_CLUSTERING,
1907 .shost_attrs = mptscsih_host_attrs,
1910 static int mptsas_get_linkerrors(struct sas_phy *phy)
1912 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1913 ConfigExtendedPageHeader_t hdr;
1914 CONFIGPARMS cfg;
1915 SasPhyPage1_t *buffer;
1916 dma_addr_t dma_handle;
1917 int error;
1919 /* FIXME: only have link errors on local phys */
1920 if (!scsi_is_sas_phy_local(phy))
1921 return -EINVAL;
1923 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
1924 hdr.ExtPageLength = 0;
1925 hdr.PageNumber = 1 /* page number 1*/;
1926 hdr.Reserved1 = 0;
1927 hdr.Reserved2 = 0;
1928 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1929 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1931 cfg.cfghdr.ehdr = &hdr;
1932 cfg.physAddr = -1;
1933 cfg.pageAddr = phy->identify.phy_identifier;
1934 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1935 cfg.dir = 0; /* read */
1936 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
1938 error = mpt_config(ioc, &cfg);
1939 if (error)
1940 return error;
1941 if (!hdr.ExtPageLength)
1942 return -ENXIO;
1944 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1945 &dma_handle);
1946 if (!buffer)
1947 return -ENOMEM;
1949 cfg.physAddr = dma_handle;
1950 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1952 error = mpt_config(ioc, &cfg);
1953 if (error)
1954 goto out_free_consistent;
1956 mptsas_print_phy_pg1(ioc, buffer);
1958 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
1959 phy->running_disparity_error_count =
1960 le32_to_cpu(buffer->RunningDisparityErrorCount);
1961 phy->loss_of_dword_sync_count =
1962 le32_to_cpu(buffer->LossDwordSynchCount);
1963 phy->phy_reset_problem_count =
1964 le32_to_cpu(buffer->PhyResetProblemCount);
1966 out_free_consistent:
1967 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1968 buffer, dma_handle);
1969 return error;
1972 static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
1973 MPT_FRAME_HDR *reply)
1975 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
1976 if (reply != NULL) {
1977 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID;
1978 memcpy(ioc->sas_mgmt.reply, reply,
1979 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
1982 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
1983 ioc->sas_mgmt.status &= ~MPT_MGMT_STATUS_PENDING;
1984 complete(&ioc->sas_mgmt.done);
1985 return 1;
1987 return 0;
1990 static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
1992 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1993 SasIoUnitControlRequest_t *req;
1994 SasIoUnitControlReply_t *reply;
1995 MPT_FRAME_HDR *mf;
1996 MPIHeader_t *hdr;
1997 unsigned long timeleft;
1998 int error = -ERESTARTSYS;
2000 /* FIXME: fusion doesn't allow non-local phy reset */
2001 if (!scsi_is_sas_phy_local(phy))
2002 return -EINVAL;
2004 /* not implemented for expanders */
2005 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
2006 return -ENXIO;
2008 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
2009 goto out;
2011 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2012 if (!mf) {
2013 error = -ENOMEM;
2014 goto out_unlock;
2017 hdr = (MPIHeader_t *) mf;
2018 req = (SasIoUnitControlRequest_t *)mf;
2019 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
2020 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
2021 req->MsgContext = hdr->MsgContext;
2022 req->Operation = hard_reset ?
2023 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
2024 req->PhyNum = phy->identify.phy_identifier;
2026 INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
2027 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2029 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
2030 10 * HZ);
2031 if (!timeleft) {
2032 /* On timeout reset the board */
2033 mpt_free_msg_frame(ioc, mf);
2034 mpt_HardResetHandler(ioc, CAN_SLEEP);
2035 error = -ETIMEDOUT;
2036 goto out_unlock;
2039 /* a reply frame is expected */
2040 if ((ioc->sas_mgmt.status &
2041 MPT_MGMT_STATUS_RF_VALID) == 0) {
2042 error = -ENXIO;
2043 goto out_unlock;
2046 /* process the completed Reply Message Frame */
2047 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
2048 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
2049 printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
2050 ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
2051 error = -ENXIO;
2052 goto out_unlock;
2055 error = 0;
2057 out_unlock:
2058 CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
2059 mutex_unlock(&ioc->sas_mgmt.mutex);
2060 out:
2061 return error;
2064 static int
2065 mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
2067 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2068 int i, error;
2069 struct mptsas_portinfo *p;
2070 struct mptsas_enclosure enclosure_info;
2071 u64 enclosure_handle;
2073 mutex_lock(&ioc->sas_topology_mutex);
2074 list_for_each_entry(p, &ioc->sas_topology, list) {
2075 for (i = 0; i < p->num_phys; i++) {
2076 if (p->phy_info[i].attached.sas_address ==
2077 rphy->identify.sas_address) {
2078 enclosure_handle = p->phy_info[i].
2079 attached.handle_enclosure;
2080 goto found_info;
2084 mutex_unlock(&ioc->sas_topology_mutex);
2085 return -ENXIO;
2087 found_info:
2088 mutex_unlock(&ioc->sas_topology_mutex);
2089 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
2090 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
2091 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
2092 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
2093 if (!error)
2094 *identifier = enclosure_info.enclosure_logical_id;
2095 return error;
2098 static int
2099 mptsas_get_bay_identifier(struct sas_rphy *rphy)
2101 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2102 struct mptsas_portinfo *p;
2103 int i, rc;
2105 mutex_lock(&ioc->sas_topology_mutex);
2106 list_for_each_entry(p, &ioc->sas_topology, list) {
2107 for (i = 0; i < p->num_phys; i++) {
2108 if (p->phy_info[i].attached.sas_address ==
2109 rphy->identify.sas_address) {
2110 rc = p->phy_info[i].attached.slot;
2111 goto out;
2115 rc = -ENXIO;
2116 out:
2117 mutex_unlock(&ioc->sas_topology_mutex);
2118 return rc;
2121 static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
2122 struct request *req)
2124 MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
2125 MPT_FRAME_HDR *mf;
2126 SmpPassthroughRequest_t *smpreq;
2127 struct request *rsp = req->next_rq;
2128 int ret;
2129 int flagsLength;
2130 unsigned long timeleft;
2131 char *psge;
2132 dma_addr_t dma_addr_in = 0;
2133 dma_addr_t dma_addr_out = 0;
2134 u64 sas_address = 0;
2136 if (!rsp) {
2137 printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
2138 ioc->name, __func__);
2139 return -EINVAL;
2142 /* do we need to support multiple segments? */
2143 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
2144 printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
2145 ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req),
2146 rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
2147 return -EINVAL;
2150 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
2151 if (ret)
2152 goto out;
2154 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2155 if (!mf) {
2156 ret = -ENOMEM;
2157 goto out_unlock;
2160 smpreq = (SmpPassthroughRequest_t *)mf;
2161 memset(smpreq, 0, sizeof(*smpreq));
2163 smpreq->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
2164 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
2166 if (rphy)
2167 sas_address = rphy->identify.sas_address;
2168 else {
2169 struct mptsas_portinfo *port_info;
2171 mutex_lock(&ioc->sas_topology_mutex);
2172 port_info = ioc->hba_port_info;
2173 if (port_info && port_info->phy_info)
2174 sas_address =
2175 port_info->phy_info[0].phy->identify.sas_address;
2176 mutex_unlock(&ioc->sas_topology_mutex);
2179 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
2181 psge = (char *)
2182 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
2184 /* request */
2185 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2186 MPI_SGE_FLAGS_END_OF_BUFFER |
2187 MPI_SGE_FLAGS_DIRECTION)
2188 << MPI_SGE_FLAGS_SHIFT;
2189 flagsLength |= (blk_rq_bytes(req) - 4);
2191 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
2192 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
2193 if (!dma_addr_out)
2194 goto put_mf;
2195 ioc->add_sge(psge, flagsLength, dma_addr_out);
2196 psge += ioc->SGE_size;
2198 /* response */
2199 flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2200 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2201 MPI_SGE_FLAGS_IOC_TO_HOST |
2202 MPI_SGE_FLAGS_END_OF_BUFFER;
2204 flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2205 flagsLength |= blk_rq_bytes(rsp) + 4;
2206 dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
2207 blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
2208 if (!dma_addr_in)
2209 goto unmap;
2210 ioc->add_sge(psge, flagsLength, dma_addr_in);
2212 INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
2213 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2215 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
2216 if (!timeleft) {
2217 printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__);
2218 /* On timeout reset the board */
2219 mpt_HardResetHandler(ioc, CAN_SLEEP);
2220 ret = -ETIMEDOUT;
2221 goto unmap;
2223 mf = NULL;
2225 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
2226 SmpPassthroughReply_t *smprep;
2228 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
2229 memcpy(req->sense, smprep, sizeof(*smprep));
2230 req->sense_len = sizeof(*smprep);
2231 req->resid_len = 0;
2232 rsp->resid_len -= smprep->ResponseDataLength;
2233 } else {
2234 printk(MYIOC_s_ERR_FMT
2235 "%s: smp passthru reply failed to be returned\n",
2236 ioc->name, __func__);
2237 ret = -ENXIO;
2239 unmap:
2240 if (dma_addr_out)
2241 pci_unmap_single(ioc->pcidev, dma_addr_out, blk_rq_bytes(req),
2242 PCI_DMA_BIDIRECTIONAL);
2243 if (dma_addr_in)
2244 pci_unmap_single(ioc->pcidev, dma_addr_in, blk_rq_bytes(rsp),
2245 PCI_DMA_BIDIRECTIONAL);
2246 put_mf:
2247 if (mf)
2248 mpt_free_msg_frame(ioc, mf);
2249 out_unlock:
2250 CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
2251 mutex_unlock(&ioc->sas_mgmt.mutex);
2252 out:
2253 return ret;
2256 static struct sas_function_template mptsas_transport_functions = {
2257 .get_linkerrors = mptsas_get_linkerrors,
2258 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
2259 .get_bay_identifier = mptsas_get_bay_identifier,
2260 .phy_reset = mptsas_phy_reset,
2261 .smp_handler = mptsas_smp_handler,
2264 static struct scsi_transport_template *mptsas_transport_template;
2266 static int
2267 mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
2269 ConfigExtendedPageHeader_t hdr;
2270 CONFIGPARMS cfg;
2271 SasIOUnitPage0_t *buffer;
2272 dma_addr_t dma_handle;
2273 int error, i;
2275 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
2276 hdr.ExtPageLength = 0;
2277 hdr.PageNumber = 0;
2278 hdr.Reserved1 = 0;
2279 hdr.Reserved2 = 0;
2280 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2281 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2283 cfg.cfghdr.ehdr = &hdr;
2284 cfg.physAddr = -1;
2285 cfg.pageAddr = 0;
2286 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2287 cfg.dir = 0; /* read */
2288 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2290 error = mpt_config(ioc, &cfg);
2291 if (error)
2292 goto out;
2293 if (!hdr.ExtPageLength) {
2294 error = -ENXIO;
2295 goto out;
2298 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2299 &dma_handle);
2300 if (!buffer) {
2301 error = -ENOMEM;
2302 goto out;
2305 cfg.physAddr = dma_handle;
2306 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2308 error = mpt_config(ioc, &cfg);
2309 if (error)
2310 goto out_free_consistent;
2312 port_info->num_phys = buffer->NumPhys;
2313 port_info->phy_info = kcalloc(port_info->num_phys,
2314 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
2315 if (!port_info->phy_info) {
2316 error = -ENOMEM;
2317 goto out_free_consistent;
2320 ioc->nvdata_version_persistent =
2321 le16_to_cpu(buffer->NvdataVersionPersistent);
2322 ioc->nvdata_version_default =
2323 le16_to_cpu(buffer->NvdataVersionDefault);
2325 for (i = 0; i < port_info->num_phys; i++) {
2326 mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
2327 port_info->phy_info[i].phy_id = i;
2328 port_info->phy_info[i].port_id =
2329 buffer->PhyData[i].Port;
2330 port_info->phy_info[i].negotiated_link_rate =
2331 buffer->PhyData[i].NegotiatedLinkRate;
2332 port_info->phy_info[i].portinfo = port_info;
2333 port_info->phy_info[i].handle =
2334 le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
2337 out_free_consistent:
2338 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2339 buffer, dma_handle);
2340 out:
2341 return error;
2344 static int
2345 mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
2347 ConfigExtendedPageHeader_t hdr;
2348 CONFIGPARMS cfg;
2349 SasIOUnitPage1_t *buffer;
2350 dma_addr_t dma_handle;
2351 int error;
2352 u16 device_missing_delay;
2354 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
2355 memset(&cfg, 0, sizeof(CONFIGPARMS));
2357 cfg.cfghdr.ehdr = &hdr;
2358 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2359 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2360 cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2361 cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2362 cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
2363 cfg.cfghdr.ehdr->PageNumber = 1;
2365 error = mpt_config(ioc, &cfg);
2366 if (error)
2367 goto out;
2368 if (!hdr.ExtPageLength) {
2369 error = -ENXIO;
2370 goto out;
2373 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2374 &dma_handle);
2375 if (!buffer) {
2376 error = -ENOMEM;
2377 goto out;
2380 cfg.physAddr = dma_handle;
2381 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2383 error = mpt_config(ioc, &cfg);
2384 if (error)
2385 goto out_free_consistent;
2387 ioc->io_missing_delay =
2388 le16_to_cpu(buffer->IODeviceMissingDelay);
2389 device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay);
2390 ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
2391 (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
2392 device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
2394 out_free_consistent:
2395 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2396 buffer, dma_handle);
2397 out:
2398 return error;
2401 static int
2402 mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2403 u32 form, u32 form_specific)
2405 ConfigExtendedPageHeader_t hdr;
2406 CONFIGPARMS cfg;
2407 SasPhyPage0_t *buffer;
2408 dma_addr_t dma_handle;
2409 int error;
2411 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
2412 hdr.ExtPageLength = 0;
2413 hdr.PageNumber = 0;
2414 hdr.Reserved1 = 0;
2415 hdr.Reserved2 = 0;
2416 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2417 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
2419 cfg.cfghdr.ehdr = &hdr;
2420 cfg.dir = 0; /* read */
2421 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2423 /* Get Phy Pg 0 for each Phy. */
2424 cfg.physAddr = -1;
2425 cfg.pageAddr = form + form_specific;
2426 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2428 error = mpt_config(ioc, &cfg);
2429 if (error)
2430 goto out;
2432 if (!hdr.ExtPageLength) {
2433 error = -ENXIO;
2434 goto out;
2437 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2438 &dma_handle);
2439 if (!buffer) {
2440 error = -ENOMEM;
2441 goto out;
2444 cfg.physAddr = dma_handle;
2445 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2447 error = mpt_config(ioc, &cfg);
2448 if (error)
2449 goto out_free_consistent;
2451 mptsas_print_phy_pg0(ioc, buffer);
2453 phy_info->hw_link_rate = buffer->HwLinkRate;
2454 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2455 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2456 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2458 out_free_consistent:
2459 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2460 buffer, dma_handle);
2461 out:
2462 return error;
2465 static int
2466 mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
2467 u32 form, u32 form_specific)
2469 ConfigExtendedPageHeader_t hdr;
2470 CONFIGPARMS cfg;
2471 SasDevicePage0_t *buffer;
2472 dma_addr_t dma_handle;
2473 __le64 sas_address;
2474 int error=0;
2476 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
2477 hdr.ExtPageLength = 0;
2478 hdr.PageNumber = 0;
2479 hdr.Reserved1 = 0;
2480 hdr.Reserved2 = 0;
2481 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2482 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
2484 cfg.cfghdr.ehdr = &hdr;
2485 cfg.pageAddr = form + form_specific;
2486 cfg.physAddr = -1;
2487 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2488 cfg.dir = 0; /* read */
2489 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2491 memset(device_info, 0, sizeof(struct mptsas_devinfo));
2492 error = mpt_config(ioc, &cfg);
2493 if (error)
2494 goto out;
2495 if (!hdr.ExtPageLength) {
2496 error = -ENXIO;
2497 goto out;
2500 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2501 &dma_handle);
2502 if (!buffer) {
2503 error = -ENOMEM;
2504 goto out;
2507 cfg.physAddr = dma_handle;
2508 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2510 error = mpt_config(ioc, &cfg);
2511 if (error)
2512 goto out_free_consistent;
2514 mptsas_print_device_pg0(ioc, buffer);
2516 memset(device_info, 0, sizeof(struct mptsas_devinfo));
2517 device_info->handle = le16_to_cpu(buffer->DevHandle);
2518 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
2519 device_info->handle_enclosure =
2520 le16_to_cpu(buffer->EnclosureHandle);
2521 device_info->slot = le16_to_cpu(buffer->Slot);
2522 device_info->phy_id = buffer->PhyNum;
2523 device_info->port_id = buffer->PhysicalPort;
2524 device_info->id = buffer->TargetID;
2525 device_info->phys_disk_num = ~0;
2526 device_info->channel = buffer->Bus;
2527 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2528 device_info->sas_address = le64_to_cpu(sas_address);
2529 device_info->device_info =
2530 le32_to_cpu(buffer->DeviceInfo);
2532 out_free_consistent:
2533 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2534 buffer, dma_handle);
2535 out:
2536 return error;
2539 static int
2540 mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
2541 u32 form, u32 form_specific)
2543 ConfigExtendedPageHeader_t hdr;
2544 CONFIGPARMS cfg;
2545 SasExpanderPage0_t *buffer;
2546 dma_addr_t dma_handle;
2547 int i, error;
2548 __le64 sas_address;
2550 memset(port_info, 0, sizeof(struct mptsas_portinfo));
2551 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
2552 hdr.ExtPageLength = 0;
2553 hdr.PageNumber = 0;
2554 hdr.Reserved1 = 0;
2555 hdr.Reserved2 = 0;
2556 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2557 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2559 cfg.cfghdr.ehdr = &hdr;
2560 cfg.physAddr = -1;
2561 cfg.pageAddr = form + form_specific;
2562 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2563 cfg.dir = 0; /* read */
2564 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2566 memset(port_info, 0, sizeof(struct mptsas_portinfo));
2567 error = mpt_config(ioc, &cfg);
2568 if (error)
2569 goto out;
2571 if (!hdr.ExtPageLength) {
2572 error = -ENXIO;
2573 goto out;
2576 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2577 &dma_handle);
2578 if (!buffer) {
2579 error = -ENOMEM;
2580 goto out;
2583 cfg.physAddr = dma_handle;
2584 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2586 error = mpt_config(ioc, &cfg);
2587 if (error)
2588 goto out_free_consistent;
2590 if (!buffer->NumPhys) {
2591 error = -ENODEV;
2592 goto out_free_consistent;
2595 /* save config data */
2596 port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1;
2597 port_info->phy_info = kcalloc(port_info->num_phys,
2598 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
2599 if (!port_info->phy_info) {
2600 error = -ENOMEM;
2601 goto out_free_consistent;
2604 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2605 for (i = 0; i < port_info->num_phys; i++) {
2606 port_info->phy_info[i].portinfo = port_info;
2607 port_info->phy_info[i].handle =
2608 le16_to_cpu(buffer->DevHandle);
2609 port_info->phy_info[i].identify.sas_address =
2610 le64_to_cpu(sas_address);
2611 port_info->phy_info[i].identify.handle_parent =
2612 le16_to_cpu(buffer->ParentDevHandle);
2615 out_free_consistent:
2616 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2617 buffer, dma_handle);
2618 out:
2619 return error;
2622 static int
2623 mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2624 u32 form, u32 form_specific)
2626 ConfigExtendedPageHeader_t hdr;
2627 CONFIGPARMS cfg;
2628 SasExpanderPage1_t *buffer;
2629 dma_addr_t dma_handle;
2630 int error=0;
2632 hdr.PageVersion = MPI_SASEXPANDER1_PAGEVERSION;
2633 hdr.ExtPageLength = 0;
2634 hdr.PageNumber = 1;
2635 hdr.Reserved1 = 0;
2636 hdr.Reserved2 = 0;
2637 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2638 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2640 cfg.cfghdr.ehdr = &hdr;
2641 cfg.physAddr = -1;
2642 cfg.pageAddr = form + form_specific;
2643 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2644 cfg.dir = 0; /* read */
2645 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
2647 error = mpt_config(ioc, &cfg);
2648 if (error)
2649 goto out;
2651 if (!hdr.ExtPageLength) {
2652 error = -ENXIO;
2653 goto out;
2656 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2657 &dma_handle);
2658 if (!buffer) {
2659 error = -ENOMEM;
2660 goto out;
2663 cfg.physAddr = dma_handle;
2664 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2666 error = mpt_config(ioc, &cfg);
2668 if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
2669 error = -ENODEV;
2670 goto out;
2673 if (error)
2674 goto out_free_consistent;
2677 mptsas_print_expander_pg1(ioc, buffer);
2679 /* save config data */
2680 phy_info->phy_id = buffer->PhyIdentifier;
2681 phy_info->port_id = buffer->PhysicalPort;
2682 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
2683 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2684 phy_info->hw_link_rate = buffer->HwLinkRate;
2685 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2686 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2688 out_free_consistent:
2689 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2690 buffer, dma_handle);
2691 out:
2692 return error;
2695 static void
2696 mptsas_parse_device_info(struct sas_identify *identify,
2697 struct mptsas_devinfo *device_info)
2699 u16 protocols;
2701 identify->sas_address = device_info->sas_address;
2702 identify->phy_identifier = device_info->phy_id;
2705 * Fill in Phy Initiator Port Protocol.
2706 * Bits 6:3, more than one bit can be set, fall through cases.
2708 protocols = device_info->device_info & 0x78;
2709 identify->initiator_port_protocols = 0;
2710 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
2711 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
2712 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
2713 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
2714 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
2715 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
2716 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
2717 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
2720 * Fill in Phy Target Port Protocol.
2721 * Bits 10:7, more than one bit can be set, fall through cases.
2723 protocols = device_info->device_info & 0x780;
2724 identify->target_port_protocols = 0;
2725 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2726 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
2727 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
2728 identify->target_port_protocols |= SAS_PROTOCOL_STP;
2729 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
2730 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
2731 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2732 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
2735 * Fill in Attached device type.
2737 switch (device_info->device_info &
2738 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
2739 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
2740 identify->device_type = SAS_PHY_UNUSED;
2741 break;
2742 case MPI_SAS_DEVICE_INFO_END_DEVICE:
2743 identify->device_type = SAS_END_DEVICE;
2744 break;
2745 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
2746 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
2747 break;
2748 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
2749 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
2750 break;
2754 static int mptsas_probe_one_phy(struct device *dev,
2755 struct mptsas_phyinfo *phy_info, int index, int local)
2757 MPT_ADAPTER *ioc;
2758 struct sas_phy *phy;
2759 struct sas_port *port;
2760 int error = 0;
2762 if (!dev) {
2763 error = -ENODEV;
2764 goto out;
2767 if (!phy_info->phy) {
2768 phy = sas_phy_alloc(dev, index);
2769 if (!phy) {
2770 error = -ENOMEM;
2771 goto out;
2773 } else
2774 phy = phy_info->phy;
2776 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
2779 * Set Negotiated link rate.
2781 switch (phy_info->negotiated_link_rate) {
2782 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
2783 phy->negotiated_linkrate = SAS_PHY_DISABLED;
2784 break;
2785 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
2786 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
2787 break;
2788 case MPI_SAS_IOUNIT0_RATE_1_5:
2789 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
2790 break;
2791 case MPI_SAS_IOUNIT0_RATE_3_0:
2792 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
2793 break;
2794 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
2795 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
2796 default:
2797 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
2798 break;
2802 * Set Max hardware link rate.
2804 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
2805 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
2806 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
2807 break;
2808 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
2809 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
2810 break;
2811 default:
2812 break;
2816 * Set Max programmed link rate.
2818 switch (phy_info->programmed_link_rate &
2819 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
2820 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
2821 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
2822 break;
2823 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
2824 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
2825 break;
2826 default:
2827 break;
2831 * Set Min hardware link rate.
2833 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
2834 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
2835 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
2836 break;
2837 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
2838 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
2839 break;
2840 default:
2841 break;
2845 * Set Min programmed link rate.
2847 switch (phy_info->programmed_link_rate &
2848 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
2849 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
2850 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
2851 break;
2852 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
2853 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
2854 break;
2855 default:
2856 break;
2859 if (!phy_info->phy) {
2861 error = sas_phy_add(phy);
2862 if (error) {
2863 sas_phy_free(phy);
2864 goto out;
2866 phy_info->phy = phy;
2869 if (!phy_info->attached.handle ||
2870 !phy_info->port_details)
2871 goto out;
2873 port = mptsas_get_port(phy_info);
2874 ioc = phy_to_ioc(phy_info->phy);
2876 if (phy_info->sas_port_add_phy) {
2878 if (!port) {
2879 port = sas_port_alloc_num(dev);
2880 if (!port) {
2881 error = -ENOMEM;
2882 goto out;
2884 error = sas_port_add(port);
2885 if (error) {
2886 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2887 "%s: exit at line=%d\n", ioc->name,
2888 __func__, __LINE__));
2889 goto out;
2891 mptsas_set_port(ioc, phy_info, port);
2892 devtprintk(ioc, dev_printk(KERN_DEBUG, &port->dev,
2893 MYIOC_s_FMT "add port %d, sas_addr (0x%llx)\n",
2894 ioc->name, port->port_identifier,
2895 (unsigned long long)phy_info->
2896 attached.sas_address));
2898 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2899 "sas_port_add_phy: phy_id=%d\n",
2900 ioc->name, phy_info->phy_id));
2901 sas_port_add_phy(port, phy_info->phy);
2902 phy_info->sas_port_add_phy = 0;
2903 devtprintk(ioc, dev_printk(KERN_DEBUG, &phy_info->phy->dev,
2904 MYIOC_s_FMT "add phy %d, phy-obj (0x%p)\n", ioc->name,
2905 phy_info->phy_id, phy_info->phy));
2907 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
2909 struct sas_rphy *rphy;
2910 struct device *parent;
2911 struct sas_identify identify;
2913 parent = dev->parent->parent;
2915 * Let the hotplug_work thread handle processing
2916 * the adding/removing of devices that occur
2917 * after start of day.
2919 if (mptsas_is_end_device(&phy_info->attached) &&
2920 phy_info->attached.handle_parent) {
2921 goto out;
2924 mptsas_parse_device_info(&identify, &phy_info->attached);
2925 if (scsi_is_host_device(parent)) {
2926 struct mptsas_portinfo *port_info;
2927 int i;
2929 port_info = ioc->hba_port_info;
2931 for (i = 0; i < port_info->num_phys; i++)
2932 if (port_info->phy_info[i].identify.sas_address ==
2933 identify.sas_address) {
2934 sas_port_mark_backlink(port);
2935 goto out;
2938 } else if (scsi_is_sas_rphy(parent)) {
2939 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
2940 if (identify.sas_address ==
2941 parent_rphy->identify.sas_address) {
2942 sas_port_mark_backlink(port);
2943 goto out;
2947 switch (identify.device_type) {
2948 case SAS_END_DEVICE:
2949 rphy = sas_end_device_alloc(port);
2950 break;
2951 case SAS_EDGE_EXPANDER_DEVICE:
2952 case SAS_FANOUT_EXPANDER_DEVICE:
2953 rphy = sas_expander_alloc(port, identify.device_type);
2954 break;
2955 default:
2956 rphy = NULL;
2957 break;
2959 if (!rphy) {
2960 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2961 "%s: exit at line=%d\n", ioc->name,
2962 __func__, __LINE__));
2963 goto out;
2966 rphy->identify = identify;
2967 error = sas_rphy_add(rphy);
2968 if (error) {
2969 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
2970 "%s: exit at line=%d\n", ioc->name,
2971 __func__, __LINE__));
2972 sas_rphy_free(rphy);
2973 goto out;
2975 mptsas_set_rphy(ioc, phy_info, rphy);
2978 out:
2979 return error;
2982 static int
2983 mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
2985 struct mptsas_portinfo *port_info, *hba;
2986 int error = -ENOMEM, i;
2988 hba = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
2989 if (! hba)
2990 goto out;
2992 error = mptsas_sas_io_unit_pg0(ioc, hba);
2993 if (error)
2994 goto out_free_port_info;
2996 mptsas_sas_io_unit_pg1(ioc);
2997 mutex_lock(&ioc->sas_topology_mutex);
2998 port_info = ioc->hba_port_info;
2999 if (!port_info) {
3000 ioc->hba_port_info = port_info = hba;
3001 ioc->hba_port_num_phy = port_info->num_phys;
3002 list_add_tail(&port_info->list, &ioc->sas_topology);
3003 } else {
3004 for (i = 0; i < hba->num_phys; i++) {
3005 port_info->phy_info[i].negotiated_link_rate =
3006 hba->phy_info[i].negotiated_link_rate;
3007 port_info->phy_info[i].handle =
3008 hba->phy_info[i].handle;
3009 port_info->phy_info[i].port_id =
3010 hba->phy_info[i].port_id;
3012 kfree(hba->phy_info);
3013 kfree(hba);
3014 hba = NULL;
3016 mutex_unlock(&ioc->sas_topology_mutex);
3017 #if defined(CPQ_CIM)
3018 ioc->num_ports = port_info->num_phys;
3019 #endif
3020 for (i = 0; i < port_info->num_phys; i++) {
3021 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
3022 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
3023 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
3024 port_info->phy_info[i].identify.handle =
3025 port_info->phy_info[i].handle;
3026 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
3027 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3028 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3029 port_info->phy_info[i].identify.handle);
3030 if (!ioc->hba_port_sas_addr)
3031 ioc->hba_port_sas_addr =
3032 port_info->phy_info[i].identify.sas_address;
3033 port_info->phy_info[i].identify.phy_id =
3034 port_info->phy_info[i].phy_id = i;
3035 if (port_info->phy_info[i].attached.handle)
3036 mptsas_sas_device_pg0(ioc,
3037 &port_info->phy_info[i].attached,
3038 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3039 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3040 port_info->phy_info[i].attached.handle);
3043 mptsas_setup_wide_ports(ioc, port_info);
3045 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
3046 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
3047 &port_info->phy_info[i], ioc->sas_index, 1);
3049 return 0;
3051 out_free_port_info:
3052 kfree(hba);
3053 out:
3054 return error;
3057 static void
3058 mptsas_expander_refresh(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
3060 struct mptsas_portinfo *parent;
3061 struct device *parent_dev;
3062 struct sas_rphy *rphy;
3063 int i;
3064 u64 sas_address; /* expander sas address */
3065 u32 handle;
3067 handle = port_info->phy_info[0].handle;
3068 sas_address = port_info->phy_info[0].identify.sas_address;
3069 for (i = 0; i < port_info->num_phys; i++) {
3070 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
3071 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
3072 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + handle);
3074 mptsas_sas_device_pg0(ioc,
3075 &port_info->phy_info[i].identify,
3076 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3077 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3078 port_info->phy_info[i].identify.handle);
3079 port_info->phy_info[i].identify.phy_id =
3080 port_info->phy_info[i].phy_id;
3082 if (port_info->phy_info[i].attached.handle) {
3083 mptsas_sas_device_pg0(ioc,
3084 &port_info->phy_info[i].attached,
3085 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3086 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3087 port_info->phy_info[i].attached.handle);
3088 port_info->phy_info[i].attached.phy_id =
3089 port_info->phy_info[i].phy_id;
3093 mutex_lock(&ioc->sas_topology_mutex);
3094 parent = mptsas_find_portinfo_by_handle(ioc,
3095 port_info->phy_info[0].identify.handle_parent);
3096 if (!parent) {
3097 mutex_unlock(&ioc->sas_topology_mutex);
3098 return;
3100 for (i = 0, parent_dev = NULL; i < parent->num_phys && !parent_dev;
3101 i++) {
3102 if (parent->phy_info[i].attached.sas_address == sas_address) {
3103 rphy = mptsas_get_rphy(&parent->phy_info[i]);
3104 parent_dev = &rphy->dev;
3107 mutex_unlock(&ioc->sas_topology_mutex);
3109 mptsas_setup_wide_ports(ioc, port_info);
3110 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
3111 mptsas_probe_one_phy(parent_dev, &port_info->phy_info[i],
3112 ioc->sas_index, 0);
3115 static void
3116 mptsas_expander_event_add(MPT_ADAPTER *ioc,
3117 MpiEventDataSasExpanderStatusChange_t *expander_data)
3119 struct mptsas_portinfo *port_info;
3120 int i;
3121 __le64 sas_address;
3123 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3124 if (!port_info)
3125 BUG();
3126 port_info->num_phys = (expander_data->NumPhys) ?
3127 expander_data->NumPhys : 1;
3128 port_info->phy_info = kcalloc(port_info->num_phys,
3129 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
3130 if (!port_info->phy_info)
3131 BUG();
3132 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3133 for (i = 0; i < port_info->num_phys; i++) {
3134 port_info->phy_info[i].portinfo = port_info;
3135 port_info->phy_info[i].handle =
3136 le16_to_cpu(expander_data->DevHandle);
3137 port_info->phy_info[i].identify.sas_address =
3138 le64_to_cpu(sas_address);
3139 port_info->phy_info[i].identify.handle_parent =
3140 le16_to_cpu(expander_data->ParentDevHandle);
3143 mutex_lock(&ioc->sas_topology_mutex);
3144 list_add_tail(&port_info->list, &ioc->sas_topology);
3145 mutex_unlock(&ioc->sas_topology_mutex);
3147 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3148 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3149 (unsigned long long)sas_address);
3151 mptsas_expander_refresh(ioc, port_info);
3155 * mptsas_delete_expander_siblings - remove siblings attached to expander
3156 * @ioc: Pointer to MPT_ADAPTER structure
3157 * @parent: the parent port_info object
3158 * @expander: the expander port_info object
3160 static void
3161 mptsas_delete_expander_siblings(MPT_ADAPTER *ioc, struct mptsas_portinfo
3162 *parent, struct mptsas_portinfo *expander)
3164 struct mptsas_phyinfo *phy_info;
3165 struct mptsas_portinfo *port_info;
3166 struct sas_rphy *rphy;
3167 int i;
3169 phy_info = expander->phy_info;
3170 for (i = 0; i < expander->num_phys; i++, phy_info++) {
3171 rphy = mptsas_get_rphy(phy_info);
3172 if (!rphy)
3173 continue;
3174 if (rphy->identify.device_type == SAS_END_DEVICE)
3175 mptsas_del_end_device(ioc, phy_info);
3178 phy_info = expander->phy_info;
3179 for (i = 0; i < expander->num_phys; i++, phy_info++) {
3180 rphy = mptsas_get_rphy(phy_info);
3181 if (!rphy)
3182 continue;
3183 if (rphy->identify.device_type ==
3184 MPI_SAS_DEVICE_INFO_EDGE_EXPANDER ||
3185 rphy->identify.device_type ==
3186 MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
3187 port_info = mptsas_find_portinfo_by_sas_address(ioc,
3188 rphy->identify.sas_address);
3189 if (!port_info)
3190 continue;
3191 if (port_info == parent) /* backlink rphy */
3192 continue;
3194 Delete this expander even if the expdevpage is exists
3195 because the parent expander is already deleted
3197 mptsas_expander_delete(ioc, port_info, 1);
3204 * mptsas_expander_delete - remove this expander
3205 * @ioc: Pointer to MPT_ADAPTER structure
3206 * @port_info: expander port_info struct
3207 * @force: Flag to forcefully delete the expander
3211 static void mptsas_expander_delete(MPT_ADAPTER *ioc,
3212 struct mptsas_portinfo *port_info, u8 force)
3215 struct mptsas_portinfo *parent;
3216 int i;
3217 u64 expander_sas_address;
3218 struct mptsas_phyinfo *phy_info;
3219 struct mptsas_portinfo buffer;
3220 struct mptsas_portinfo_details *port_details;
3221 struct sas_port *port;
3223 if (!port_info)
3224 return;
3226 /* see if expander is still there before deleting */
3227 mptsas_sas_expander_pg0(ioc, &buffer,
3228 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3229 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
3230 port_info->phy_info[0].identify.handle);
3232 if (buffer.num_phys) {
3233 kfree(buffer.phy_info);
3234 if (!force)
3235 return;
3240 * Obtain the port_info instance to the parent port
3242 port_details = NULL;
3243 expander_sas_address =
3244 port_info->phy_info[0].identify.sas_address;
3245 parent = mptsas_find_portinfo_by_handle(ioc,
3246 port_info->phy_info[0].identify.handle_parent);
3247 mptsas_delete_expander_siblings(ioc, parent, port_info);
3248 if (!parent)
3249 goto out;
3252 * Delete rphys in the parent that point
3253 * to this expander.
3255 phy_info = parent->phy_info;
3256 port = NULL;
3257 for (i = 0; i < parent->num_phys; i++, phy_info++) {
3258 if (!phy_info->phy)
3259 continue;
3260 if (phy_info->attached.sas_address !=
3261 expander_sas_address)
3262 continue;
3263 if (!port) {
3264 port = mptsas_get_port(phy_info);
3265 port_details = phy_info->port_details;
3267 dev_printk(KERN_DEBUG, &phy_info->phy->dev,
3268 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
3269 phy_info->phy_id, phy_info->phy);
3270 sas_port_delete_phy(port, phy_info->phy);
3272 if (port) {
3273 dev_printk(KERN_DEBUG, &port->dev,
3274 MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n",
3275 ioc->name, port->port_identifier,
3276 (unsigned long long)expander_sas_address);
3277 sas_port_delete(port);
3278 mptsas_port_delete(ioc, port_details);
3280 out:
3282 printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, "
3283 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3284 (unsigned long long)expander_sas_address);
3287 * free link
3289 list_del(&port_info->list);
3290 kfree(port_info->phy_info);
3291 kfree(port_info);
3296 * mptsas_send_expander_event - expanders events
3297 * @ioc: Pointer to MPT_ADAPTER structure
3298 * @expander_data: event data
3301 * This function handles adding, removing, and refreshing
3302 * device handles within the expander objects.
3304 static void
3305 mptsas_send_expander_event(struct fw_event_work *fw_event)
3307 MPT_ADAPTER *ioc;
3308 MpiEventDataSasExpanderStatusChange_t *expander_data;
3309 struct mptsas_portinfo *port_info;
3310 __le64 sas_address;
3311 int i;
3313 ioc = fw_event->ioc;
3314 expander_data = (MpiEventDataSasExpanderStatusChange_t *)
3315 fw_event->event_data;
3316 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3317 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3319 if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) {
3320 if (port_info) {
3321 for (i = 0; i < port_info->num_phys; i++) {
3322 port_info->phy_info[i].portinfo = port_info;
3323 port_info->phy_info[i].handle =
3324 le16_to_cpu(expander_data->DevHandle);
3325 port_info->phy_info[i].identify.sas_address =
3326 le64_to_cpu(sas_address);
3327 port_info->phy_info[i].identify.handle_parent =
3328 le16_to_cpu(expander_data->ParentDevHandle);
3330 mptsas_expander_refresh(ioc, port_info);
3331 } else if (!port_info && expander_data->NumPhys)
3332 mptsas_expander_event_add(ioc, expander_data);
3333 } else if (expander_data->ReasonCode ==
3334 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING)
3335 mptsas_expander_delete(ioc, port_info, 0);
3337 mptsas_free_fw_event(ioc, fw_event);
3342 * mptsas_expander_add -
3343 * @ioc: Pointer to MPT_ADAPTER structure
3344 * @handle:
3347 struct mptsas_portinfo *
3348 mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
3350 struct mptsas_portinfo buffer, *port_info;
3351 int i;
3353 if ((mptsas_sas_expander_pg0(ioc, &buffer,
3354 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3355 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)))
3356 return NULL;
3358 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_ATOMIC);
3359 if (!port_info) {
3360 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3361 "%s: exit at line=%d\n", ioc->name,
3362 __func__, __LINE__));
3363 return NULL;
3365 port_info->num_phys = buffer.num_phys;
3366 port_info->phy_info = buffer.phy_info;
3367 for (i = 0; i < port_info->num_phys; i++)
3368 port_info->phy_info[i].portinfo = port_info;
3369 mutex_lock(&ioc->sas_topology_mutex);
3370 list_add_tail(&port_info->list, &ioc->sas_topology);
3371 mutex_unlock(&ioc->sas_topology_mutex);
3372 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3373 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3374 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3375 mptsas_expander_refresh(ioc, port_info);
3376 return port_info;
3379 static void
3380 mptsas_send_link_status_event(struct fw_event_work *fw_event)
3382 MPT_ADAPTER *ioc;
3383 MpiEventDataSasPhyLinkStatus_t *link_data;
3384 struct mptsas_portinfo *port_info;
3385 struct mptsas_phyinfo *phy_info = NULL;
3386 __le64 sas_address;
3387 u8 phy_num;
3388 u8 link_rate;
3390 ioc = fw_event->ioc;
3391 link_data = (MpiEventDataSasPhyLinkStatus_t *)fw_event->event_data;
3393 memcpy(&sas_address, &link_data->SASAddress, sizeof(__le64));
3394 sas_address = le64_to_cpu(sas_address);
3395 link_rate = link_data->LinkRates >> 4;
3396 phy_num = link_data->PhyNum;
3398 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3399 if (port_info) {
3400 phy_info = &port_info->phy_info[phy_num];
3401 if (phy_info)
3402 phy_info->negotiated_link_rate = link_rate;
3405 if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
3406 link_rate == MPI_SAS_IOUNIT0_RATE_3_0) {
3408 if (!port_info) {
3409 if (ioc->old_sas_discovery_protocal) {
3410 port_info = mptsas_expander_add(ioc,
3411 le16_to_cpu(link_data->DevHandle));
3412 if (port_info)
3413 goto out;
3415 goto out;
3418 if (port_info == ioc->hba_port_info)
3419 mptsas_probe_hba_phys(ioc);
3420 else
3421 mptsas_expander_refresh(ioc, port_info);
3422 } else if (phy_info && phy_info->phy) {
3423 if (link_rate == MPI_SAS_IOUNIT0_RATE_PHY_DISABLED)
3424 phy_info->phy->negotiated_linkrate =
3425 SAS_PHY_DISABLED;
3426 else if (link_rate ==
3427 MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
3428 phy_info->phy->negotiated_linkrate =
3429 SAS_LINK_RATE_FAILED;
3430 else
3431 phy_info->phy->negotiated_linkrate =
3432 SAS_LINK_RATE_UNKNOWN;
3434 out:
3435 mptsas_free_fw_event(ioc, fw_event);
3438 static void
3439 mptsas_not_responding_devices(MPT_ADAPTER *ioc)
3441 struct mptsas_portinfo buffer, *port_info;
3442 struct mptsas_device_info *sas_info;
3443 struct mptsas_devinfo sas_device;
3444 u32 handle;
3445 VirtTarget *vtarget = NULL;
3446 struct mptsas_phyinfo *phy_info;
3447 u8 found_expander;
3448 int retval, retry_count;
3449 unsigned long flags;
3451 mpt_findImVolumes(ioc);
3453 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3454 if (ioc->ioc_reset_in_progress) {
3455 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3456 "%s: exiting due to a parallel reset \n", ioc->name,
3457 __func__));
3458 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3459 return;
3461 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3463 /* devices, logical volumes */
3464 mutex_lock(&ioc->sas_device_info_mutex);
3465 redo_device_scan:
3466 list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
3467 if (sas_info->is_cached)
3468 continue;
3469 if (!sas_info->is_logical_volume) {
3470 sas_device.handle = 0;
3471 retry_count = 0;
3472 retry_page:
3473 retval = mptsas_sas_device_pg0(ioc, &sas_device,
3474 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
3475 << MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3476 (sas_info->fw.channel << 8) +
3477 sas_info->fw.id);
3479 if (sas_device.handle)
3480 continue;
3481 if (retval == -EBUSY) {
3482 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3483 if (ioc->ioc_reset_in_progress) {
3484 dfailprintk(ioc,
3485 printk(MYIOC_s_DEBUG_FMT
3486 "%s: exiting due to reset\n",
3487 ioc->name, __func__));
3488 spin_unlock_irqrestore
3489 (&ioc->taskmgmt_lock, flags);
3490 mutex_unlock(&ioc->
3491 sas_device_info_mutex);
3492 return;
3494 spin_unlock_irqrestore(&ioc->taskmgmt_lock,
3495 flags);
3498 if (retval && (retval != -ENODEV)) {
3499 if (retry_count < 10) {
3500 retry_count++;
3501 goto retry_page;
3502 } else {
3503 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3504 "%s: Config page retry exceeded retry "
3505 "count deleting device 0x%llx\n",
3506 ioc->name, __func__,
3507 sas_info->sas_address));
3511 /* delete device */
3512 vtarget = mptsas_find_vtarget(ioc,
3513 sas_info->fw.channel, sas_info->fw.id);
3515 if (vtarget)
3516 vtarget->deleted = 1;
3518 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3519 sas_info->sas_address);
3521 if (phy_info) {
3522 mptsas_del_end_device(ioc, phy_info);
3523 goto redo_device_scan;
3525 } else
3526 mptsas_volume_delete(ioc, sas_info->fw.id);
3528 mutex_unlock(&ioc->sas_device_info_mutex);
3530 /* expanders */
3531 mutex_lock(&ioc->sas_topology_mutex);
3532 redo_expander_scan:
3533 list_for_each_entry(port_info, &ioc->sas_topology, list) {
3535 if (port_info->phy_info &&
3536 (!(port_info->phy_info[0].identify.device_info &
3537 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
3538 continue;
3539 found_expander = 0;
3540 handle = 0xFFFF;
3541 while (!mptsas_sas_expander_pg0(ioc, &buffer,
3542 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3543 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle) &&
3544 !found_expander) {
3546 handle = buffer.phy_info[0].handle;
3547 if (buffer.phy_info[0].identify.sas_address ==
3548 port_info->phy_info[0].identify.sas_address) {
3549 found_expander = 1;
3551 kfree(buffer.phy_info);
3554 if (!found_expander) {
3555 mptsas_expander_delete(ioc, port_info, 0);
3556 goto redo_expander_scan;
3559 mutex_unlock(&ioc->sas_topology_mutex);
3563 * mptsas_probe_expanders - adding expanders
3564 * @ioc: Pointer to MPT_ADAPTER structure
3567 static void
3568 mptsas_probe_expanders(MPT_ADAPTER *ioc)
3570 struct mptsas_portinfo buffer, *port_info;
3571 u32 handle;
3572 int i;
3574 handle = 0xFFFF;
3575 while (!mptsas_sas_expander_pg0(ioc, &buffer,
3576 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3577 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)) {
3579 handle = buffer.phy_info[0].handle;
3580 port_info = mptsas_find_portinfo_by_sas_address(ioc,
3581 buffer.phy_info[0].identify.sas_address);
3583 if (port_info) {
3584 /* refreshing handles */
3585 for (i = 0; i < buffer.num_phys; i++) {
3586 port_info->phy_info[i].handle = handle;
3587 port_info->phy_info[i].identify.handle_parent =
3588 buffer.phy_info[0].identify.handle_parent;
3590 mptsas_expander_refresh(ioc, port_info);
3591 kfree(buffer.phy_info);
3592 continue;
3595 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3596 if (!port_info) {
3597 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3598 "%s: exit at line=%d\n", ioc->name,
3599 __func__, __LINE__));
3600 return;
3602 port_info->num_phys = buffer.num_phys;
3603 port_info->phy_info = buffer.phy_info;
3604 for (i = 0; i < port_info->num_phys; i++)
3605 port_info->phy_info[i].portinfo = port_info;
3606 mutex_lock(&ioc->sas_topology_mutex);
3607 list_add_tail(&port_info->list, &ioc->sas_topology);
3608 mutex_unlock(&ioc->sas_topology_mutex);
3609 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3610 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3611 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3612 mptsas_expander_refresh(ioc, port_info);
3616 static void
3617 mptsas_probe_devices(MPT_ADAPTER *ioc)
3619 u16 handle;
3620 struct mptsas_devinfo sas_device;
3621 struct mptsas_phyinfo *phy_info;
3623 handle = 0xFFFF;
3624 while (!(mptsas_sas_device_pg0(ioc, &sas_device,
3625 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
3627 handle = sas_device.handle;
3629 if ((sas_device.device_info &
3630 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
3631 MPI_SAS_DEVICE_INFO_STP_TARGET |
3632 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0)
3633 continue;
3635 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
3636 if (!phy_info)
3637 continue;
3639 if (mptsas_get_rphy(phy_info))
3640 continue;
3642 mptsas_add_end_device(ioc, phy_info);
3647 * mptsas_scan_sas_topology -
3648 * @ioc: Pointer to MPT_ADAPTER structure
3649 * @sas_address:
3652 static void
3653 mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
3655 struct scsi_device *sdev;
3656 int i;
3658 mptsas_probe_hba_phys(ioc);
3659 mptsas_probe_expanders(ioc);
3660 mptsas_probe_devices(ioc);
3663 Reporting RAID volumes.
3665 if (!ioc->ir_firmware || !ioc->raid_data.pIocPg2 ||
3666 !ioc->raid_data.pIocPg2->NumActiveVolumes)
3667 return;
3668 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
3669 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
3670 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
3671 if (sdev) {
3672 scsi_device_put(sdev);
3673 continue;
3675 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
3676 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
3677 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID);
3678 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
3679 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
3684 static void
3685 mptsas_handle_queue_full_event(struct fw_event_work *fw_event)
3687 MPT_ADAPTER *ioc;
3688 EventDataQueueFull_t *qfull_data;
3689 struct mptsas_device_info *sas_info;
3690 struct scsi_device *sdev;
3691 int depth;
3692 int id = -1;
3693 int channel = -1;
3694 int fw_id, fw_channel;
3695 u16 current_depth;
3698 ioc = fw_event->ioc;
3699 qfull_data = (EventDataQueueFull_t *)fw_event->event_data;
3700 fw_id = qfull_data->TargetID;
3701 fw_channel = qfull_data->Bus;
3702 current_depth = le16_to_cpu(qfull_data->CurrentDepth);
3704 /* if hidden raid component, look for the volume id */
3705 mutex_lock(&ioc->sas_device_info_mutex);
3706 if (mptscsih_is_phys_disk(ioc, fw_channel, fw_id)) {
3707 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
3708 list) {
3709 if (sas_info->is_cached ||
3710 sas_info->is_logical_volume)
3711 continue;
3712 if (sas_info->is_hidden_raid_component &&
3713 (sas_info->fw.channel == fw_channel &&
3714 sas_info->fw.id == fw_id)) {
3715 id = sas_info->volume_id;
3716 channel = MPTSAS_RAID_CHANNEL;
3717 goto out;
3720 } else {
3721 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
3722 list) {
3723 if (sas_info->is_cached ||
3724 sas_info->is_hidden_raid_component ||
3725 sas_info->is_logical_volume)
3726 continue;
3727 if (sas_info->fw.channel == fw_channel &&
3728 sas_info->fw.id == fw_id) {
3729 id = sas_info->os.id;
3730 channel = sas_info->os.channel;
3731 goto out;
3737 out:
3738 mutex_unlock(&ioc->sas_device_info_mutex);
3740 if (id != -1) {
3741 shost_for_each_device(sdev, ioc->sh) {
3742 if (sdev->id == id && sdev->channel == channel) {
3743 if (current_depth > sdev->queue_depth) {
3744 sdev_printk(KERN_INFO, sdev,
3745 "strange observation, the queue "
3746 "depth is (%d) meanwhile fw queue "
3747 "depth (%d)\n", sdev->queue_depth,
3748 current_depth);
3749 continue;
3751 depth = scsi_track_queue_full(sdev,
3752 current_depth - 1);
3753 if (depth > 0)
3754 sdev_printk(KERN_INFO, sdev,
3755 "Queue depth reduced to (%d)\n",
3756 depth);
3757 else if (depth < 0)
3758 sdev_printk(KERN_INFO, sdev,
3759 "Tagged Command Queueing is being "
3760 "disabled\n");
3761 else if (depth == 0)
3762 sdev_printk(KERN_INFO, sdev,
3763 "Queue depth not changed yet\n");
3768 mptsas_free_fw_event(ioc, fw_event);
3772 static struct mptsas_phyinfo *
3773 mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
3775 struct mptsas_portinfo *port_info;
3776 struct mptsas_phyinfo *phy_info = NULL;
3777 int i;
3779 mutex_lock(&ioc->sas_topology_mutex);
3780 list_for_each_entry(port_info, &ioc->sas_topology, list) {
3781 for (i = 0; i < port_info->num_phys; i++) {
3782 if (!mptsas_is_end_device(
3783 &port_info->phy_info[i].attached))
3784 continue;
3785 if (port_info->phy_info[i].attached.sas_address
3786 != sas_address)
3787 continue;
3788 phy_info = &port_info->phy_info[i];
3789 break;
3792 mutex_unlock(&ioc->sas_topology_mutex);
3793 return phy_info;
3797 * mptsas_find_phyinfo_by_phys_disk_num -
3798 * @ioc: Pointer to MPT_ADAPTER structure
3799 * @phys_disk_num:
3800 * @channel:
3801 * @id:
3804 static struct mptsas_phyinfo *
3805 mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num,
3806 u8 channel, u8 id)
3808 struct mptsas_phyinfo *phy_info = NULL;
3809 struct mptsas_portinfo *port_info;
3810 RaidPhysDiskPage1_t *phys_disk = NULL;
3811 int num_paths;
3812 u64 sas_address = 0;
3813 int i;
3815 phy_info = NULL;
3816 if (!ioc->raid_data.pIocPg3)
3817 return NULL;
3818 /* dual port support */
3819 num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num);
3820 if (!num_paths)
3821 goto out;
3822 phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
3823 (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
3824 if (!phys_disk)
3825 goto out;
3826 mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk);
3827 for (i = 0; i < num_paths; i++) {
3828 if ((phys_disk->Path[i].Flags & 1) != 0)
3829 /* entry no longer valid */
3830 continue;
3831 if ((id == phys_disk->Path[i].PhysDiskID) &&
3832 (channel == phys_disk->Path[i].PhysDiskBus)) {
3833 memcpy(&sas_address, &phys_disk->Path[i].WWID,
3834 sizeof(u64));
3835 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3836 sas_address);
3837 goto out;
3841 out:
3842 kfree(phys_disk);
3843 if (phy_info)
3844 return phy_info;
3847 * Extra code to handle RAID0 case, where the sas_address is not updated
3848 * in phys_disk_page_1 when hotswapped
3850 mutex_lock(&ioc->sas_topology_mutex);
3851 list_for_each_entry(port_info, &ioc->sas_topology, list) {
3852 for (i = 0; i < port_info->num_phys && !phy_info; i++) {
3853 if (!mptsas_is_end_device(
3854 &port_info->phy_info[i].attached))
3855 continue;
3856 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
3857 continue;
3858 if ((port_info->phy_info[i].attached.phys_disk_num ==
3859 phys_disk_num) &&
3860 (port_info->phy_info[i].attached.id == id) &&
3861 (port_info->phy_info[i].attached.channel ==
3862 channel))
3863 phy_info = &port_info->phy_info[i];
3866 mutex_unlock(&ioc->sas_topology_mutex);
3867 return phy_info;
3870 static void
3871 mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
3873 int rc;
3875 sdev->no_uld_attach = data ? 1 : 0;
3876 rc = scsi_device_reprobe(sdev);
3879 static void
3880 mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
3882 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
3883 mptsas_reprobe_lun);
3886 static void
3887 mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
3889 CONFIGPARMS cfg;
3890 ConfigPageHeader_t hdr;
3891 dma_addr_t dma_handle;
3892 pRaidVolumePage0_t buffer = NULL;
3893 RaidPhysDiskPage0_t phys_disk;
3894 int i;
3895 struct mptsas_phyinfo *phy_info;
3896 struct mptsas_devinfo sas_device;
3898 memset(&cfg, 0 , sizeof(CONFIGPARMS));
3899 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
3900 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
3901 cfg.pageAddr = (channel << 8) + id;
3902 cfg.cfghdr.hdr = &hdr;
3903 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
3905 if (mpt_config(ioc, &cfg) != 0)
3906 goto out;
3908 if (!hdr.PageLength)
3909 goto out;
3911 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
3912 &dma_handle);
3914 if (!buffer)
3915 goto out;
3917 cfg.physAddr = dma_handle;
3918 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
3920 if (mpt_config(ioc, &cfg) != 0)
3921 goto out;
3923 if (!(buffer->VolumeStatus.Flags &
3924 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
3925 goto out;
3927 if (!buffer->NumPhysDisks)
3928 goto out;
3930 for (i = 0; i < buffer->NumPhysDisks; i++) {
3932 if (mpt_raid_phys_disk_pg0(ioc,
3933 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
3934 continue;
3936 if (mptsas_sas_device_pg0(ioc, &sas_device,
3937 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
3938 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3939 (phys_disk.PhysDiskBus << 8) +
3940 phys_disk.PhysDiskID))
3941 continue;
3943 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3944 sas_device.sas_address);
3945 mptsas_add_end_device(ioc, phy_info);
3948 out:
3949 if (buffer)
3950 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
3951 dma_handle);
3954 * Work queue thread to handle SAS hotplug events
3956 static void
3957 mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
3958 struct mptsas_hotplug_event *hot_plug_info)
3960 struct mptsas_phyinfo *phy_info;
3961 struct scsi_target * starget;
3962 struct mptsas_devinfo sas_device;
3963 VirtTarget *vtarget;
3964 int i;
3966 switch (hot_plug_info->event_type) {
3968 case MPTSAS_ADD_PHYSDISK:
3970 if (!ioc->raid_data.pIocPg2)
3971 break;
3973 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
3974 if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID ==
3975 hot_plug_info->id) {
3976 printk(MYIOC_s_WARN_FMT "firmware bug: unable "
3977 "to add hidden disk - target_id matchs "
3978 "volume_id\n", ioc->name);
3979 mptsas_free_fw_event(ioc, fw_event);
3980 return;
3983 mpt_findImVolumes(ioc);
3985 case MPTSAS_ADD_DEVICE:
3986 memset(&sas_device, 0, sizeof(struct mptsas_devinfo));
3987 mptsas_sas_device_pg0(ioc, &sas_device,
3988 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
3989 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3990 (hot_plug_info->channel << 8) +
3991 hot_plug_info->id);
3993 if (!sas_device.handle)
3994 return;
3996 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
3997 if (!phy_info)
3998 break;
4000 if (mptsas_get_rphy(phy_info))
4001 break;
4003 mptsas_add_end_device(ioc, phy_info);
4004 break;
4006 case MPTSAS_DEL_DEVICE:
4007 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4008 hot_plug_info->sas_address);
4009 mptsas_del_end_device(ioc, phy_info);
4010 break;
4012 case MPTSAS_DEL_PHYSDISK:
4014 mpt_findImVolumes(ioc);
4016 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
4017 ioc, hot_plug_info->phys_disk_num,
4018 hot_plug_info->channel,
4019 hot_plug_info->id);
4020 mptsas_del_end_device(ioc, phy_info);
4021 break;
4023 case MPTSAS_ADD_PHYSDISK_REPROBE:
4025 if (mptsas_sas_device_pg0(ioc, &sas_device,
4026 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4027 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4028 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
4029 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4030 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4031 __func__, hot_plug_info->id, __LINE__));
4032 break;
4035 phy_info = mptsas_find_phyinfo_by_sas_address(
4036 ioc, sas_device.sas_address);
4038 if (!phy_info) {
4039 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4040 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4041 __func__, hot_plug_info->id, __LINE__));
4042 break;
4045 starget = mptsas_get_starget(phy_info);
4046 if (!starget) {
4047 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4048 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4049 __func__, hot_plug_info->id, __LINE__));
4050 break;
4053 vtarget = starget->hostdata;
4054 if (!vtarget) {
4055 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4056 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4057 __func__, hot_plug_info->id, __LINE__));
4058 break;
4061 mpt_findImVolumes(ioc);
4063 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Hidding: "
4064 "fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4065 ioc->name, hot_plug_info->channel, hot_plug_info->id,
4066 hot_plug_info->phys_disk_num, (unsigned long long)
4067 sas_device.sas_address);
4069 vtarget->id = hot_plug_info->phys_disk_num;
4070 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
4071 phy_info->attached.phys_disk_num = hot_plug_info->phys_disk_num;
4072 mptsas_reprobe_target(starget, 1);
4073 break;
4075 case MPTSAS_DEL_PHYSDISK_REPROBE:
4077 if (mptsas_sas_device_pg0(ioc, &sas_device,
4078 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4079 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4080 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
4081 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4082 "%s: fw_id=%d exit at line=%d\n",
4083 ioc->name, __func__,
4084 hot_plug_info->id, __LINE__));
4085 break;
4088 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4089 sas_device.sas_address);
4090 if (!phy_info) {
4091 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4092 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4093 __func__, hot_plug_info->id, __LINE__));
4094 break;
4097 starget = mptsas_get_starget(phy_info);
4098 if (!starget) {
4099 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4100 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4101 __func__, hot_plug_info->id, __LINE__));
4102 break;
4105 vtarget = starget->hostdata;
4106 if (!vtarget) {
4107 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4108 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4109 __func__, hot_plug_info->id, __LINE__));
4110 break;
4113 if (!(vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) {
4114 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4115 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4116 __func__, hot_plug_info->id, __LINE__));
4117 break;
4120 mpt_findImVolumes(ioc);
4122 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Exposing:"
4123 " fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4124 ioc->name, hot_plug_info->channel, hot_plug_info->id,
4125 hot_plug_info->phys_disk_num, (unsigned long long)
4126 sas_device.sas_address);
4128 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
4129 vtarget->id = hot_plug_info->id;
4130 phy_info->attached.phys_disk_num = ~0;
4131 mptsas_reprobe_target(starget, 0);
4132 mptsas_add_device_component_by_fw(ioc,
4133 hot_plug_info->channel, hot_plug_info->id);
4134 break;
4136 case MPTSAS_ADD_RAID:
4138 mpt_findImVolumes(ioc);
4139 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
4140 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4141 hot_plug_info->id);
4142 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
4143 hot_plug_info->id, 0);
4144 break;
4146 case MPTSAS_DEL_RAID:
4148 mpt_findImVolumes(ioc);
4149 printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
4150 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4151 hot_plug_info->id);
4152 scsi_remove_device(hot_plug_info->sdev);
4153 scsi_device_put(hot_plug_info->sdev);
4154 break;
4156 case MPTSAS_ADD_INACTIVE_VOLUME:
4158 mpt_findImVolumes(ioc);
4159 mptsas_adding_inactive_raid_components(ioc,
4160 hot_plug_info->channel, hot_plug_info->id);
4161 break;
4163 default:
4164 break;
4167 mptsas_free_fw_event(ioc, fw_event);
4170 static void
4171 mptsas_send_sas_event(struct fw_event_work *fw_event)
4173 MPT_ADAPTER *ioc;
4174 struct mptsas_hotplug_event hot_plug_info;
4175 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
4176 u32 device_info;
4177 u64 sas_address;
4179 ioc = fw_event->ioc;
4180 sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
4181 fw_event->event_data;
4182 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
4184 if ((device_info &
4185 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
4186 MPI_SAS_DEVICE_INFO_STP_TARGET |
4187 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) {
4188 mptsas_free_fw_event(ioc, fw_event);
4189 return;
4192 if (sas_event_data->ReasonCode ==
4193 MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED) {
4194 mptbase_sas_persist_operation(ioc,
4195 MPI_SAS_OP_CLEAR_NOT_PRESENT);
4196 mptsas_free_fw_event(ioc, fw_event);
4197 return;
4200 switch (sas_event_data->ReasonCode) {
4201 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
4202 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
4203 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4204 hot_plug_info.handle = le16_to_cpu(sas_event_data->DevHandle);
4205 hot_plug_info.channel = sas_event_data->Bus;
4206 hot_plug_info.id = sas_event_data->TargetID;
4207 hot_plug_info.phy_id = sas_event_data->PhyNum;
4208 memcpy(&sas_address, &sas_event_data->SASAddress,
4209 sizeof(u64));
4210 hot_plug_info.sas_address = le64_to_cpu(sas_address);
4211 hot_plug_info.device_info = device_info;
4212 if (sas_event_data->ReasonCode &
4213 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
4214 hot_plug_info.event_type = MPTSAS_ADD_DEVICE;
4215 else
4216 hot_plug_info.event_type = MPTSAS_DEL_DEVICE;
4217 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4218 break;
4220 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
4221 mptbase_sas_persist_operation(ioc,
4222 MPI_SAS_OP_CLEAR_NOT_PRESENT);
4223 mptsas_free_fw_event(ioc, fw_event);
4224 break;
4226 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
4227 /* TODO */
4228 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
4229 /* TODO */
4230 default:
4231 mptsas_free_fw_event(ioc, fw_event);
4232 break;
4236 static void
4237 mptsas_send_raid_event(struct fw_event_work *fw_event)
4239 MPT_ADAPTER *ioc;
4240 EVENT_DATA_RAID *raid_event_data;
4241 struct mptsas_hotplug_event hot_plug_info;
4242 int status;
4243 int state;
4244 struct scsi_device *sdev = NULL;
4245 VirtDevice *vdevice = NULL;
4246 RaidPhysDiskPage0_t phys_disk;
4248 ioc = fw_event->ioc;
4249 raid_event_data = (EVENT_DATA_RAID *)fw_event->event_data;
4250 status = le32_to_cpu(raid_event_data->SettingsStatus);
4251 state = (status >> 8) & 0xff;
4253 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4254 hot_plug_info.id = raid_event_data->VolumeID;
4255 hot_plug_info.channel = raid_event_data->VolumeBus;
4256 hot_plug_info.phys_disk_num = raid_event_data->PhysDiskNum;
4258 if (raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_DELETED ||
4259 raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_CREATED ||
4260 raid_event_data->ReasonCode ==
4261 MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED) {
4262 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
4263 hot_plug_info.id, 0);
4264 hot_plug_info.sdev = sdev;
4265 if (sdev)
4266 vdevice = sdev->hostdata;
4269 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4270 "ReasonCode=%02x\n", ioc->name, __func__,
4271 raid_event_data->ReasonCode));
4273 switch (raid_event_data->ReasonCode) {
4274 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4275 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK_REPROBE;
4276 break;
4277 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4278 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK_REPROBE;
4279 break;
4280 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4281 switch (state) {
4282 case MPI_PD_STATE_ONLINE:
4283 case MPI_PD_STATE_NOT_COMPATIBLE:
4284 mpt_raid_phys_disk_pg0(ioc,
4285 raid_event_data->PhysDiskNum, &phys_disk);
4286 hot_plug_info.id = phys_disk.PhysDiskID;
4287 hot_plug_info.channel = phys_disk.PhysDiskBus;
4288 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
4289 break;
4290 case MPI_PD_STATE_FAILED:
4291 case MPI_PD_STATE_MISSING:
4292 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
4293 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
4294 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
4295 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
4296 break;
4297 default:
4298 break;
4300 break;
4301 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4302 if (!sdev)
4303 break;
4304 vdevice->vtarget->deleted = 1; /* block IO */
4305 hot_plug_info.event_type = MPTSAS_DEL_RAID;
4306 break;
4307 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4308 if (sdev) {
4309 scsi_device_put(sdev);
4310 break;
4312 hot_plug_info.event_type = MPTSAS_ADD_RAID;
4313 break;
4314 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4315 if (!(status & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)) {
4316 if (!sdev)
4317 break;
4318 vdevice->vtarget->deleted = 1; /* block IO */
4319 hot_plug_info.event_type = MPTSAS_DEL_RAID;
4320 break;
4322 switch (state) {
4323 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
4324 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
4325 if (!sdev)
4326 break;
4327 vdevice->vtarget->deleted = 1; /* block IO */
4328 hot_plug_info.event_type = MPTSAS_DEL_RAID;
4329 break;
4330 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
4331 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
4332 if (sdev) {
4333 scsi_device_put(sdev);
4334 break;
4336 hot_plug_info.event_type = MPTSAS_ADD_RAID;
4337 break;
4338 default:
4339 break;
4341 break;
4342 default:
4343 break;
4346 if (hot_plug_info.event_type != MPTSAS_IGNORE_EVENT)
4347 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4348 else
4349 mptsas_free_fw_event(ioc, fw_event);
4353 * mptsas_issue_tm - send mptsas internal tm request
4354 * @ioc: Pointer to MPT_ADAPTER structure
4355 * @type: Task Management type
4356 * @channel: channel number for task management
4357 * @id: Logical Target ID for reset (if appropriate)
4358 * @lun: Logical unit for reset (if appropriate)
4359 * @task_context: Context for the task to be aborted
4360 * @timeout: timeout for task management control
4362 * return 0 on success and -1 on failure:
4365 static int
4366 mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun,
4367 int task_context, ulong timeout, u8 *issue_reset)
4369 MPT_FRAME_HDR *mf;
4370 SCSITaskMgmt_t *pScsiTm;
4371 int retval;
4372 unsigned long timeleft;
4374 *issue_reset = 0;
4375 mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
4376 if (mf == NULL) {
4377 retval = -1; /* return failure */
4378 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt request: no "
4379 "msg frames!!\n", ioc->name));
4380 goto out;
4383 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request: mr = %p, "
4384 "task_type = 0x%02X,\n\t timeout = %ld, fw_channel = %d, "
4385 "fw_id = %d, lun = %lld,\n\t task_context = 0x%x\n", ioc->name, mf,
4386 type, timeout, channel, id, (unsigned long long)lun,
4387 task_context));
4389 pScsiTm = (SCSITaskMgmt_t *) mf;
4390 memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
4391 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
4392 pScsiTm->TaskType = type;
4393 pScsiTm->MsgFlags = 0;
4394 pScsiTm->TargetID = id;
4395 pScsiTm->Bus = channel;
4396 pScsiTm->ChainOffset = 0;
4397 pScsiTm->Reserved = 0;
4398 pScsiTm->Reserved1 = 0;
4399 pScsiTm->TaskMsgContext = task_context;
4400 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
4402 INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4403 CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
4404 retval = 0;
4405 mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
4407 /* Now wait for the command to complete */
4408 timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
4409 timeout*HZ);
4410 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
4411 retval = -1; /* return failure */
4412 dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
4413 "TaskMgmt request: TIMED OUT!(mr=%p)\n", ioc->name, mf));
4414 mpt_free_msg_frame(ioc, mf);
4415 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
4416 goto out;
4417 *issue_reset = 1;
4418 goto out;
4421 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
4422 retval = -1; /* return failure */
4423 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4424 "TaskMgmt request: failed with no reply\n", ioc->name));
4425 goto out;
4428 out:
4429 CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4430 return retval;
4434 * mptsas_broadcast_primative_work - Handle broadcast primitives
4435 * @work: work queue payload containing info describing the event
4437 * this will be handled in workqueue context.
4439 static void
4440 mptsas_broadcast_primative_work(struct fw_event_work *fw_event)
4442 MPT_ADAPTER *ioc = fw_event->ioc;
4443 MPT_FRAME_HDR *mf;
4444 VirtDevice *vdevice;
4445 int ii;
4446 struct scsi_cmnd *sc;
4447 SCSITaskMgmtReply_t *pScsiTmReply;
4448 u8 issue_reset;
4449 int task_context;
4450 u8 channel, id;
4451 int lun;
4452 u32 termination_count;
4453 u32 query_count;
4455 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4456 "%s - enter\n", ioc->name, __func__));
4458 mutex_lock(&ioc->taskmgmt_cmds.mutex);
4459 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
4460 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4461 mptsas_requeue_fw_event(ioc, fw_event, 1000);
4462 return;
4465 issue_reset = 0;
4466 termination_count = 0;
4467 query_count = 0;
4468 mpt_findImVolumes(ioc);
4469 pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
4471 for (ii = 0; ii < ioc->req_depth; ii++) {
4472 if (ioc->fw_events_off)
4473 goto out;
4474 sc = mptscsih_get_scsi_lookup(ioc, ii);
4475 if (!sc)
4476 continue;
4477 mf = MPT_INDEX_2_MFPTR(ioc, ii);
4478 if (!mf)
4479 continue;
4480 task_context = mf->u.frame.hwhdr.msgctxu.MsgContext;
4481 vdevice = sc->device->hostdata;
4482 if (!vdevice || !vdevice->vtarget)
4483 continue;
4484 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
4485 continue; /* skip hidden raid components */
4486 if (vdevice->vtarget->raidVolume)
4487 continue; /* skip hidden raid components */
4488 channel = vdevice->vtarget->channel;
4489 id = vdevice->vtarget->id;
4490 lun = vdevice->lun;
4491 if (mptsas_issue_tm(ioc, MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK,
4492 channel, id, (u64)lun, task_context, 30, &issue_reset))
4493 goto out;
4494 query_count++;
4495 termination_count +=
4496 le32_to_cpu(pScsiTmReply->TerminationCount);
4497 if ((pScsiTmReply->IOCStatus == MPI_IOCSTATUS_SUCCESS) &&
4498 (pScsiTmReply->ResponseCode ==
4499 MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
4500 pScsiTmReply->ResponseCode ==
4501 MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC))
4502 continue;
4503 if (mptsas_issue_tm(ioc,
4504 MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET,
4505 channel, id, (u64)lun, 0, 30, &issue_reset))
4506 goto out;
4507 termination_count +=
4508 le32_to_cpu(pScsiTmReply->TerminationCount);
4511 out:
4512 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4513 "%s - exit, query_count = %d termination_count = %d\n",
4514 ioc->name, __func__, query_count, termination_count));
4516 ioc->broadcast_aen_busy = 0;
4517 mpt_clear_taskmgmt_in_progress_flag(ioc);
4518 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4520 if (issue_reset) {
4521 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
4522 ioc->name, __func__);
4523 mpt_HardResetHandler(ioc, CAN_SLEEP);
4525 mptsas_free_fw_event(ioc, fw_event);
4529 * mptsas_send_ir2_event - handle exposing hidden disk when
4530 * an inactive raid volume is added
4532 * @ioc: Pointer to MPT_ADAPTER structure
4533 * @ir2_data
4536 static void
4537 mptsas_send_ir2_event(struct fw_event_work *fw_event)
4539 MPT_ADAPTER *ioc;
4540 struct mptsas_hotplug_event hot_plug_info;
4541 MPI_EVENT_DATA_IR2 *ir2_data;
4542 u8 reasonCode;
4543 RaidPhysDiskPage0_t phys_disk;
4545 ioc = fw_event->ioc;
4546 ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data;
4547 reasonCode = ir2_data->ReasonCode;
4549 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4550 "ReasonCode=%02x\n", ioc->name, __func__, reasonCode));
4552 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4553 hot_plug_info.id = ir2_data->TargetID;
4554 hot_plug_info.channel = ir2_data->Bus;
4555 switch (reasonCode) {
4556 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
4557 hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
4558 break;
4559 case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
4560 hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4561 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
4562 break;
4563 case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
4564 hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4565 mpt_raid_phys_disk_pg0(ioc,
4566 ir2_data->PhysDiskNum, &phys_disk);
4567 hot_plug_info.id = phys_disk.PhysDiskID;
4568 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
4569 break;
4570 default:
4571 mptsas_free_fw_event(ioc, fw_event);
4572 return;
4574 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4577 static int
4578 mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
4580 u32 event = le32_to_cpu(reply->Event);
4581 int sz, event_data_sz;
4582 struct fw_event_work *fw_event;
4583 unsigned long delay;
4585 /* events turned off due to host reset or driver unloading */
4586 if (ioc->fw_events_off)
4587 return 0;
4589 delay = msecs_to_jiffies(1);
4590 switch (event) {
4591 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
4593 EVENT_DATA_SAS_BROADCAST_PRIMITIVE *broadcast_event_data =
4594 (EVENT_DATA_SAS_BROADCAST_PRIMITIVE *)reply->Data;
4595 if (broadcast_event_data->Primitive !=
4596 MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
4597 return 0;
4598 if (ioc->broadcast_aen_busy)
4599 return 0;
4600 ioc->broadcast_aen_busy = 1;
4601 break;
4603 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
4605 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
4606 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
4608 if (sas_event_data->ReasonCode ==
4609 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
4610 mptsas_target_reset_queue(ioc, sas_event_data);
4611 return 0;
4613 break;
4615 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
4617 MpiEventDataSasExpanderStatusChange_t *expander_data =
4618 (MpiEventDataSasExpanderStatusChange_t *)reply->Data;
4620 if (ioc->old_sas_discovery_protocal)
4621 return 0;
4623 if (expander_data->ReasonCode ==
4624 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING &&
4625 ioc->device_missing_delay)
4626 delay = HZ * ioc->device_missing_delay;
4627 break;
4629 case MPI_EVENT_SAS_DISCOVERY:
4631 u32 discovery_status;
4632 EventDataSasDiscovery_t *discovery_data =
4633 (EventDataSasDiscovery_t *)reply->Data;
4635 discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
4636 ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
4637 if (ioc->old_sas_discovery_protocal && !discovery_status)
4638 mptsas_queue_rescan(ioc);
4639 return 0;
4641 case MPI_EVENT_INTEGRATED_RAID:
4642 case MPI_EVENT_PERSISTENT_TABLE_FULL:
4643 case MPI_EVENT_IR2:
4644 case MPI_EVENT_SAS_PHY_LINK_STATUS:
4645 case MPI_EVENT_QUEUE_FULL:
4646 break;
4647 default:
4648 return 0;
4651 event_data_sz = ((reply->MsgLength * 4) -
4652 offsetof(EventNotificationReply_t, Data));
4653 sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
4654 fw_event = kzalloc(sz, GFP_ATOMIC);
4655 if (!fw_event) {
4656 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
4657 __func__, __LINE__);
4658 return 0;
4660 memcpy(fw_event->event_data, reply->Data, event_data_sz);
4661 fw_event->event = event;
4662 fw_event->ioc = ioc;
4663 mptsas_add_fw_event(ioc, fw_event, delay);
4664 return 0;
4667 /* Delete a volume when no longer listed in ioc pg2
4669 static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id)
4671 struct scsi_device *sdev;
4672 int i;
4674 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0);
4675 if (!sdev)
4676 return;
4677 if (!ioc->raid_data.pIocPg2)
4678 goto out;
4679 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
4680 goto out;
4681 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
4682 if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id)
4683 goto release_sdev;
4684 out:
4685 printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
4686 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id);
4687 scsi_remove_device(sdev);
4688 release_sdev:
4689 scsi_device_put(sdev);
4692 static int
4693 mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
4695 struct Scsi_Host *sh;
4696 MPT_SCSI_HOST *hd;
4697 MPT_ADAPTER *ioc;
4698 unsigned long flags;
4699 int ii;
4700 int numSGE = 0;
4701 int scale;
4702 int ioc_cap;
4703 int error=0;
4704 int r;
4706 r = mpt_attach(pdev,id);
4707 if (r)
4708 return r;
4710 ioc = pci_get_drvdata(pdev);
4711 mptsas_fw_event_off(ioc);
4712 ioc->DoneCtx = mptsasDoneCtx;
4713 ioc->TaskCtx = mptsasTaskCtx;
4714 ioc->InternalCtx = mptsasInternalCtx;
4716 /* Added sanity check on readiness of the MPT adapter.
4718 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
4719 printk(MYIOC_s_WARN_FMT
4720 "Skipping because it's not operational!\n",
4721 ioc->name);
4722 error = -ENODEV;
4723 goto out_mptsas_probe;
4726 if (!ioc->active) {
4727 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
4728 ioc->name);
4729 error = -ENODEV;
4730 goto out_mptsas_probe;
4733 /* Sanity check - ensure at least 1 port is INITIATOR capable
4735 ioc_cap = 0;
4736 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
4737 if (ioc->pfacts[ii].ProtocolFlags &
4738 MPI_PORTFACTS_PROTOCOL_INITIATOR)
4739 ioc_cap++;
4742 if (!ioc_cap) {
4743 printk(MYIOC_s_WARN_FMT
4744 "Skipping ioc=%p because SCSI Initiator mode "
4745 "is NOT enabled!\n", ioc->name, ioc);
4746 return 0;
4749 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
4750 if (!sh) {
4751 printk(MYIOC_s_WARN_FMT
4752 "Unable to register controller with SCSI subsystem\n",
4753 ioc->name);
4754 error = -1;
4755 goto out_mptsas_probe;
4758 spin_lock_irqsave(&ioc->FreeQlock, flags);
4760 /* Attach the SCSI Host to the IOC structure
4762 ioc->sh = sh;
4764 sh->io_port = 0;
4765 sh->n_io_port = 0;
4766 sh->irq = 0;
4768 /* set 16 byte cdb's */
4769 sh->max_cmd_len = 16;
4770 sh->can_queue = min_t(int, ioc->req_depth - 10, sh->can_queue);
4771 sh->max_id = -1;
4772 sh->max_lun = max_lun;
4773 sh->transportt = mptsas_transport_template;
4775 /* Required entry.
4777 sh->unique_id = ioc->id;
4779 INIT_LIST_HEAD(&ioc->sas_topology);
4780 mutex_init(&ioc->sas_topology_mutex);
4781 mutex_init(&ioc->sas_discovery_mutex);
4782 mutex_init(&ioc->sas_mgmt.mutex);
4783 init_completion(&ioc->sas_mgmt.done);
4785 /* Verify that we won't exceed the maximum
4786 * number of chain buffers
4787 * We can optimize: ZZ = req_sz/sizeof(SGE)
4788 * For 32bit SGE's:
4789 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
4790 * + (req_sz - 64)/sizeof(SGE)
4791 * A slightly different algorithm is required for
4792 * 64bit SGEs.
4794 scale = ioc->req_sz/ioc->SGE_size;
4795 if (ioc->sg_addr_size == sizeof(u64)) {
4796 numSGE = (scale - 1) *
4797 (ioc->facts.MaxChainDepth-1) + scale +
4798 (ioc->req_sz - 60) / ioc->SGE_size;
4799 } else {
4800 numSGE = 1 + (scale - 1) *
4801 (ioc->facts.MaxChainDepth-1) + scale +
4802 (ioc->req_sz - 64) / ioc->SGE_size;
4805 if (numSGE < sh->sg_tablesize) {
4806 /* Reset this value */
4807 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4808 "Resetting sg_tablesize to %d from %d\n",
4809 ioc->name, numSGE, sh->sg_tablesize));
4810 sh->sg_tablesize = numSGE;
4813 hd = shost_priv(sh);
4814 hd->ioc = ioc;
4816 /* SCSI needs scsi_cmnd lookup table!
4817 * (with size equal to req_depth*PtrSz!)
4819 ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
4820 if (!ioc->ScsiLookup) {
4821 error = -ENOMEM;
4822 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4823 goto out_mptsas_probe;
4825 spin_lock_init(&ioc->scsi_lookup_lock);
4827 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
4828 ioc->name, ioc->ScsiLookup));
4830 ioc->sas_data.ptClear = mpt_pt_clear;
4832 hd->last_queue_full = 0;
4833 INIT_LIST_HEAD(&hd->target_reset_list);
4834 INIT_LIST_HEAD(&ioc->sas_device_info_list);
4835 mutex_init(&ioc->sas_device_info_mutex);
4837 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4839 if (ioc->sas_data.ptClear==1) {
4840 mptbase_sas_persist_operation(
4841 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
4844 error = scsi_add_host(sh, &ioc->pcidev->dev);
4845 if (error) {
4846 dprintk(ioc, printk(MYIOC_s_ERR_FMT
4847 "scsi_add_host failed\n", ioc->name));
4848 goto out_mptsas_probe;
4851 /* older firmware doesn't support expander events */
4852 if ((ioc->facts.HeaderVersion >> 8) < 0xE)
4853 ioc->old_sas_discovery_protocal = 1;
4854 mptsas_scan_sas_topology(ioc);
4855 mptsas_fw_event_on(ioc);
4856 return 0;
4858 out_mptsas_probe:
4860 mptscsih_remove(pdev);
4861 return error;
4864 void
4865 mptsas_shutdown(struct pci_dev *pdev)
4867 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
4869 mptsas_fw_event_off(ioc);
4870 mptsas_cleanup_fw_event_q(ioc);
4873 static void __devexit mptsas_remove(struct pci_dev *pdev)
4875 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
4876 struct mptsas_portinfo *p, *n;
4877 int i;
4879 mptsas_shutdown(pdev);
4881 mptsas_del_device_components(ioc);
4883 ioc->sas_discovery_ignore_events = 1;
4884 sas_remove_host(ioc->sh);
4886 mutex_lock(&ioc->sas_topology_mutex);
4887 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
4888 list_del(&p->list);
4889 for (i = 0 ; i < p->num_phys ; i++)
4890 mptsas_port_delete(ioc, p->phy_info[i].port_details);
4892 kfree(p->phy_info);
4893 kfree(p);
4895 mutex_unlock(&ioc->sas_topology_mutex);
4896 ioc->hba_port_info = NULL;
4897 mptscsih_remove(pdev);
4900 static struct pci_device_id mptsas_pci_table[] = {
4901 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
4902 PCI_ANY_ID, PCI_ANY_ID },
4903 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
4904 PCI_ANY_ID, PCI_ANY_ID },
4905 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
4906 PCI_ANY_ID, PCI_ANY_ID },
4907 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
4908 PCI_ANY_ID, PCI_ANY_ID },
4909 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
4910 PCI_ANY_ID, PCI_ANY_ID },
4911 {0} /* Terminating entry */
4913 MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
4916 static struct pci_driver mptsas_driver = {
4917 .name = "mptsas",
4918 .id_table = mptsas_pci_table,
4919 .probe = mptsas_probe,
4920 .remove = __devexit_p(mptsas_remove),
4921 .shutdown = mptsas_shutdown,
4922 #ifdef CONFIG_PM
4923 .suspend = mptscsih_suspend,
4924 .resume = mptscsih_resume,
4925 #endif
4928 static int __init
4929 mptsas_init(void)
4931 int error;
4933 show_mptmod_ver(my_NAME, my_VERSION);
4935 mptsas_transport_template =
4936 sas_attach_transport(&mptsas_transport_functions);
4937 if (!mptsas_transport_template)
4938 return -ENODEV;
4940 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
4941 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
4942 mptsasInternalCtx =
4943 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
4944 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
4945 mptsasDeviceResetCtx =
4946 mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
4948 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
4949 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
4951 error = pci_register_driver(&mptsas_driver);
4952 if (error)
4953 sas_release_transport(mptsas_transport_template);
4955 return error;
4958 static void __exit
4959 mptsas_exit(void)
4961 pci_unregister_driver(&mptsas_driver);
4962 sas_release_transport(mptsas_transport_template);
4964 mpt_reset_deregister(mptsasDoneCtx);
4965 mpt_event_deregister(mptsasDoneCtx);
4967 mpt_deregister(mptsasMgmtCtx);
4968 mpt_deregister(mptsasInternalCtx);
4969 mpt_deregister(mptsasTaskCtx);
4970 mpt_deregister(mptsasDoneCtx);
4971 mpt_deregister(mptsasDeviceResetCtx);
4974 module_init(mptsas_init);
4975 module_exit(mptsas_exit);