[SCSI] mptsas : Handle INSUFFICIENT resources status as similar to IOC BUSY status
[deliverable/linux.git] / drivers / message / fusion / mptsas.c
CommitLineData
0c33b27d
CH
1/*
2 * linux/drivers/message/fusion/mptsas.c
f36789e2
PS
3 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
0c33b27d 5 *
cddc0ab7 6 * Copyright (c) 1999-2008 LSI Corporation
16d20101 7 * (mailto:DL-MPTFusionLinux@lsi.com)
0c33b27d
CH
8 */
9/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10/*
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.
14
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.
19
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.
30
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
39
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
43*/
44/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
45
46#include <linux/module.h>
47#include <linux/kernel.h>
48#include <linux/init.h>
49#include <linux/errno.h>
cd354f1a 50#include <linux/jiffies.h>
0c33b27d 51#include <linux/workqueue.h>
547f9a21 52#include <linux/delay.h> /* for mdelay */
0c33b27d 53
547f9a21 54#include <scsi/scsi.h>
0c33b27d
CH
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>
547f9a21 59#include <scsi/scsi_dbg.h>
0c33b27d
CH
60
61#include "mptbase.h"
62#include "mptscsih.h"
56af97ae 63#include "mptsas.h"
0c33b27d
CH
64
65
66#define my_NAME "Fusion MPT SAS Host driver"
67#define my_VERSION MPT_LINUX_VERSION_COMMON
68#define MYNAM "mptsas"
69
e8bf3941
JB
70/*
71 * Reserved channel for integrated raid
72 */
73#define MPTSAS_RAID_CHANNEL 1
74
0c33b27d
CH
75MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
9f4203b3 78MODULE_VERSION(my_VERSION);
0c33b27d 79
0c33b27d
CH
80static int mpt_pt_clear;
81module_param(mpt_pt_clear, int, 0);
82MODULE_PARM_DESC(mpt_pt_clear,
ba856d32 83 " Clear persistency table: enable=1 "
0c33b27d
CH
84 "(default=MPTSCSIH_PT_CLEAR=0)");
85
793955f5
EM
86/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
87#define MPTSAS_MAX_LUN (16895)
88static int max_lun = MPTSAS_MAX_LUN;
89module_param(max_lun, int, 0);
90MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
91
f606f571
PS
92static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
93static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
94static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
95static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
e7deff33 96static u8 mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
0c33b27d 97
3eb0822c
KD
98static void mptsas_firmware_event_work(struct work_struct *work);
99static void mptsas_send_sas_event(struct fw_event_work *fw_event);
100static void mptsas_send_raid_event(struct fw_event_work *fw_event);
101static void mptsas_send_ir2_event(struct fw_event_work *fw_event);
102static void mptsas_parse_device_info(struct sas_identify *identify,
103 struct mptsas_devinfo *device_info);
104static inline void mptsas_set_rphy(MPT_ADAPTER *ioc,
105 struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy);
106static struct mptsas_phyinfo *mptsas_find_phyinfo_by_sas_address
107 (MPT_ADAPTER *ioc, u64 sas_address);
108static int mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
109 struct mptsas_devinfo *device_info, u32 form, u32 form_specific);
110static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc,
111 struct mptsas_enclosure *enclosure, u32 form, u32 form_specific);
112static int mptsas_add_end_device(MPT_ADAPTER *ioc,
113 struct mptsas_phyinfo *phy_info);
114static void mptsas_del_end_device(MPT_ADAPTER *ioc,
115 struct mptsas_phyinfo *phy_info);
f9c34022
KD
116static void mptsas_send_link_status_event(struct fw_event_work *fw_event);
117static struct mptsas_portinfo *mptsas_find_portinfo_by_sas_address
118 (MPT_ADAPTER *ioc, u64 sas_address);
119static void mptsas_expander_delete(MPT_ADAPTER *ioc,
120 struct mptsas_portinfo *port_info, u8 force);
121static void mptsas_send_expander_event(struct fw_event_work *fw_event);
eedf92b9
KD
122static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
123static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
db7051b2 124static void mptsas_broadcast_primative_work(struct fw_event_work *fw_event);
57e98513 125static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event);
a7938b0b 126static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);
0c33b27d 127
d6ecdd63
PS
128static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
129 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
130{
29dd3609
EM
131 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
132 "---- IO UNIT PAGE 0 ------------\n", ioc->name));
133 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
134 ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
135 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
136 ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
137 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
138 ioc->name, phy_data->Port));
139 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
140 ioc->name, phy_data->PortFlags));
141 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
142 ioc->name, phy_data->PhyFlags));
143 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
144 ioc->name, phy_data->NegotiatedLinkRate));
145 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
146 "Controller PHY Device Info=0x%X\n", ioc->name,
147 le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
148 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
149 ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
b5141128
CH
150}
151
d6ecdd63 152static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
b5141128
CH
153{
154 __le64 sas_address;
155
156 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
157
29dd3609
EM
158 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
159 "---- SAS PHY PAGE 0 ------------\n", ioc->name));
160 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
161 "Attached Device Handle=0x%X\n", ioc->name,
162 le16_to_cpu(pg0->AttachedDevHandle)));
163 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
164 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
165 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
166 "Attached PHY Identifier=0x%X\n", ioc->name,
167 pg0->AttachedPhyIdentifier));
168 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
169 ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
170 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
171 ioc->name, pg0->ProgrammedLinkRate));
172 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
173 ioc->name, pg0->ChangeCount));
174 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
175 ioc->name, le32_to_cpu(pg0->PhyInfo)));
b5141128
CH
176}
177
d6ecdd63 178static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
b5141128 179{
29dd3609
EM
180 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
181 "---- SAS PHY PAGE 1 ------------\n", ioc->name));
182 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
183 ioc->name, pg1->InvalidDwordCount));
184 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
185 "Running Disparity Error Count=0x%x\n", ioc->name,
186 pg1->RunningDisparityErrorCount));
187 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
188 "Loss Dword Synch Count=0x%x\n", ioc->name,
189 pg1->LossDwordSynchCount));
190 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
191 "PHY Reset Problem Count=0x%x\n\n", ioc->name,
192 pg1->PhyResetProblemCount));
b5141128
CH
193}
194
d6ecdd63 195static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
b5141128
CH
196{
197 __le64 sas_address;
198
199 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
200
29dd3609
EM
201 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
202 "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
203 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
204 ioc->name, le16_to_cpu(pg0->DevHandle)));
205 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
206 ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
207 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
208 ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
209 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
210 ioc->name, le16_to_cpu(pg0->Slot)));
211 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
212 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
213 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
214 ioc->name, pg0->TargetID));
215 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
216 ioc->name, pg0->Bus));
217 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
218 ioc->name, pg0->PhyNum));
219 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
220 ioc->name, le16_to_cpu(pg0->AccessStatus)));
221 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
222 ioc->name, le32_to_cpu(pg0->DeviceInfo)));
223 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
224 ioc->name, le16_to_cpu(pg0->Flags)));
225 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
226 ioc->name, pg0->PhysicalPort));
b5141128
CH
227}
228
d6ecdd63
PS
229static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
230{
29dd3609
EM
231 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
232 "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
233 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
234 ioc->name, pg1->PhysicalPort));
235 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
236 ioc->name, pg1->PhyIdentifier));
237 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
238 ioc->name, pg1->NegotiatedLinkRate));
239 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
240 ioc->name, pg1->ProgrammedLinkRate));
241 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
242 ioc->name, pg1->HwLinkRate));
243 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
244 ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
245 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
246 "Attached Device Handle=0x%X\n\n", ioc->name,
247 le16_to_cpu(pg1->AttachedDevHandle)));
b5141128 248}
b5141128 249
3eb0822c
KD
250/* inhibit sas firmware event handling */
251static void
252mptsas_fw_event_off(MPT_ADAPTER *ioc)
253{
254 unsigned long flags;
255
256 spin_lock_irqsave(&ioc->fw_event_lock, flags);
257 ioc->fw_events_off = 1;
258 ioc->sas_discovery_quiesce_io = 0;
259 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
260
261}
262
263/* enable sas firmware event handling */
264static void
265mptsas_fw_event_on(MPT_ADAPTER *ioc)
266{
267 unsigned long flags;
268
269 spin_lock_irqsave(&ioc->fw_event_lock, flags);
270 ioc->fw_events_off = 0;
271 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
272}
273
274/* queue a sas firmware event */
275static void
276mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
277 unsigned long delay)
278{
279 unsigned long flags;
280
281 spin_lock_irqsave(&ioc->fw_event_lock, flags);
282 list_add_tail(&fw_event->list, &ioc->fw_event_list);
283 INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
284 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n",
285 ioc->name, __func__, fw_event));
286 queue_delayed_work(ioc->fw_event_q, &fw_event->work,
287 delay);
288 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
289}
290
db7051b2
KD
291/* requeue a sas firmware event */
292static void
293mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
294 unsigned long delay)
295{
296 unsigned long flags;
297 spin_lock_irqsave(&ioc->fw_event_lock, flags);
298 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
299 "(fw_event=0x%p)\n", ioc->name, __func__, fw_event));
300 fw_event->retries++;
301 queue_delayed_work(ioc->fw_event_q, &fw_event->work,
302 msecs_to_jiffies(delay));
303 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
304}
305
3eb0822c
KD
306/* free memory assoicated to a sas firmware event */
307static void
308mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
309{
310 unsigned long flags;
311
312 spin_lock_irqsave(&ioc->fw_event_lock, flags);
313 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n",
314 ioc->name, __func__, fw_event));
315 list_del(&fw_event->list);
316 kfree(fw_event);
317 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
318}
319
320/* walk the firmware event queue, and either stop or wait for
321 * outstanding events to complete */
322static void
323mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
324{
325 struct fw_event_work *fw_event, *next;
326 struct mptsas_target_reset_event *target_reset_list, *n;
327 u8 flush_q;
328 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
329
330 /* flush the target_reset_list */
331 if (!list_empty(&hd->target_reset_list)) {
332 list_for_each_entry_safe(target_reset_list, n,
333 &hd->target_reset_list, list) {
334 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
335 "%s: removing target reset for id=%d\n",
336 ioc->name, __func__,
337 target_reset_list->sas_event_data.TargetID));
338 list_del(&target_reset_list->list);
339 kfree(target_reset_list);
340 }
341 }
342
343 if (list_empty(&ioc->fw_event_list) ||
344 !ioc->fw_event_q || in_interrupt())
345 return;
346
347 flush_q = 0;
348 list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
349 if (cancel_delayed_work(&fw_event->work))
350 mptsas_free_fw_event(ioc, fw_event);
351 else
352 flush_q = 1;
353 }
354 if (flush_q)
355 flush_workqueue(ioc->fw_event_q);
356}
357
358
e3094447
CH
359static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
360{
361 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
362 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
363}
364
365static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
366{
367 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
368 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
369}
370
e6b2d76a
ME
371/*
372 * mptsas_find_portinfo_by_handle
373 *
374 * This function should be called with the sas_topology_mutex already held
375 */
376static struct mptsas_portinfo *
377mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
378{
379 struct mptsas_portinfo *port_info, *rc=NULL;
380 int i;
381
382 list_for_each_entry(port_info, &ioc->sas_topology, list)
383 for (i = 0; i < port_info->num_phys; i++)
384 if (port_info->phy_info[i].identify.handle == handle) {
385 rc = port_info;
386 goto out;
387 }
388 out:
389 return rc;
390}
391
f9c34022
KD
392/**
393 * mptsas_find_portinfo_by_sas_address -
394 * @ioc: Pointer to MPT_ADAPTER structure
395 * @handle:
396 *
397 * This function should be called with the sas_topology_mutex already held
398 *
399 **/
400static struct mptsas_portinfo *
401mptsas_find_portinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
402{
403 struct mptsas_portinfo *port_info, *rc = NULL;
404 int i;
405
406 if (sas_address >= ioc->hba_port_sas_addr &&
407 sas_address < (ioc->hba_port_sas_addr +
408 ioc->hba_port_num_phy))
409 return ioc->hba_port_info;
410
411 mutex_lock(&ioc->sas_topology_mutex);
412 list_for_each_entry(port_info, &ioc->sas_topology, list)
413 for (i = 0; i < port_info->num_phys; i++)
414 if (port_info->phy_info[i].identify.sas_address ==
415 sas_address) {
416 rc = port_info;
417 goto out;
418 }
419 out:
420 mutex_unlock(&ioc->sas_topology_mutex);
421 return rc;
422}
423
bd23e94c
ME
424/*
425 * Returns true if there is a scsi end device
426 */
427static inline int
428mptsas_is_end_device(struct mptsas_devinfo * attached)
429{
547f9a21 430 if ((attached->sas_address) &&
bd23e94c
ME
431 (attached->device_info &
432 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
433 ((attached->device_info &
434 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
435 (attached->device_info &
436 MPI_SAS_DEVICE_INFO_STP_TARGET) |
437 (attached->device_info &
438 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
439 return 1;
440 else
441 return 0;
442}
443
547f9a21 444/* no mutex */
376ac830 445static void
d6ecdd63 446mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
547f9a21
EM
447{
448 struct mptsas_portinfo *port_info;
449 struct mptsas_phyinfo *phy_info;
450 u8 i;
451
452 if (!port_details)
453 return;
454
455 port_info = port_details->port_info;
456 phy_info = port_info->phy_info;
457
29dd3609 458 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
cadbd4a5 459 "bitmask=0x%016llX\n", ioc->name, __func__, port_details,
f99be43b
EM
460 port_details->num_phys, (unsigned long long)
461 port_details->phy_bitmask));
547f9a21
EM
462
463 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
464 if(phy_info->port_details != port_details)
465 continue;
466 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
3eb0822c 467 mptsas_set_rphy(ioc, phy_info, NULL);
547f9a21
EM
468 phy_info->port_details = NULL;
469 }
470 kfree(port_details);
471}
472
473static inline struct sas_rphy *
474mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
475{
476 if (phy_info->port_details)
477 return phy_info->port_details->rphy;
478 else
479 return NULL;
480}
481
482static inline void
d6ecdd63 483mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
547f9a21
EM
484{
485 if (phy_info->port_details) {
486 phy_info->port_details->rphy = rphy;
29dd3609
EM
487 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
488 ioc->name, rphy));
547f9a21
EM
489 }
490
547f9a21 491 if (rphy) {
c51d0bea
EM
492 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
493 &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
29dd3609
EM
494 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
495 ioc->name, rphy, rphy->dev.release));
547f9a21 496 }
547f9a21
EM
497}
498
499static inline struct sas_port *
500mptsas_get_port(struct mptsas_phyinfo *phy_info)
501{
502 if (phy_info->port_details)
503 return phy_info->port_details->port;
504 else
505 return NULL;
506}
507
508static inline void
d6ecdd63 509mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
547f9a21
EM
510{
511 if (phy_info->port_details)
512 phy_info->port_details->port = port;
513
547f9a21 514 if (port) {
c51d0bea
EM
515 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
516 &port->dev, MYIOC_s_FMT "add:", ioc->name));
29dd3609
EM
517 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
518 ioc->name, port, port->dev.release));
547f9a21 519 }
547f9a21
EM
520}
521
522static inline struct scsi_target *
523mptsas_get_starget(struct mptsas_phyinfo *phy_info)
524{
525 if (phy_info->port_details)
526 return phy_info->port_details->starget;
527 else
528 return NULL;
529}
530
531static inline void
532mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
533starget)
534{
535 if (phy_info->port_details)
536 phy_info->port_details->starget = starget;
537}
538
3eb0822c
KD
539/**
540 * mptsas_add_device_component -
541 * @ioc: Pointer to MPT_ADAPTER structure
542 * @channel: fw mapped id's
543 * @id:
544 * @sas_address:
545 * @device_info:
546 *
547 **/
548static void
549mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
550 u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id)
551{
552 struct mptsas_device_info *sas_info, *next;
553 struct scsi_device *sdev;
554 struct scsi_target *starget;
555 struct sas_rphy *rphy;
556
557 /*
558 * Delete all matching devices out of the list
559 */
560 mutex_lock(&ioc->sas_device_info_mutex);
561 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
562 list) {
a7938b0b
KD
563 if (!sas_info->is_logical_volume &&
564 (sas_info->sas_address == sas_address ||
565 (sas_info->fw.channel == channel &&
566 sas_info->fw.id == id))) {
3eb0822c
KD
567 list_del(&sas_info->list);
568 kfree(sas_info);
569 }
570 }
571
572 sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
573 if (!sas_info)
574 goto out;
575
576 /*
577 * Set Firmware mapping
578 */
579 sas_info->fw.id = id;
580 sas_info->fw.channel = channel;
581
582 sas_info->sas_address = sas_address;
583 sas_info->device_info = device_info;
584 sas_info->slot = slot;
585 sas_info->enclosure_logical_id = enclosure_logical_id;
586 INIT_LIST_HEAD(&sas_info->list);
587 list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
588
589 /*
590 * Set OS mapping
591 */
592 shost_for_each_device(sdev, ioc->sh) {
593 starget = scsi_target(sdev);
594 rphy = dev_to_rphy(starget->dev.parent);
595 if (rphy->identify.sas_address == sas_address) {
596 sas_info->os.id = starget->id;
597 sas_info->os.channel = starget->channel;
598 }
599 }
600
601 out:
602 mutex_unlock(&ioc->sas_device_info_mutex);
603 return;
604}
605
606/**
607 * mptsas_add_device_component_by_fw -
608 * @ioc: Pointer to MPT_ADAPTER structure
609 * @channel: fw mapped id's
610 * @id:
611 *
612 **/
613static void
614mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
615{
616 struct mptsas_devinfo sas_device;
617 struct mptsas_enclosure enclosure_info;
618 int rc;
619
620 rc = mptsas_sas_device_pg0(ioc, &sas_device,
621 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
622 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
623 (channel << 8) + id);
624 if (rc)
625 return;
626
627 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
628 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
629 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
630 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
631 sas_device.handle_enclosure);
632
633 mptsas_add_device_component(ioc, sas_device.channel,
634 sas_device.id, sas_device.sas_address, sas_device.device_info,
635 sas_device.slot, enclosure_info.enclosure_logical_id);
636}
637
a7938b0b 638/**
fc847ab4 639 * mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding each individual device to list
a7938b0b
KD
640 * @ioc: Pointer to MPT_ADAPTER structure
641 * @channel: fw mapped id's
642 * @id:
643 *
644 **/
645static void
646mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc,
647 struct scsi_target *starget)
648{
649 CONFIGPARMS cfg;
650 ConfigPageHeader_t hdr;
651 dma_addr_t dma_handle;
652 pRaidVolumePage0_t buffer = NULL;
653 int i;
654 RaidPhysDiskPage0_t phys_disk;
655 struct mptsas_device_info *sas_info, *next;
656
657 memset(&cfg, 0 , sizeof(CONFIGPARMS));
658 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
659 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
660 /* assumption that all volumes on channel = 0 */
661 cfg.pageAddr = starget->id;
662 cfg.cfghdr.hdr = &hdr;
663 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
664 cfg.timeout = 10;
665
666 if (mpt_config(ioc, &cfg) != 0)
667 goto out;
668
669 if (!hdr.PageLength)
670 goto out;
671
672 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
673 &dma_handle);
674
675 if (!buffer)
676 goto out;
677
678 cfg.physAddr = dma_handle;
679 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
680
681 if (mpt_config(ioc, &cfg) != 0)
682 goto out;
683
684 if (!buffer->NumPhysDisks)
685 goto out;
686
687 /*
688 * Adding entry for hidden components
689 */
690 for (i = 0; i < buffer->NumPhysDisks; i++) {
691
692 if (mpt_raid_phys_disk_pg0(ioc,
693 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
694 continue;
695
696 mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus,
697 phys_disk.PhysDiskID);
698
57e98513
KD
699 mutex_lock(&ioc->sas_device_info_mutex);
700 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
701 list) {
702 if (!sas_info->is_logical_volume &&
703 (sas_info->fw.channel == phys_disk.PhysDiskBus &&
704 sas_info->fw.id == phys_disk.PhysDiskID)) {
705 sas_info->is_hidden_raid_component = 1;
706 sas_info->volume_id = starget->id;
707 }
708 }
709 mutex_unlock(&ioc->sas_device_info_mutex);
710
a7938b0b
KD
711 }
712
713 /*
714 * Delete all matching devices out of the list
715 */
716 mutex_lock(&ioc->sas_device_info_mutex);
717 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
718 list) {
719 if (sas_info->is_logical_volume && sas_info->fw.id ==
720 starget->id) {
721 list_del(&sas_info->list);
722 kfree(sas_info);
723 }
724 }
725
726 sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
727 if (sas_info) {
728 sas_info->fw.id = starget->id;
729 sas_info->os.id = starget->id;
730 sas_info->os.channel = starget->channel;
731 sas_info->is_logical_volume = 1;
732 INIT_LIST_HEAD(&sas_info->list);
733 list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
734 }
735 mutex_unlock(&ioc->sas_device_info_mutex);
736
737 out:
738 if (buffer)
739 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
740 dma_handle);
741}
742
3eb0822c
KD
743/**
744 * mptsas_add_device_component_starget -
745 * @ioc: Pointer to MPT_ADAPTER structure
746 * @starget:
747 *
748 **/
749static void
750mptsas_add_device_component_starget(MPT_ADAPTER *ioc,
751 struct scsi_target *starget)
752{
753 VirtTarget *vtarget;
754 struct sas_rphy *rphy;
755 struct mptsas_phyinfo *phy_info = NULL;
756 struct mptsas_enclosure enclosure_info;
757
758 rphy = dev_to_rphy(starget->dev.parent);
759 vtarget = starget->hostdata;
760 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
761 rphy->identify.sas_address);
762 if (!phy_info)
763 return;
764
765 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
766 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
767 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
768 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
769 phy_info->attached.handle_enclosure);
770
771 mptsas_add_device_component(ioc, phy_info->attached.channel,
772 phy_info->attached.id, phy_info->attached.sas_address,
773 phy_info->attached.device_info,
774 phy_info->attached.slot, enclosure_info.enclosure_logical_id);
775}
776
57e98513 777/**
fc847ab4 778 * mptsas_del_device_component_by_os - Once a device has been removed, we mark the entry in the list as being cached
57e98513
KD
779 * @ioc: Pointer to MPT_ADAPTER structure
780 * @channel: os mapped id's
781 * @id:
782 *
783 **/
784static void
785mptsas_del_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
786{
787 struct mptsas_device_info *sas_info, *next;
788
789 /*
790 * Set is_cached flag
791 */
792 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
793 list) {
794 if (sas_info->os.channel == channel && sas_info->os.id == id)
795 sas_info->is_cached = 1;
796 }
797}
798
3eb0822c
KD
799/**
800 * mptsas_del_device_components - Cleaning the list
801 * @ioc: Pointer to MPT_ADAPTER structure
802 *
803 **/
804static void
805mptsas_del_device_components(MPT_ADAPTER *ioc)
806{
807 struct mptsas_device_info *sas_info, *next;
808
809 mutex_lock(&ioc->sas_device_info_mutex);
810 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
811 list) {
812 list_del(&sas_info->list);
813 kfree(sas_info);
814 }
815 mutex_unlock(&ioc->sas_device_info_mutex);
816}
817
547f9a21
EM
818
819/*
820 * mptsas_setup_wide_ports
821 *
822 * Updates for new and existing narrow/wide port configuration
823 * in the sas_topology
824 */
376ac830 825static void
547f9a21
EM
826mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
827{
828 struct mptsas_portinfo_details * port_details;
829 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
830 u64 sas_address;
831 int i, j;
832
833 mutex_lock(&ioc->sas_topology_mutex);
834
835 phy_info = port_info->phy_info;
836 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
837 if (phy_info->attached.handle)
838 continue;
839 port_details = phy_info->port_details;
840 if (!port_details)
841 continue;
842 if (port_details->num_phys < 2)
843 continue;
844 /*
845 * Removing a phy from a port, letting the last
846 * phy be removed by firmware events.
847 */
29dd3609
EM
848 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
849 "%s: [%p]: deleting phy = %d\n",
cadbd4a5 850 ioc->name, __func__, port_details, i));
547f9a21
EM
851 port_details->num_phys--;
852 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
853 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
854 sas_port_delete_phy(port_details->port, phy_info->phy);
855 phy_info->port_details = NULL;
856 }
857
858 /*
859 * Populate and refresh the tree
860 */
861 phy_info = port_info->phy_info;
862 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
863 sas_address = phy_info->attached.sas_address;
29dd3609
EM
864 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
865 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
866 if (!sas_address)
867 continue;
868 port_details = phy_info->port_details;
869 /*
870 * Forming a port
871 */
872 if (!port_details) {
2f187862
KD
873 port_details = kzalloc(sizeof(struct
874 mptsas_portinfo_details), GFP_KERNEL);
547f9a21
EM
875 if (!port_details)
876 goto out;
877 port_details->num_phys = 1;
878 port_details->port_info = port_info;
547f9a21
EM
879 if (phy_info->phy_id < 64 )
880 port_details->phy_bitmask |=
881 (1 << phy_info->phy_id);
882 phy_info->sas_port_add_phy=1;
29dd3609 883 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
f99be43b 884 "phy_id=%d sas_address=0x%018llX\n",
29dd3609 885 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
886 phy_info->port_details = port_details;
887 }
888
889 if (i == port_info->num_phys - 1)
890 continue;
891 phy_info_cmp = &port_info->phy_info[i + 1];
892 for (j = i + 1 ; j < port_info->num_phys ; j++,
893 phy_info_cmp++) {
894 if (!phy_info_cmp->attached.sas_address)
895 continue;
896 if (sas_address != phy_info_cmp->attached.sas_address)
897 continue;
898 if (phy_info_cmp->port_details == port_details )
899 continue;
29dd3609 900 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 901 "\t\tphy_id=%d sas_address=0x%018llX\n",
29dd3609 902 ioc->name, j, (unsigned long long)
f99be43b 903 phy_info_cmp->attached.sas_address));
547f9a21
EM
904 if (phy_info_cmp->port_details) {
905 port_details->rphy =
906 mptsas_get_rphy(phy_info_cmp);
907 port_details->port =
908 mptsas_get_port(phy_info_cmp);
909 port_details->starget =
910 mptsas_get_starget(phy_info_cmp);
547f9a21
EM
911 port_details->num_phys =
912 phy_info_cmp->port_details->num_phys;
547f9a21
EM
913 if (!phy_info_cmp->port_details->num_phys)
914 kfree(phy_info_cmp->port_details);
915 } else
916 phy_info_cmp->sas_port_add_phy=1;
917 /*
918 * Adding a phy to a port
919 */
920 phy_info_cmp->port_details = port_details;
921 if (phy_info_cmp->phy_id < 64 )
922 port_details->phy_bitmask |=
923 (1 << phy_info_cmp->phy_id);
924 port_details->num_phys++;
925 }
926 }
927
928 out:
929
547f9a21
EM
930 for (i = 0; i < port_info->num_phys; i++) {
931 port_details = port_info->phy_info[i].port_details;
932 if (!port_details)
933 continue;
29dd3609 934 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 935 "%s: [%p]: phy_id=%02d num_phys=%02d "
cadbd4a5 936 "bitmask=0x%016llX\n", ioc->name, __func__,
f99be43b
EM
937 port_details, i, port_details->num_phys,
938 (unsigned long long)port_details->phy_bitmask));
29dd3609
EM
939 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
940 ioc->name, port_details->port, port_details->rphy));
547f9a21 941 }
29dd3609 942 dsaswideprintk(ioc, printk("\n"));
547f9a21
EM
943 mutex_unlock(&ioc->sas_topology_mutex);
944}
945
df9e062a
EM
946/**
947 * csmisas_find_vtarget
948 *
949 * @ioc
950 * @volume_id
951 * @volume_bus
952 *
953 **/
954static VirtTarget *
955mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
956{
957 struct scsi_device *sdev;
a69de507 958 VirtDevice *vdevice;
df9e062a
EM
959 VirtTarget *vtarget = NULL;
960
961 shost_for_each_device(sdev, ioc->sh) {
e7deff33
KD
962 vdevice = sdev->hostdata;
963 if ((vdevice == NULL) ||
964 (vdevice->vtarget == NULL))
df9e062a 965 continue;
a7938b0b
KD
966 if ((vdevice->vtarget->tflags &
967 MPT_TARGET_FLAGS_RAID_COMPONENT ||
968 vdevice->vtarget->raidVolume))
969 continue;
a69de507 970 if (vdevice->vtarget->id == id &&
e7deff33 971 vdevice->vtarget->channel == channel)
a69de507 972 vtarget = vdevice->vtarget;
df9e062a
EM
973 }
974 return vtarget;
975}
976
3eb0822c
KD
977static void
978mptsas_queue_device_delete(MPT_ADAPTER *ioc,
979 MpiEventDataSasDeviceStatusChange_t *sas_event_data)
980{
981 struct fw_event_work *fw_event;
982 int sz;
983
984 sz = offsetof(struct fw_event_work, event_data) +
985 sizeof(MpiEventDataSasDeviceStatusChange_t);
986 fw_event = kzalloc(sz, GFP_ATOMIC);
987 if (!fw_event) {
988 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
989 ioc->name, __func__, __LINE__);
990 return;
991 }
992 memcpy(fw_event->event_data, sas_event_data,
993 sizeof(MpiEventDataSasDeviceStatusChange_t));
994 fw_event->event = MPI_EVENT_SAS_DEVICE_STATUS_CHANGE;
995 fw_event->ioc = ioc;
996 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
997}
998
eedf92b9
KD
999static void
1000mptsas_queue_rescan(MPT_ADAPTER *ioc)
1001{
1002 struct fw_event_work *fw_event;
1003 int sz;
1004
1005 sz = offsetof(struct fw_event_work, event_data);
1006 fw_event = kzalloc(sz, GFP_ATOMIC);
1007 if (!fw_event) {
1008 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
1009 ioc->name, __func__, __LINE__);
1010 return;
1011 }
1012 fw_event->event = -1;
1013 fw_event->ioc = ioc;
1014 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
1015}
1016
3eb0822c 1017
df9e062a
EM
1018/**
1019 * mptsas_target_reset
1020 *
1021 * Issues TARGET_RESET to end device using handshaking method
1022 *
1023 * @ioc
1024 * @channel
1025 * @id
1026 *
1027 * Returns (1) success
1028 * (0) failure
1029 *
1030 **/
1031static int
1032mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
1033{
1034 MPT_FRAME_HDR *mf;
1035 SCSITaskMgmt_t *pScsiTm;
ea2a788d
KD
1036 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0)
1037 return 0;
1038
df9e062a 1039
e7deff33
KD
1040 mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
1041 if (mf == NULL) {
1042 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
ea2a788d
KD
1043 "%s, no msg frames @%d!!\n", ioc->name,
1044 __func__, __LINE__));
1045 goto out_fail;
df9e062a
EM
1046 }
1047
ea2a788d
KD
1048 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
1049 ioc->name, mf));
1050
df9e062a
EM
1051 /* Format the Request
1052 */
1053 pScsiTm = (SCSITaskMgmt_t *) mf;
1054 memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
1055 pScsiTm->TargetID = id;
1056 pScsiTm->Bus = channel;
1057 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1058 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
1059 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
1060
d6ecdd63 1061 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
df9e062a 1062
ea2a788d
KD
1063 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1064 "TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
1065 ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
1066
e7deff33 1067 mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
df9e062a
EM
1068
1069 return 1;
ea2a788d
KD
1070
1071 out_fail:
1072
1073 mpt_clear_taskmgmt_in_progress_flag(ioc);
1074 return 0;
df9e062a
EM
1075}
1076
1077/**
1078 * mptsas_target_reset_queue
1079 *
1080 * Receive request for TARGET_RESET after recieving an firmware
1081 * event NOT_RESPONDING_EVENT, then put command in link list
1082 * and queue if task_queue already in use.
1083 *
1084 * @ioc
1085 * @sas_event_data
1086 *
1087 **/
547f9a21 1088static void
df9e062a
EM
1089mptsas_target_reset_queue(MPT_ADAPTER *ioc,
1090 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
547f9a21 1091{
e7eae9f6 1092 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a
EM
1093 VirtTarget *vtarget = NULL;
1094 struct mptsas_target_reset_event *target_reset_list;
1095 u8 id, channel;
547f9a21 1096
df9e062a
EM
1097 id = sas_event_data->TargetID;
1098 channel = sas_event_data->Bus;
1099
1100 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
1101 return;
1102
1103 vtarget->deleted = 1; /* block IO */
1104
2f187862 1105 target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
df9e062a
EM
1106 GFP_ATOMIC);
1107 if (!target_reset_list) {
e7deff33
KD
1108 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
1109 "%s, failed to allocate mem @%d..!!\n",
1110 ioc->name, __func__, __LINE__));
df9e062a
EM
1111 return;
1112 }
1113
1114 memcpy(&target_reset_list->sas_event_data, sas_event_data,
1115 sizeof(*sas_event_data));
1116 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
1117
e7deff33 1118 target_reset_list->time_count = jiffies;
df9e062a
EM
1119
1120 if (mptsas_target_reset(ioc, channel, id)) {
1121 target_reset_list->target_reset_issued = 1;
df9e062a
EM
1122 }
1123}
1124
1125/**
fc847ab4 1126 * mptsas_taskmgmt_complete - complete SAS task management function
e7deff33 1127 * @ioc: Pointer to MPT_ADAPTER structure
df9e062a 1128 *
fc847ab4
JB
1129 * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, enable work
1130 * queue to finish off removing device from upper layers. then send next
1131 * TARGET_RESET in the queue.
df9e062a 1132 **/
e7deff33
KD
1133static int
1134mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
df9e062a 1135{
e7eae9f6 1136 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a 1137 struct list_head *head = &hd->target_reset_list;
df9e062a 1138 u8 id, channel;
e7deff33
KD
1139 struct mptsas_target_reset_event *target_reset_list;
1140 SCSITaskMgmtReply_t *pScsiTmReply;
1141
1142 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: "
1143 "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
1144
1145 pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
1146 if (pScsiTmReply) {
1147 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1148 "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
1149 "\ttask_type = 0x%02X, iocstatus = 0x%04X "
1150 "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
1151 "term_cmnds = %d\n", ioc->name,
1152 pScsiTmReply->Bus, pScsiTmReply->TargetID,
1153 pScsiTmReply->TaskType,
1154 le16_to_cpu(pScsiTmReply->IOCStatus),
1155 le32_to_cpu(pScsiTmReply->IOCLogInfo),
1156 pScsiTmReply->ResponseCode,
1157 le32_to_cpu(pScsiTmReply->TerminationCount)));
1158
1159 if (pScsiTmReply->ResponseCode)
1160 mptscsih_taskmgmt_response_code(ioc,
1161 pScsiTmReply->ResponseCode);
1162 }
1163
1164 if (pScsiTmReply && (pScsiTmReply->TaskType ==
1165 MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
1166 MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
1167 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
1168 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
1169 memcpy(ioc->taskmgmt_cmds.reply, mr,
1170 min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
1171 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
1172 ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
1173 complete(&ioc->taskmgmt_cmds.done);
1174 return 1;
1175 }
1176 return 0;
1177 }
1178
1179 mpt_clear_taskmgmt_in_progress_flag(ioc);
df9e062a
EM
1180
1181 if (list_empty(head))
e7deff33
KD
1182 return 1;
1183
1184 target_reset_list = list_entry(head->next,
1185 struct mptsas_target_reset_event, list);
df9e062a 1186
e7deff33
KD
1187 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1188 "TaskMgmt: completed (%d seconds)\n",
1189 ioc->name, jiffies_to_msecs(jiffies -
1190 target_reset_list->time_count)/1000));
df9e062a 1191
e7deff33
KD
1192 id = pScsiTmReply->TargetID;
1193 channel = pScsiTmReply->Bus;
1194 target_reset_list->time_count = jiffies;
df9e062a
EM
1195
1196 /*
1197 * retry target reset
1198 */
1199 if (!target_reset_list->target_reset_issued) {
e7deff33 1200 if (mptsas_target_reset(ioc, channel, id))
df9e062a 1201 target_reset_list->target_reset_issued = 1;
e7deff33 1202 return 1;
df9e062a
EM
1203 }
1204
1205 /*
1206 * enable work queue to remove device from upper layers
1207 */
1208 list_del(&target_reset_list->list);
3eb0822c
KD
1209 if ((mptsas_find_vtarget(ioc, channel, id)) && !ioc->fw_events_off)
1210 mptsas_queue_device_delete(ioc,
1211 &target_reset_list->sas_event_data);
ea2a788d 1212
e7deff33 1213
df9e062a
EM
1214 /*
1215 * issue target reset to next device in the queue
1216 */
1217
1218 head = &hd->target_reset_list;
1219 if (list_empty(head))
e7deff33 1220 return 1;
df9e062a
EM
1221
1222 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
1223 list);
1224
e7deff33
KD
1225 id = target_reset_list->sas_event_data.TargetID;
1226 channel = target_reset_list->sas_event_data.Bus;
1227 target_reset_list->time_count = jiffies;
df9e062a 1228
e7deff33 1229 if (mptsas_target_reset(ioc, channel, id))
df9e062a 1230 target_reset_list->target_reset_issued = 1;
df9e062a 1231
e7deff33 1232 return 1;
df9e062a
EM
1233}
1234
1235/**
1236 * mptscsih_ioc_reset
1237 *
1238 * @ioc
1239 * @reset_phase
1240 *
1241 **/
1242static int
1243mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1244{
ba76ef24 1245 MPT_SCSI_HOST *hd;
df9e062a
EM
1246 int rc;
1247
1248 rc = mptscsih_ioc_reset(ioc, reset_phase);
3eb0822c
KD
1249 if ((ioc->bus_type != SAS) || (!rc))
1250 return rc;
df9e062a 1251
e7eae9f6 1252 hd = shost_priv(ioc->sh);
ba76ef24 1253 if (!hd->ioc)
df9e062a
EM
1254 goto out;
1255
3eb0822c
KD
1256 switch (reset_phase) {
1257 case MPT_IOC_SETUP_RESET:
1258 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1259 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
1260 mptsas_fw_event_off(ioc);
1261 break;
1262 case MPT_IOC_PRE_RESET:
1263 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1264 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
1265 break;
1266 case MPT_IOC_POST_RESET:
1267 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1268 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
1269 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
1270 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET;
1271 complete(&ioc->sas_mgmt.done);
1272 }
1273 mptsas_cleanup_fw_event_q(ioc);
eedf92b9 1274 mptsas_queue_rescan(ioc);
3eb0822c
KD
1275 mptsas_fw_event_on(ioc);
1276 break;
1277 default:
1278 break;
547f9a21 1279 }
df9e062a
EM
1280
1281 out:
1282 return rc;
547f9a21
EM
1283}
1284
3eb0822c
KD
1285
1286/**
1287 * enum device_state -
1288 * @DEVICE_RETRY: need to retry the TUR
1289 * @DEVICE_ERROR: TUR return error, don't add device
1290 * @DEVICE_READY: device can be added
1291 *
1292 */
1293enum device_state{
1294 DEVICE_RETRY,
1295 DEVICE_ERROR,
1296 DEVICE_READY,
1297};
1298
e3094447 1299static int
52435430 1300mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
e3094447
CH
1301 u32 form, u32 form_specific)
1302{
1303 ConfigExtendedPageHeader_t hdr;
1304 CONFIGPARMS cfg;
1305 SasEnclosurePage0_t *buffer;
1306 dma_addr_t dma_handle;
1307 int error;
1308 __le64 le_identifier;
1309
1310 memset(&hdr, 0, sizeof(hdr));
1311 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
1312 hdr.PageNumber = 0;
1313 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1314 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
1315
1316 cfg.cfghdr.ehdr = &hdr;
1317 cfg.physAddr = -1;
1318 cfg.pageAddr = form + form_specific;
1319 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1320 cfg.dir = 0; /* read */
1321 cfg.timeout = 10;
1322
1323 error = mpt_config(ioc, &cfg);
1324 if (error)
1325 goto out;
1326 if (!hdr.ExtPageLength) {
1327 error = -ENXIO;
1328 goto out;
1329 }
1330
1331 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1332 &dma_handle);
1333 if (!buffer) {
1334 error = -ENOMEM;
1335 goto out;
1336 }
1337
1338 cfg.physAddr = dma_handle;
1339 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1340
1341 error = mpt_config(ioc, &cfg);
1342 if (error)
1343 goto out_free_consistent;
1344
1345 /* save config data */
1346 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
1347 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
1348 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
1349 enclosure->flags = le16_to_cpu(buffer->Flags);
1350 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
1351 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
1352 enclosure->start_id = buffer->StartTargetID;
1353 enclosure->start_channel = buffer->StartBus;
1354 enclosure->sep_id = buffer->SEPTargetID;
1355 enclosure->sep_channel = buffer->SEPBus;
1356
1357 out_free_consistent:
1358 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1359 buffer, dma_handle);
1360 out:
1361 return error;
1362}
b5141128 1363
3eb0822c
KD
1364/**
1365 * mptsas_add_end_device - report a new end device to sas transport layer
1366 * @ioc: Pointer to MPT_ADAPTER structure
1367 * @phy_info: decribes attached device
1368 *
1369 * return (0) success (1) failure
1370 *
1371 **/
1372static int
1373mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1374{
1375 struct sas_rphy *rphy;
1376 struct sas_port *port;
1377 struct sas_identify identify;
1378 char *ds = NULL;
1379 u8 fw_id;
1380
1381 if (!phy_info) {
1382 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1383 "%s: exit at line=%d\n", ioc->name,
1384 __func__, __LINE__));
1385 return 1;
1386 }
1387
1388 fw_id = phy_info->attached.id;
1389
1390 if (mptsas_get_rphy(phy_info)) {
1391 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1392 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1393 __func__, fw_id, __LINE__));
1394 return 2;
1395 }
1396
1397 port = mptsas_get_port(phy_info);
1398 if (!port) {
1399 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1400 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1401 __func__, fw_id, __LINE__));
1402 return 3;
1403 }
1404
1405 if (phy_info->attached.device_info &
1406 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1407 ds = "ssp";
1408 if (phy_info->attached.device_info &
1409 MPI_SAS_DEVICE_INFO_STP_TARGET)
1410 ds = "stp";
1411 if (phy_info->attached.device_info &
1412 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1413 ds = "sata";
1414
1415 printk(MYIOC_s_INFO_FMT "attaching %s device: fw_channel %d, fw_id %d,"
1416 " phy %d, sas_addr 0x%llx\n", ioc->name, ds,
1417 phy_info->attached.channel, phy_info->attached.id,
1418 phy_info->attached.phy_id, (unsigned long long)
1419 phy_info->attached.sas_address);
1420
1421 mptsas_parse_device_info(&identify, &phy_info->attached);
1422 rphy = sas_end_device_alloc(port);
1423 if (!rphy) {
1424 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1425 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1426 __func__, fw_id, __LINE__));
1427 return 5; /* non-fatal: an rphy can be added later */
1428 }
1429
1430 rphy->identify = identify;
1431 if (sas_rphy_add(rphy)) {
1432 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1433 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1434 __func__, fw_id, __LINE__));
1435 sas_rphy_free(rphy);
1436 return 6;
1437 }
1438 mptsas_set_rphy(ioc, phy_info, rphy);
1439 return 0;
1440}
1441
1442/**
fc847ab4 1443 * mptsas_del_end_device - report a deleted end device to sas transport layer
3eb0822c
KD
1444 * @ioc: Pointer to MPT_ADAPTER structure
1445 * @phy_info: decribes attached device
1446 *
1447 **/
1448static void
1449mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1450{
1451 struct sas_rphy *rphy;
1452 struct sas_port *port;
1453 struct mptsas_portinfo *port_info;
1454 struct mptsas_phyinfo *phy_info_parent;
1455 int i;
1456 char *ds = NULL;
1457 u8 fw_id;
1458 u64 sas_address;
1459
1460 if (!phy_info)
1461 return;
1462
1463 fw_id = phy_info->attached.id;
1464 sas_address = phy_info->attached.sas_address;
1465
1466 if (!phy_info->port_details) {
1467 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1468 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1469 __func__, fw_id, __LINE__));
1470 return;
1471 }
1472 rphy = mptsas_get_rphy(phy_info);
1473 if (!rphy) {
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;
1478 }
1479
1480 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR
1481 || phy_info->attached.device_info
1482 & MPI_SAS_DEVICE_INFO_SMP_INITIATOR
1483 || phy_info->attached.device_info
1484 & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1485 ds = "initiator";
1486 if (phy_info->attached.device_info &
1487 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1488 ds = "ssp";
1489 if (phy_info->attached.device_info &
1490 MPI_SAS_DEVICE_INFO_STP_TARGET)
1491 ds = "stp";
1492 if (phy_info->attached.device_info &
1493 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1494 ds = "sata";
1495
1496 dev_printk(KERN_DEBUG, &rphy->dev, MYIOC_s_FMT
1497 "removing %s device: fw_channel %d, fw_id %d, phy %d,"
1498 "sas_addr 0x%llx\n", ioc->name, ds, phy_info->attached.channel,
1499 phy_info->attached.id, phy_info->attached.phy_id,
1500 (unsigned long long) sas_address);
1501
1502 port = mptsas_get_port(phy_info);
1503 if (!port) {
1504 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1505 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1506 __func__, fw_id, __LINE__));
1507 return;
1508 }
1509 port_info = phy_info->portinfo;
1510 phy_info_parent = port_info->phy_info;
1511 for (i = 0; i < port_info->num_phys; i++, phy_info_parent++) {
1512 if (!phy_info_parent->phy)
1513 continue;
1514 if (phy_info_parent->attached.sas_address !=
1515 sas_address)
1516 continue;
1517 dev_printk(KERN_DEBUG, &phy_info_parent->phy->dev,
1518 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n",
1519 ioc->name, phy_info_parent->phy_id,
1520 phy_info_parent->phy);
1521 sas_port_delete_phy(port, phy_info_parent->phy);
1522 }
1523
1524 dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
1525 "delete port %d, sas_addr (0x%llx)\n", ioc->name,
1526 port->port_identifier, (unsigned long long)sas_address);
1527 sas_port_delete(port);
1528 mptsas_set_port(ioc, phy_info, NULL);
1529 mptsas_port_delete(ioc, phy_info->port_details);
1530}
1531
1532struct mptsas_phyinfo *
1533mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
1534 struct mptsas_devinfo *sas_device)
1535{
1536 struct mptsas_phyinfo *phy_info;
1537 struct mptsas_portinfo *port_info;
1538 int i;
1539
1540 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
1541 sas_device->sas_address);
1542 if (!phy_info)
1543 goto out;
1544 port_info = phy_info->portinfo;
1545 if (!port_info)
1546 goto out;
1547 mutex_lock(&ioc->sas_topology_mutex);
1548 for (i = 0; i < port_info->num_phys; i++) {
1549 if (port_info->phy_info[i].attached.sas_address !=
1550 sas_device->sas_address)
1551 continue;
1552 port_info->phy_info[i].attached.channel = sas_device->channel;
1553 port_info->phy_info[i].attached.id = sas_device->id;
1554 port_info->phy_info[i].attached.sas_address =
1555 sas_device->sas_address;
1556 port_info->phy_info[i].attached.handle = sas_device->handle;
1557 port_info->phy_info[i].attached.handle_parent =
1558 sas_device->handle_parent;
1559 port_info->phy_info[i].attached.handle_enclosure =
1560 sas_device->handle_enclosure;
1561 }
1562 mutex_unlock(&ioc->sas_topology_mutex);
1563 out:
1564 return phy_info;
1565}
1566
1567/**
1568 * mptsas_firmware_event_work - work thread for processing fw events
1569 * @work: work queue payload containing info describing the event
1570 * Context: user
1571 *
1572 */
1573static void
1574mptsas_firmware_event_work(struct work_struct *work)
1575{
1576 struct fw_event_work *fw_event =
1577 container_of(work, struct fw_event_work, work.work);
1578 MPT_ADAPTER *ioc = fw_event->ioc;
1579
eedf92b9
KD
1580 /* special rescan topology handling */
1581 if (fw_event->event == -1) {
1582 if (ioc->in_rescan) {
1583 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1584 "%s: rescan ignored as it is in progress\n",
1585 ioc->name, __func__));
1586 return;
1587 }
1588 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: rescan after "
1589 "reset\n", ioc->name, __func__));
1590 ioc->in_rescan = 1;
1591 mptsas_not_responding_devices(ioc);
1592 mptsas_scan_sas_topology(ioc);
1593 ioc->in_rescan = 0;
1594 mptsas_free_fw_event(ioc, fw_event);
1595 return;
1596 }
3eb0822c
KD
1597
1598 /* events handling turned off during host reset */
1599 if (ioc->fw_events_off) {
1600 mptsas_free_fw_event(ioc, fw_event);
1601 return;
1602 }
1603
1604 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_event=(0x%p), "
1605 "event = (0x%02x)\n", ioc->name, __func__, fw_event,
1606 (fw_event->event & 0xFF)));
1607
1608 switch (fw_event->event) {
1609 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1610 mptsas_send_sas_event(fw_event);
1611 break;
1612 case MPI_EVENT_INTEGRATED_RAID:
1613 mptsas_send_raid_event(fw_event);
1614 break;
1615 case MPI_EVENT_IR2:
1616 mptsas_send_ir2_event(fw_event);
1617 break;
1618 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1619 mptbase_sas_persist_operation(ioc,
1620 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1621 mptsas_free_fw_event(ioc, fw_event);
1622 break;
db7051b2
KD
1623 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
1624 mptsas_broadcast_primative_work(fw_event);
1625 break;
f9c34022
KD
1626 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
1627 mptsas_send_expander_event(fw_event);
1628 break;
1629 case MPI_EVENT_SAS_PHY_LINK_STATUS:
1630 mptsas_send_link_status_event(fw_event);
1631 break;
57e98513
KD
1632 case MPI_EVENT_QUEUE_FULL:
1633 mptsas_handle_queue_full_event(fw_event);
1634 break;
3eb0822c
KD
1635 }
1636}
1637
1638
1639
f013db32
JB
1640static int
1641mptsas_slave_configure(struct scsi_device *sdev)
1642{
3eb0822c
KD
1643 struct Scsi_Host *host = sdev->host;
1644 MPT_SCSI_HOST *hd = shost_priv(host);
1645 MPT_ADAPTER *ioc = hd->ioc;
a7938b0b 1646 VirtDevice *vdevice = sdev->hostdata;
3c0c25b9 1647
a7938b0b
KD
1648 if (vdevice->vtarget->deleted) {
1649 sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n");
1650 vdevice->vtarget->deleted = 0;
1651 }
1652
1653 /*
1654 * RAID volumes placed beyond the last expected port.
1655 * Ignore sending sas mode pages in that case..
1656 */
1657 if (sdev->channel == MPTSAS_RAID_CHANNEL) {
1658 mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev));
e8bf3941 1659 goto out;
a7938b0b 1660 }
e8bf3941
JB
1661
1662 sas_read_port_mode_page(sdev);
f013db32 1663
3eb0822c
KD
1664 mptsas_add_device_component_starget(ioc, scsi_target(sdev));
1665
e8bf3941 1666 out:
f013db32
JB
1667 return mptscsih_slave_configure(sdev);
1668}
1669
547f9a21
EM
1670static int
1671mptsas_target_alloc(struct scsi_target *starget)
1672{
1673 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 1674 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21 1675 VirtTarget *vtarget;
793955f5 1676 u8 id, channel;
547f9a21
EM
1677 struct sas_rphy *rphy;
1678 struct mptsas_portinfo *p;
1679 int i;
e80b002b 1680 MPT_ADAPTER *ioc = hd->ioc;
547f9a21
EM
1681
1682 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
1683 if (!vtarget)
1684 return -ENOMEM;
1685
1686 vtarget->starget = starget;
e80b002b 1687 vtarget->ioc_id = ioc->id;
793955f5
EM
1688 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
1689 id = starget->id;
547f9a21
EM
1690 channel = 0;
1691
793955f5
EM
1692 /*
1693 * RAID volumes placed beyond the last expected port.
1694 */
1695 if (starget->channel == MPTSAS_RAID_CHANNEL) {
a7938b0b
KD
1696 if (!ioc->raid_data.pIocPg2) {
1697 kfree(vtarget);
1698 return -ENXIO;
1699 }
1700 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
1701 if (id == ioc->raid_data.pIocPg2->
1702 RaidVolume[i].VolumeID) {
1703 channel = ioc->raid_data.pIocPg2->
1704 RaidVolume[i].VolumeBus;
1705 }
1706 }
1707 vtarget->raidVolume = 1;
547f9a21 1708 goto out;
793955f5 1709 }
547f9a21
EM
1710
1711 rphy = dev_to_rphy(starget->dev.parent);
e80b002b
EM
1712 mutex_lock(&ioc->sas_topology_mutex);
1713 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
1714 for (i = 0; i < p->num_phys; i++) {
1715 if (p->phy_info[i].attached.sas_address !=
1716 rphy->identify.sas_address)
1717 continue;
793955f5 1718 id = p->phy_info[i].attached.id;
547f9a21
EM
1719 channel = p->phy_info[i].attached.channel;
1720 mptsas_set_starget(&p->phy_info[i], starget);
1721
1722 /*
1723 * Exposing hidden raid components
1724 */
e80b002b
EM
1725 if (mptscsih_is_phys_disk(ioc, channel, id)) {
1726 id = mptscsih_raid_id_to_num(ioc,
793955f5 1727 channel, id);
547f9a21
EM
1728 vtarget->tflags |=
1729 MPT_TARGET_FLAGS_RAID_COMPONENT;
b506ade9 1730 p->phy_info[i].attached.phys_disk_num = id;
547f9a21 1731 }
e80b002b 1732 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
1733 goto out;
1734 }
1735 }
e80b002b 1736 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
1737
1738 kfree(vtarget);
1739 return -ENXIO;
1740
1741 out:
793955f5
EM
1742 vtarget->id = id;
1743 vtarget->channel = channel;
547f9a21
EM
1744 starget->hostdata = vtarget;
1745 return 0;
1746}
1747
1748static void
1749mptsas_target_destroy(struct scsi_target *starget)
1750{
1751 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 1752 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21
EM
1753 struct sas_rphy *rphy;
1754 struct mptsas_portinfo *p;
1755 int i;
3eb0822c
KD
1756 MPT_ADAPTER *ioc = hd->ioc;
1757 VirtTarget *vtarget;
547f9a21
EM
1758
1759 if (!starget->hostdata)
1760 return;
1761
3eb0822c
KD
1762 vtarget = starget->hostdata;
1763
57e98513
KD
1764 mptsas_del_device_component_by_os(ioc, starget->channel,
1765 starget->id);
1766
3eb0822c 1767
e8bf3941 1768 if (starget->channel == MPTSAS_RAID_CHANNEL)
547f9a21
EM
1769 goto out;
1770
1771 rphy = dev_to_rphy(starget->dev.parent);
e80b002b 1772 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
1773 for (i = 0; i < p->num_phys; i++) {
1774 if (p->phy_info[i].attached.sas_address !=
1775 rphy->identify.sas_address)
1776 continue;
3eb0822c
KD
1777
1778 starget_printk(KERN_INFO, starget, MYIOC_s_FMT
1779 "delete device: fw_channel %d, fw_id %d, phy %d, "
1780 "sas_addr 0x%llx\n", ioc->name,
1781 p->phy_info[i].attached.channel,
1782 p->phy_info[i].attached.id,
1783 p->phy_info[i].attached.phy_id, (unsigned long long)
1784 p->phy_info[i].attached.sas_address);
1785
547f9a21 1786 mptsas_set_starget(&p->phy_info[i], NULL);
547f9a21
EM
1787 }
1788 }
1789
1790 out:
3eb0822c 1791 vtarget->starget = NULL;
547f9a21
EM
1792 kfree(starget->hostdata);
1793 starget->hostdata = NULL;
1794}
1795
1796
0c33b27d 1797static int
c7c82987 1798mptsas_slave_alloc(struct scsi_device *sdev)
0c33b27d 1799{
c7c82987 1800 struct Scsi_Host *host = sdev->host;
e7eae9f6 1801 MPT_SCSI_HOST *hd = shost_priv(host);
0c33b27d
CH
1802 struct sas_rphy *rphy;
1803 struct mptsas_portinfo *p;
a69de507 1804 VirtDevice *vdevice;
c7c82987 1805 struct scsi_target *starget;
547f9a21 1806 int i;
e80b002b 1807 MPT_ADAPTER *ioc = hd->ioc;
0c33b27d 1808
a69de507
EM
1809 vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
1810 if (!vdevice) {
547f9a21 1811 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
e80b002b 1812 ioc->name, sizeof(VirtDevice));
0c33b27d
CH
1813 return -ENOMEM;
1814 }
c7c82987 1815 starget = scsi_target(sdev);
a69de507 1816 vdevice->vtarget = starget->hostdata;
0c33b27d 1817
e8bf3941 1818 if (sdev->channel == MPTSAS_RAID_CHANNEL)
816aa907 1819 goto out;
816aa907 1820
c7c82987 1821 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
e80b002b
EM
1822 mutex_lock(&ioc->sas_topology_mutex);
1823 list_for_each_entry(p, &ioc->sas_topology, list) {
0c33b27d 1824 for (i = 0; i < p->num_phys; i++) {
547f9a21
EM
1825 if (p->phy_info[i].attached.sas_address !=
1826 rphy->identify.sas_address)
1827 continue;
a69de507 1828 vdevice->lun = sdev->lun;
547f9a21
EM
1829 /*
1830 * Exposing hidden raid components
1831 */
e80b002b 1832 if (mptscsih_is_phys_disk(ioc,
793955f5
EM
1833 p->phy_info[i].attached.channel,
1834 p->phy_info[i].attached.id))
547f9a21 1835 sdev->no_uld_attach = 1;
e80b002b 1836 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21 1837 goto out;
0c33b27d
CH
1838 }
1839 }
e80b002b 1840 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d 1841
a69de507 1842 kfree(vdevice);
23f236ed 1843 return -ENXIO;
0c33b27d
CH
1844
1845 out:
a69de507
EM
1846 vdevice->vtarget->num_luns++;
1847 sdev->hostdata = vdevice;
0c33b27d
CH
1848 return 0;
1849}
1850
547f9a21
EM
1851static int
1852mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
9a28f49a 1853{
7b5a65b9
KD
1854 MPT_SCSI_HOST *hd;
1855 MPT_ADAPTER *ioc;
a69de507 1856 VirtDevice *vdevice = SCpnt->device->hostdata;
7d3eecf7 1857
a69de507 1858 if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
547f9a21
EM
1859 SCpnt->result = DID_NO_CONNECT << 16;
1860 done(SCpnt);
1861 return 0;
7d3eecf7 1862 }
547f9a21 1863
7b5a65b9
KD
1864 hd = shost_priv(SCpnt->device->host);
1865 ioc = hd->ioc;
1866
1867 if (ioc->sas_discovery_quiesce_io)
1868 return SCSI_MLQUEUE_HOST_BUSY;
1869
793955f5
EM
1870// scsi_print_command(SCpnt);
1871
547f9a21 1872 return mptscsih_qcmd(SCpnt,done);
9a28f49a
CH
1873}
1874
547f9a21 1875
0c33b27d 1876static struct scsi_host_template mptsas_driver_template = {
f78496da 1877 .module = THIS_MODULE,
0c33b27d
CH
1878 .proc_name = "mptsas",
1879 .proc_info = mptscsih_proc_info,
1880 .name = "MPT SPI Host",
1881 .info = mptscsih_info,
547f9a21
EM
1882 .queuecommand = mptsas_qcmd,
1883 .target_alloc = mptsas_target_alloc,
0c33b27d 1884 .slave_alloc = mptsas_slave_alloc,
f013db32 1885 .slave_configure = mptsas_slave_configure,
547f9a21
EM
1886 .target_destroy = mptsas_target_destroy,
1887 .slave_destroy = mptscsih_slave_destroy,
0c33b27d
CH
1888 .change_queue_depth = mptscsih_change_queue_depth,
1889 .eh_abort_handler = mptscsih_abort,
1890 .eh_device_reset_handler = mptscsih_dev_reset,
1891 .eh_bus_reset_handler = mptscsih_bus_reset,
1892 .eh_host_reset_handler = mptscsih_host_reset,
1893 .bios_param = mptscsih_bios_param,
9d2e9d66 1894 .can_queue = MPT_SAS_CAN_QUEUE,
0c33b27d
CH
1895 .this_id = -1,
1896 .sg_tablesize = MPT_SCSI_SG_DEPTH,
1897 .max_sectors = 8192,
1898 .cmd_per_lun = 7,
1899 .use_clustering = ENABLE_CLUSTERING,
edb9068d 1900 .shost_attrs = mptscsih_host_attrs,
0c33b27d
CH
1901};
1902
b5141128 1903static int mptsas_get_linkerrors(struct sas_phy *phy)
0c33b27d 1904{
b5141128
CH
1905 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1906 ConfigExtendedPageHeader_t hdr;
1907 CONFIGPARMS cfg;
1908 SasPhyPage1_t *buffer;
1909 dma_addr_t dma_handle;
1910 int error;
0c33b27d 1911
f4ad7b58
JB
1912 /* FIXME: only have link errors on local phys */
1913 if (!scsi_is_sas_phy_local(phy))
1914 return -EINVAL;
1915
b5141128
CH
1916 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
1917 hdr.ExtPageLength = 0;
1918 hdr.PageNumber = 1 /* page number 1*/;
1919 hdr.Reserved1 = 0;
1920 hdr.Reserved2 = 0;
1921 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1922 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
0c33b27d 1923
b5141128
CH
1924 cfg.cfghdr.ehdr = &hdr;
1925 cfg.physAddr = -1;
1926 cfg.pageAddr = phy->identify.phy_identifier;
1927 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1928 cfg.dir = 0; /* read */
1929 cfg.timeout = 10;
0c33b27d 1930
b5141128
CH
1931 error = mpt_config(ioc, &cfg);
1932 if (error)
1933 return error;
1934 if (!hdr.ExtPageLength)
1935 return -ENXIO;
0c33b27d 1936
b5141128
CH
1937 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1938 &dma_handle);
1939 if (!buffer)
1940 return -ENOMEM;
0c33b27d 1941
b5141128
CH
1942 cfg.physAddr = dma_handle;
1943 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1944
1945 error = mpt_config(ioc, &cfg);
1946 if (error)
1947 goto out_free_consistent;
1948
d6ecdd63 1949 mptsas_print_phy_pg1(ioc, buffer);
b5141128
CH
1950
1951 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
1952 phy->running_disparity_error_count =
1953 le32_to_cpu(buffer->RunningDisparityErrorCount);
1954 phy->loss_of_dword_sync_count =
1955 le32_to_cpu(buffer->LossDwordSynchCount);
1956 phy->phy_reset_problem_count =
1957 le32_to_cpu(buffer->PhyResetProblemCount);
1958
1959 out_free_consistent:
1960 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1961 buffer, dma_handle);
1962 return error;
0c33b27d
CH
1963}
1964
da4fa655
CH
1965static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
1966 MPT_FRAME_HDR *reply)
1967{
f0f09d3b 1968 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
da4fa655 1969 if (reply != NULL) {
f0f09d3b 1970 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID;
da4fa655
CH
1971 memcpy(ioc->sas_mgmt.reply, reply,
1972 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
1973 }
2f187862
KD
1974
1975 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
1976 ioc->sas_mgmt.status &= ~MPT_MGMT_STATUS_PENDING;
1977 complete(&ioc->sas_mgmt.done);
1978 return 1;
1979 }
1980 return 0;
da4fa655
CH
1981}
1982
1983static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
1984{
1985 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1986 SasIoUnitControlRequest_t *req;
1987 SasIoUnitControlReply_t *reply;
1988 MPT_FRAME_HDR *mf;
1989 MPIHeader_t *hdr;
1990 unsigned long timeleft;
1991 int error = -ERESTARTSYS;
1992
f4ad7b58
JB
1993 /* FIXME: fusion doesn't allow non-local phy reset */
1994 if (!scsi_is_sas_phy_local(phy))
1995 return -EINVAL;
1996
da4fa655
CH
1997 /* not implemented for expanders */
1998 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
1999 return -ENXIO;
2000
eeb846ce 2001 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
da4fa655
CH
2002 goto out;
2003
2004 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2005 if (!mf) {
2006 error = -ENOMEM;
2007 goto out_unlock;
2008 }
2009
2010 hdr = (MPIHeader_t *) mf;
2011 req = (SasIoUnitControlRequest_t *)mf;
2012 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
2013 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
2014 req->MsgContext = hdr->MsgContext;
2015 req->Operation = hard_reset ?
2016 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
2017 req->PhyNum = phy->identify.phy_identifier;
2018
2f187862 2019 INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
da4fa655
CH
2020 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2021
2022 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
2023 10 * HZ);
2024 if (!timeleft) {
2025 /* On timeout reset the board */
2026 mpt_free_msg_frame(ioc, mf);
2027 mpt_HardResetHandler(ioc, CAN_SLEEP);
2028 error = -ETIMEDOUT;
2029 goto out_unlock;
2030 }
2031
2032 /* a reply frame is expected */
2033 if ((ioc->sas_mgmt.status &
f0f09d3b 2034 MPT_MGMT_STATUS_RF_VALID) == 0) {
da4fa655
CH
2035 error = -ENXIO;
2036 goto out_unlock;
2037 }
2038
2039 /* process the completed Reply Message Frame */
2040 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
2041 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
29dd3609 2042 printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
cadbd4a5 2043 ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
da4fa655
CH
2044 error = -ENXIO;
2045 goto out_unlock;
2046 }
2047
2048 error = 0;
2049
2050 out_unlock:
2f187862 2051 CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
eeb846ce 2052 mutex_unlock(&ioc->sas_mgmt.mutex);
da4fa655
CH
2053 out:
2054 return error;
2055}
0c33b27d 2056
e3094447
CH
2057static int
2058mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
2059{
2060 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2061 int i, error;
2062 struct mptsas_portinfo *p;
2063 struct mptsas_enclosure enclosure_info;
2064 u64 enclosure_handle;
2065
2066 mutex_lock(&ioc->sas_topology_mutex);
2067 list_for_each_entry(p, &ioc->sas_topology, list) {
2068 for (i = 0; i < p->num_phys; i++) {
2069 if (p->phy_info[i].attached.sas_address ==
2070 rphy->identify.sas_address) {
2071 enclosure_handle = p->phy_info[i].
2072 attached.handle_enclosure;
2073 goto found_info;
2074 }
2075 }
2076 }
2077 mutex_unlock(&ioc->sas_topology_mutex);
2078 return -ENXIO;
2079
2080 found_info:
2081 mutex_unlock(&ioc->sas_topology_mutex);
2082 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
52435430 2083 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
e3094447
CH
2084 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
2085 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
2086 if (!error)
2087 *identifier = enclosure_info.enclosure_logical_id;
2088 return error;
2089}
2090
2091static int
2092mptsas_get_bay_identifier(struct sas_rphy *rphy)
2093{
2094 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2095 struct mptsas_portinfo *p;
2096 int i, rc;
2097
2098 mutex_lock(&ioc->sas_topology_mutex);
2099 list_for_each_entry(p, &ioc->sas_topology, list) {
2100 for (i = 0; i < p->num_phys; i++) {
2101 if (p->phy_info[i].attached.sas_address ==
2102 rphy->identify.sas_address) {
2103 rc = p->phy_info[i].attached.slot;
2104 goto out;
2105 }
2106 }
2107 }
2108 rc = -ENXIO;
2109 out:
2110 mutex_unlock(&ioc->sas_topology_mutex);
2111 return rc;
2112}
2113
159e36fe
FT
2114static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
2115 struct request *req)
2116{
2117 MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
2118 MPT_FRAME_HDR *mf;
2119 SmpPassthroughRequest_t *smpreq;
2120 struct request *rsp = req->next_rq;
2121 int ret;
2122 int flagsLength;
2123 unsigned long timeleft;
2124 char *psge;
2125 dma_addr_t dma_addr_in = 0;
2126 dma_addr_t dma_addr_out = 0;
2127 u64 sas_address = 0;
2128
2129 if (!rsp) {
29dd3609 2130 printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
cadbd4a5 2131 ioc->name, __func__);
159e36fe
FT
2132 return -EINVAL;
2133 }
2134
2135 /* do we need to support multiple segments? */
2136 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
29dd3609 2137 printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
b0790410
TH
2138 ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req),
2139 rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
159e36fe
FT
2140 return -EINVAL;
2141 }
2142
2143 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
2144 if (ret)
2145 goto out;
2146
2147 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2148 if (!mf) {
2149 ret = -ENOMEM;
2150 goto out_unlock;
2151 }
2152
2153 smpreq = (SmpPassthroughRequest_t *)mf;
2154 memset(smpreq, 0, sizeof(*smpreq));
2155
b0790410 2156 smpreq->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
159e36fe
FT
2157 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
2158
2159 if (rphy)
2160 sas_address = rphy->identify.sas_address;
2161 else {
2162 struct mptsas_portinfo *port_info;
2163
2164 mutex_lock(&ioc->sas_topology_mutex);
f9c34022 2165 port_info = ioc->hba_port_info;
159e36fe
FT
2166 if (port_info && port_info->phy_info)
2167 sas_address =
2168 port_info->phy_info[0].phy->identify.sas_address;
2169 mutex_unlock(&ioc->sas_topology_mutex);
2170 }
2171
2172 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
2173
2174 psge = (char *)
2175 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
2176
2177 /* request */
2178 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2179 MPI_SGE_FLAGS_END_OF_BUFFER |
14d0f0b0
KD
2180 MPI_SGE_FLAGS_DIRECTION)
2181 << MPI_SGE_FLAGS_SHIFT;
b0790410 2182 flagsLength |= (blk_rq_bytes(req) - 4);
159e36fe
FT
2183
2184 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
b0790410 2185 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
159e36fe
FT
2186 if (!dma_addr_out)
2187 goto put_mf;
14d0f0b0 2188 ioc->add_sge(psge, flagsLength, dma_addr_out);
2f187862 2189 psge += ioc->SGE_size;
159e36fe
FT
2190
2191 /* response */
2f187862
KD
2192 flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2193 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2194 MPI_SGE_FLAGS_IOC_TO_HOST |
2195 MPI_SGE_FLAGS_END_OF_BUFFER;
2196
2197 flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
b0790410 2198 flagsLength |= blk_rq_bytes(rsp) + 4;
159e36fe 2199 dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
b0790410 2200 blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
159e36fe
FT
2201 if (!dma_addr_in)
2202 goto unmap;
14d0f0b0 2203 ioc->add_sge(psge, flagsLength, dma_addr_in);
159e36fe 2204
2f187862 2205 INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
159e36fe
FT
2206 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2207
2208 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
2209 if (!timeleft) {
cadbd4a5 2210 printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__);
159e36fe
FT
2211 /* On timeout reset the board */
2212 mpt_HardResetHandler(ioc, CAN_SLEEP);
2213 ret = -ETIMEDOUT;
2214 goto unmap;
2215 }
2216 mf = NULL;
2217
f0f09d3b 2218 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
159e36fe
FT
2219 SmpPassthroughReply_t *smprep;
2220
2221 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
2222 memcpy(req->sense, smprep, sizeof(*smprep));
2223 req->sense_len = sizeof(*smprep);
5f49f631
TH
2224 req->resid_len = 0;
2225 rsp->resid_len -= smprep->ResponseDataLength;
159e36fe 2226 } else {
2f187862
KD
2227 printk(MYIOC_s_ERR_FMT
2228 "%s: smp passthru reply failed to be returned\n",
cadbd4a5 2229 ioc->name, __func__);
159e36fe
FT
2230 ret = -ENXIO;
2231 }
2232unmap:
2233 if (dma_addr_out)
b0790410 2234 pci_unmap_single(ioc->pcidev, dma_addr_out, blk_rq_bytes(req),
159e36fe
FT
2235 PCI_DMA_BIDIRECTIONAL);
2236 if (dma_addr_in)
b0790410 2237 pci_unmap_single(ioc->pcidev, dma_addr_in, blk_rq_bytes(rsp),
159e36fe
FT
2238 PCI_DMA_BIDIRECTIONAL);
2239put_mf:
2240 if (mf)
2241 mpt_free_msg_frame(ioc, mf);
2242out_unlock:
2f187862 2243 CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
159e36fe
FT
2244 mutex_unlock(&ioc->sas_mgmt.mutex);
2245out:
2246 return ret;
2247}
2248
b5141128
CH
2249static struct sas_function_template mptsas_transport_functions = {
2250 .get_linkerrors = mptsas_get_linkerrors,
e3094447
CH
2251 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
2252 .get_bay_identifier = mptsas_get_bay_identifier,
da4fa655 2253 .phy_reset = mptsas_phy_reset,
159e36fe 2254 .smp_handler = mptsas_smp_handler,
b5141128
CH
2255};
2256
2257static struct scsi_transport_template *mptsas_transport_template;
0c33b27d
CH
2258
2259static int
2260mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
2261{
2262 ConfigExtendedPageHeader_t hdr;
2263 CONFIGPARMS cfg;
2264 SasIOUnitPage0_t *buffer;
2265 dma_addr_t dma_handle;
2266 int error, i;
2267
2268 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
2269 hdr.ExtPageLength = 0;
2270 hdr.PageNumber = 0;
2271 hdr.Reserved1 = 0;
2272 hdr.Reserved2 = 0;
2273 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2274 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2275
2276 cfg.cfghdr.ehdr = &hdr;
2277 cfg.physAddr = -1;
2278 cfg.pageAddr = 0;
2279 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2280 cfg.dir = 0; /* read */
2281 cfg.timeout = 10;
2282
2283 error = mpt_config(ioc, &cfg);
2284 if (error)
2285 goto out;
2286 if (!hdr.ExtPageLength) {
2287 error = -ENXIO;
2288 goto out;
2289 }
2290
2291 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2292 &dma_handle);
2293 if (!buffer) {
2294 error = -ENOMEM;
2295 goto out;
2296 }
2297
2298 cfg.physAddr = dma_handle;
2299 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2300
2301 error = mpt_config(ioc, &cfg);
2302 if (error)
2303 goto out_free_consistent;
2304
2305 port_info->num_phys = buffer->NumPhys;
2306 port_info->phy_info = kcalloc(port_info->num_phys,
2f187862 2307 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
0c33b27d
CH
2308 if (!port_info->phy_info) {
2309 error = -ENOMEM;
2310 goto out_free_consistent;
2311 }
2312
edb9068d
PS
2313 ioc->nvdata_version_persistent =
2314 le16_to_cpu(buffer->NvdataVersionPersistent);
2315 ioc->nvdata_version_default =
2316 le16_to_cpu(buffer->NvdataVersionDefault);
2317
0c33b27d 2318 for (i = 0; i < port_info->num_phys; i++) {
d6ecdd63 2319 mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
0c33b27d
CH
2320 port_info->phy_info[i].phy_id = i;
2321 port_info->phy_info[i].port_id =
2322 buffer->PhyData[i].Port;
2323 port_info->phy_info[i].negotiated_link_rate =
2324 buffer->PhyData[i].NegotiatedLinkRate;
547f9a21 2325 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
2326 port_info->phy_info[i].handle =
2327 le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
0c33b27d
CH
2328 }
2329
2330 out_free_consistent:
2331 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2332 buffer, dma_handle);
2333 out:
2334 return error;
2335}
2336
edb9068d
PS
2337static int
2338mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
2339{
2340 ConfigExtendedPageHeader_t hdr;
2341 CONFIGPARMS cfg;
2342 SasIOUnitPage1_t *buffer;
2343 dma_addr_t dma_handle;
2344 int error;
2345 u16 device_missing_delay;
2346
2347 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
2348 memset(&cfg, 0, sizeof(CONFIGPARMS));
2349
2350 cfg.cfghdr.ehdr = &hdr;
2351 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2352 cfg.timeout = 10;
2353 cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2354 cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2355 cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
2356 cfg.cfghdr.ehdr->PageNumber = 1;
2357
2358 error = mpt_config(ioc, &cfg);
2359 if (error)
2360 goto out;
2361 if (!hdr.ExtPageLength) {
2362 error = -ENXIO;
2363 goto out;
2364 }
2365
2366 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2367 &dma_handle);
2368 if (!buffer) {
2369 error = -ENOMEM;
2370 goto out;
2371 }
2372
2373 cfg.physAddr = dma_handle;
2374 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2375
2376 error = mpt_config(ioc, &cfg);
2377 if (error)
2378 goto out_free_consistent;
2379
2380 ioc->io_missing_delay =
2381 le16_to_cpu(buffer->IODeviceMissingDelay);
2382 device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay);
2383 ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
2384 (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
2385 device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
2386
2387 out_free_consistent:
2388 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2389 buffer, dma_handle);
2390 out:
2391 return error;
2392}
2393
0c33b27d
CH
2394static int
2395mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2396 u32 form, u32 form_specific)
2397{
2398 ConfigExtendedPageHeader_t hdr;
2399 CONFIGPARMS cfg;
2400 SasPhyPage0_t *buffer;
2401 dma_addr_t dma_handle;
2402 int error;
2403
2404 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
2405 hdr.ExtPageLength = 0;
2406 hdr.PageNumber = 0;
2407 hdr.Reserved1 = 0;
2408 hdr.Reserved2 = 0;
2409 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2410 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
2411
2412 cfg.cfghdr.ehdr = &hdr;
2413 cfg.dir = 0; /* read */
2414 cfg.timeout = 10;
2415
2416 /* Get Phy Pg 0 for each Phy. */
2417 cfg.physAddr = -1;
2418 cfg.pageAddr = form + form_specific;
2419 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2420
2421 error = mpt_config(ioc, &cfg);
2422 if (error)
2423 goto out;
2424
2425 if (!hdr.ExtPageLength) {
2426 error = -ENXIO;
2427 goto out;
2428 }
2429
2430 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2431 &dma_handle);
2432 if (!buffer) {
2433 error = -ENOMEM;
2434 goto out;
2435 }
2436
2437 cfg.physAddr = dma_handle;
2438 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2439
2440 error = mpt_config(ioc, &cfg);
2441 if (error)
2442 goto out_free_consistent;
2443
d6ecdd63 2444 mptsas_print_phy_pg0(ioc, buffer);
0c33b27d
CH
2445
2446 phy_info->hw_link_rate = buffer->HwLinkRate;
2447 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2448 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2449 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2450
2451 out_free_consistent:
2452 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2453 buffer, dma_handle);
2454 out:
2455 return error;
2456}
2457
2458static int
2459mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
2460 u32 form, u32 form_specific)
2461{
2462 ConfigExtendedPageHeader_t hdr;
2463 CONFIGPARMS cfg;
2464 SasDevicePage0_t *buffer;
2465 dma_addr_t dma_handle;
2466 __le64 sas_address;
bd23e94c
ME
2467 int error=0;
2468
0c33b27d
CH
2469 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
2470 hdr.ExtPageLength = 0;
2471 hdr.PageNumber = 0;
2472 hdr.Reserved1 = 0;
2473 hdr.Reserved2 = 0;
2474 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2475 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
2476
2477 cfg.cfghdr.ehdr = &hdr;
2478 cfg.pageAddr = form + form_specific;
2479 cfg.physAddr = -1;
2480 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2481 cfg.dir = 0; /* read */
2482 cfg.timeout = 10;
2483
db9c9174 2484 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d
CH
2485 error = mpt_config(ioc, &cfg);
2486 if (error)
2487 goto out;
2488 if (!hdr.ExtPageLength) {
2489 error = -ENXIO;
2490 goto out;
2491 }
2492
2493 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2494 &dma_handle);
2495 if (!buffer) {
2496 error = -ENOMEM;
2497 goto out;
2498 }
2499
2500 cfg.physAddr = dma_handle;
2501 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2502
2503 error = mpt_config(ioc, &cfg);
2504 if (error)
2505 goto out_free_consistent;
2506
d6ecdd63 2507 mptsas_print_device_pg0(ioc, buffer);
0c33b27d 2508
2f187862 2509 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d 2510 device_info->handle = le16_to_cpu(buffer->DevHandle);
c73787ee 2511 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
e3094447
CH
2512 device_info->handle_enclosure =
2513 le16_to_cpu(buffer->EnclosureHandle);
2514 device_info->slot = le16_to_cpu(buffer->Slot);
0c33b27d
CH
2515 device_info->phy_id = buffer->PhyNum;
2516 device_info->port_id = buffer->PhysicalPort;
9a28f49a 2517 device_info->id = buffer->TargetID;
b506ade9 2518 device_info->phys_disk_num = ~0;
9a28f49a 2519 device_info->channel = buffer->Bus;
0c33b27d
CH
2520 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2521 device_info->sas_address = le64_to_cpu(sas_address);
2522 device_info->device_info =
2523 le32_to_cpu(buffer->DeviceInfo);
2524
2525 out_free_consistent:
2526 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2527 buffer, dma_handle);
2528 out:
2529 return error;
2530}
2531
2532static int
2533mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
2534 u32 form, u32 form_specific)
2535{
2536 ConfigExtendedPageHeader_t hdr;
2537 CONFIGPARMS cfg;
2538 SasExpanderPage0_t *buffer;
2539 dma_addr_t dma_handle;
547f9a21 2540 int i, error;
2f187862 2541 __le64 sas_address;
0c33b27d 2542
2f187862 2543 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
2544 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
2545 hdr.ExtPageLength = 0;
2546 hdr.PageNumber = 0;
2547 hdr.Reserved1 = 0;
2548 hdr.Reserved2 = 0;
2549 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2550 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2551
2552 cfg.cfghdr.ehdr = &hdr;
2553 cfg.physAddr = -1;
2554 cfg.pageAddr = form + form_specific;
2555 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2556 cfg.dir = 0; /* read */
2557 cfg.timeout = 10;
2558
db9c9174 2559 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
2560 error = mpt_config(ioc, &cfg);
2561 if (error)
2562 goto out;
2563
2564 if (!hdr.ExtPageLength) {
2565 error = -ENXIO;
2566 goto out;
2567 }
2568
2569 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2570 &dma_handle);
2571 if (!buffer) {
2572 error = -ENOMEM;
2573 goto out;
2574 }
2575
2576 cfg.physAddr = dma_handle;
2577 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2578
2579 error = mpt_config(ioc, &cfg);
2580 if (error)
2581 goto out_free_consistent;
2582
51f39eae
KO
2583 if (!buffer->NumPhys) {
2584 error = -ENODEV;
2585 goto out_free_consistent;
2586 }
2587
0c33b27d 2588 /* save config data */
2f187862 2589 port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1;
0c33b27d 2590 port_info->phy_info = kcalloc(port_info->num_phys,
2f187862 2591 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
0c33b27d
CH
2592 if (!port_info->phy_info) {
2593 error = -ENOMEM;
2594 goto out_free_consistent;
2595 }
2596
2f187862 2597 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2ecce492 2598 for (i = 0; i < port_info->num_phys; i++) {
547f9a21 2599 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
2600 port_info->phy_info[i].handle =
2601 le16_to_cpu(buffer->DevHandle);
2f187862
KD
2602 port_info->phy_info[i].identify.sas_address =
2603 le64_to_cpu(sas_address);
2604 port_info->phy_info[i].identify.handle_parent =
2605 le16_to_cpu(buffer->ParentDevHandle);
2ecce492 2606 }
547f9a21 2607
0c33b27d
CH
2608 out_free_consistent:
2609 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2610 buffer, dma_handle);
2611 out:
2612 return error;
2613}
2614
2615static int
2616mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2617 u32 form, u32 form_specific)
2618{
2619 ConfigExtendedPageHeader_t hdr;
2620 CONFIGPARMS cfg;
2621 SasExpanderPage1_t *buffer;
2622 dma_addr_t dma_handle;
bd23e94c
ME
2623 int error=0;
2624
2f187862 2625 hdr.PageVersion = MPI_SASEXPANDER1_PAGEVERSION;
0c33b27d
CH
2626 hdr.ExtPageLength = 0;
2627 hdr.PageNumber = 1;
2628 hdr.Reserved1 = 0;
2629 hdr.Reserved2 = 0;
2630 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2631 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2632
2633 cfg.cfghdr.ehdr = &hdr;
2634 cfg.physAddr = -1;
2635 cfg.pageAddr = form + form_specific;
2636 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2637 cfg.dir = 0; /* read */
2638 cfg.timeout = 10;
2639
2640 error = mpt_config(ioc, &cfg);
2641 if (error)
2642 goto out;
2643
2644 if (!hdr.ExtPageLength) {
2645 error = -ENXIO;
2646 goto out;
2647 }
2648
2649 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2650 &dma_handle);
2651 if (!buffer) {
2652 error = -ENOMEM;
2653 goto out;
2654 }
2655
2656 cfg.physAddr = dma_handle;
2657 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2658
2659 error = mpt_config(ioc, &cfg);
2f187862
KD
2660
2661 if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
2662 error = -ENODEV;
2663 goto out;
2664 }
2665
0c33b27d
CH
2666 if (error)
2667 goto out_free_consistent;
2668
2669
d6ecdd63 2670 mptsas_print_expander_pg1(ioc, buffer);
0c33b27d
CH
2671
2672 /* save config data */
024358ee 2673 phy_info->phy_id = buffer->PhyIdentifier;
0c33b27d
CH
2674 phy_info->port_id = buffer->PhysicalPort;
2675 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
2676 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2677 phy_info->hw_link_rate = buffer->HwLinkRate;
2678 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2679 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2680
0c33b27d
CH
2681 out_free_consistent:
2682 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2683 buffer, dma_handle);
2684 out:
2685 return error;
2686}
2687
2688static void
2689mptsas_parse_device_info(struct sas_identify *identify,
2690 struct mptsas_devinfo *device_info)
2691{
2692 u16 protocols;
2693
2694 identify->sas_address = device_info->sas_address;
2695 identify->phy_identifier = device_info->phy_id;
2696
2697 /*
2698 * Fill in Phy Initiator Port Protocol.
2699 * Bits 6:3, more than one bit can be set, fall through cases.
2700 */
2701 protocols = device_info->device_info & 0x78;
2702 identify->initiator_port_protocols = 0;
2703 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
2704 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
2705 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
2706 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
2707 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
2708 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
2709 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
2710 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
2711
2712 /*
2713 * Fill in Phy Target Port Protocol.
2714 * Bits 10:7, more than one bit can be set, fall through cases.
2715 */
2716 protocols = device_info->device_info & 0x780;
2717 identify->target_port_protocols = 0;
2718 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2719 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
2720 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
2721 identify->target_port_protocols |= SAS_PROTOCOL_STP;
2722 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
2723 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
2724 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2725 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
2726
2727 /*
2728 * Fill in Attached device type.
2729 */
2730 switch (device_info->device_info &
2731 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
2732 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
2733 identify->device_type = SAS_PHY_UNUSED;
2734 break;
2735 case MPI_SAS_DEVICE_INFO_END_DEVICE:
2736 identify->device_type = SAS_END_DEVICE;
2737 break;
2738 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
2739 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
2740 break;
2741 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
2742 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
2743 break;
2744 }
2745}
2746
2747static int mptsas_probe_one_phy(struct device *dev,
ac01bbbd 2748 struct mptsas_phyinfo *phy_info, int index, int local)
0c33b27d 2749{
e6b2d76a 2750 MPT_ADAPTER *ioc;
9a28f49a 2751 struct sas_phy *phy;
547f9a21
EM
2752 struct sas_port *port;
2753 int error = 0;
0c33b27d 2754
547f9a21
EM
2755 if (!dev) {
2756 error = -ENODEV;
2757 goto out;
2758 }
e6b2d76a
ME
2759
2760 if (!phy_info->phy) {
2761 phy = sas_phy_alloc(dev, index);
547f9a21
EM
2762 if (!phy) {
2763 error = -ENOMEM;
2764 goto out;
2765 }
e6b2d76a
ME
2766 } else
2767 phy = phy_info->phy;
0c33b27d 2768
9a28f49a 2769 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
0c33b27d
CH
2770
2771 /*
2772 * Set Negotiated link rate.
2773 */
2774 switch (phy_info->negotiated_link_rate) {
2775 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
9a28f49a 2776 phy->negotiated_linkrate = SAS_PHY_DISABLED;
0c33b27d
CH
2777 break;
2778 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
9a28f49a 2779 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
0c33b27d
CH
2780 break;
2781 case MPI_SAS_IOUNIT0_RATE_1_5:
9a28f49a 2782 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2783 break;
2784 case MPI_SAS_IOUNIT0_RATE_3_0:
9a28f49a 2785 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2786 break;
2787 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
2788 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
2789 default:
9a28f49a 2790 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
0c33b27d
CH
2791 break;
2792 }
2793
2794 /*
2795 * Set Max hardware link rate.
2796 */
2797 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
2798 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
9a28f49a 2799 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2800 break;
2801 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 2802 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2803 break;
2804 default:
2805 break;
2806 }
2807
2808 /*
2809 * Set Max programmed link rate.
2810 */
2811 switch (phy_info->programmed_link_rate &
2812 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
2813 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
9a28f49a 2814 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2815 break;
2816 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 2817 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2818 break;
2819 default:
2820 break;
2821 }
2822
2823 /*
2824 * Set Min hardware link rate.
2825 */
2826 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
2827 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
9a28f49a 2828 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2829 break;
2830 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 2831 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2832 break;
2833 default:
2834 break;
2835 }
2836
2837 /*
2838 * Set Min programmed link rate.
2839 */
2840 switch (phy_info->programmed_link_rate &
2841 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
2842 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
9a28f49a 2843 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2844 break;
2845 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 2846 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2847 break;
2848 default:
2849 break;
2850 }
2851
e6b2d76a 2852 if (!phy_info->phy) {
ac01bbbd 2853
e6b2d76a
ME
2854 error = sas_phy_add(phy);
2855 if (error) {
2856 sas_phy_free(phy);
547f9a21 2857 goto out;
e6b2d76a
ME
2858 }
2859 phy_info->phy = phy;
0c33b27d
CH
2860 }
2861
547f9a21
EM
2862 if (!phy_info->attached.handle ||
2863 !phy_info->port_details)
2864 goto out;
2865
2866 port = mptsas_get_port(phy_info);
2867 ioc = phy_to_ioc(phy_info->phy);
2868
2869 if (phy_info->sas_port_add_phy) {
2870
2871 if (!port) {
dc22f16d 2872 port = sas_port_alloc_num(dev);
547f9a21
EM
2873 if (!port) {
2874 error = -ENOMEM;
2875 goto out;
2876 }
2877 error = sas_port_add(port);
2878 if (error) {
d6ecdd63 2879 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 2880 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 2881 __func__, __LINE__));
547f9a21
EM
2882 goto out;
2883 }
d6ecdd63 2884 mptsas_set_port(ioc, phy_info, port);
2f187862
KD
2885 devtprintk(ioc, dev_printk(KERN_DEBUG, &port->dev,
2886 MYIOC_s_FMT "add port %d, sas_addr (0x%llx)\n",
2887 ioc->name, port->port_identifier,
2888 (unsigned long long)phy_info->
2889 attached.sas_address));
547f9a21 2890 }
2f187862
KD
2891 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2892 "sas_port_add_phy: phy_id=%d\n",
2893 ioc->name, phy_info->phy_id));
547f9a21
EM
2894 sas_port_add_phy(port, phy_info->phy);
2895 phy_info->sas_port_add_phy = 0;
2f187862
KD
2896 devtprintk(ioc, dev_printk(KERN_DEBUG, &phy_info->phy->dev,
2897 MYIOC_s_FMT "add phy %d, phy-obj (0x%p)\n", ioc->name,
2898 phy_info->phy_id, phy_info->phy));
547f9a21 2899 }
547f9a21 2900 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
e6b2d76a 2901
0c33b27d 2902 struct sas_rphy *rphy;
2686de27 2903 struct device *parent;
f013db32 2904 struct sas_identify identify;
0c33b27d 2905
2686de27 2906 parent = dev->parent->parent;
e6b2d76a
ME
2907 /*
2908 * Let the hotplug_work thread handle processing
2909 * the adding/removing of devices that occur
2910 * after start of day.
2911 */
2f187862
KD
2912 if (mptsas_is_end_device(&phy_info->attached) &&
2913 phy_info->attached.handle_parent) {
2914 goto out;
2915 }
e6b2d76a 2916
f013db32 2917 mptsas_parse_device_info(&identify, &phy_info->attached);
2686de27
JB
2918 if (scsi_is_host_device(parent)) {
2919 struct mptsas_portinfo *port_info;
2920 int i;
2921
f9c34022 2922 port_info = ioc->hba_port_info;
2686de27
JB
2923
2924 for (i = 0; i < port_info->num_phys; i++)
2925 if (port_info->phy_info[i].identify.sas_address ==
0c269e6d
JB
2926 identify.sas_address) {
2927 sas_port_mark_backlink(port);
2686de27 2928 goto out;
0c269e6d 2929 }
2686de27
JB
2930
2931 } else if (scsi_is_sas_rphy(parent)) {
2932 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
2933 if (identify.sas_address ==
0c269e6d
JB
2934 parent_rphy->identify.sas_address) {
2935 sas_port_mark_backlink(port);
2686de27 2936 goto out;
0c269e6d 2937 }
2686de27
JB
2938 }
2939
f013db32
JB
2940 switch (identify.device_type) {
2941 case SAS_END_DEVICE:
547f9a21 2942 rphy = sas_end_device_alloc(port);
f013db32
JB
2943 break;
2944 case SAS_EDGE_EXPANDER_DEVICE:
2945 case SAS_FANOUT_EXPANDER_DEVICE:
547f9a21 2946 rphy = sas_expander_alloc(port, identify.device_type);
f013db32
JB
2947 break;
2948 default:
2949 rphy = NULL;
2950 break;
2951 }
547f9a21 2952 if (!rphy) {
d6ecdd63 2953 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 2954 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 2955 __func__, __LINE__));
547f9a21
EM
2956 goto out;
2957 }
0c33b27d 2958
f013db32 2959 rphy->identify = identify;
0c33b27d
CH
2960 error = sas_rphy_add(rphy);
2961 if (error) {
d6ecdd63 2962 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 2963 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 2964 __func__, __LINE__));
0c33b27d 2965 sas_rphy_free(rphy);
547f9a21 2966 goto out;
0c33b27d 2967 }
d6ecdd63 2968 mptsas_set_rphy(ioc, phy_info, rphy);
0c33b27d
CH
2969 }
2970
547f9a21
EM
2971 out:
2972 return error;
0c33b27d
CH
2973}
2974
2975static int
e6b2d76a 2976mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
0c33b27d 2977{
e6b2d76a 2978 struct mptsas_portinfo *port_info, *hba;
0c33b27d
CH
2979 int error = -ENOMEM, i;
2980
f9c34022 2981 hba = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
e6b2d76a 2982 if (! hba)
0c33b27d 2983 goto out;
0c33b27d 2984
e6b2d76a 2985 error = mptsas_sas_io_unit_pg0(ioc, hba);
0c33b27d
CH
2986 if (error)
2987 goto out_free_port_info;
2988
edb9068d 2989 mptsas_sas_io_unit_pg1(ioc);
9a28f49a 2990 mutex_lock(&ioc->sas_topology_mutex);
f9c34022 2991 port_info = ioc->hba_port_info;
e6b2d76a 2992 if (!port_info) {
f9c34022
KD
2993 ioc->hba_port_info = port_info = hba;
2994 ioc->hba_port_num_phy = port_info->num_phys;
e6b2d76a
ME
2995 list_add_tail(&port_info->list, &ioc->sas_topology);
2996 } else {
2ecce492 2997 for (i = 0; i < hba->num_phys; i++) {
e6b2d76a
ME
2998 port_info->phy_info[i].negotiated_link_rate =
2999 hba->phy_info[i].negotiated_link_rate;
2ecce492
EM
3000 port_info->phy_info[i].handle =
3001 hba->phy_info[i].handle;
3002 port_info->phy_info[i].port_id =
3003 hba->phy_info[i].port_id;
3004 }
547f9a21 3005 kfree(hba->phy_info);
e6b2d76a
ME
3006 kfree(hba);
3007 hba = NULL;
3008 }
9a28f49a 3009 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022
KD
3010#if defined(CPQ_CIM)
3011 ioc->num_ports = port_info->num_phys;
3012#endif
0c33b27d
CH
3013 for (i = 0; i < port_info->num_phys; i++) {
3014 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
3015 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
3016 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
f9c34022
KD
3017 port_info->phy_info[i].identify.handle =
3018 port_info->phy_info[i].handle;
0c33b27d 3019 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
2ecce492
EM
3020 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3021 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
f9c34022
KD
3022 port_info->phy_info[i].identify.handle);
3023 if (!ioc->hba_port_sas_addr)
3024 ioc->hba_port_sas_addr =
3025 port_info->phy_info[i].identify.sas_address;
024358ee 3026 port_info->phy_info[i].identify.phy_id =
2ecce492 3027 port_info->phy_info[i].phy_id = i;
547f9a21 3028 if (port_info->phy_info[i].attached.handle)
0c33b27d
CH
3029 mptsas_sas_device_pg0(ioc,
3030 &port_info->phy_info[i].attached,
3031 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3032 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3033 port_info->phy_info[i].attached.handle);
547f9a21 3034 }
0c33b27d 3035
547f9a21
EM
3036 mptsas_setup_wide_ports(ioc, port_info);
3037
3038 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
0c33b27d 3039 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
e6b2d76a 3040 &port_info->phy_info[i], ioc->sas_index, 1);
0c33b27d
CH
3041
3042 return 0;
3043
3044 out_free_port_info:
547f9a21 3045 kfree(hba);
0c33b27d
CH
3046 out:
3047 return error;
3048}
3049
f9c34022
KD
3050static void
3051mptsas_expander_refresh(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
0c33b27d 3052{
f9c34022
KD
3053 struct mptsas_portinfo *parent;
3054 struct device *parent_dev;
3055 struct sas_rphy *rphy;
3056 int i;
3057 u64 sas_address; /* expander sas address */
3058 u32 handle;
9a28f49a 3059
f9c34022
KD
3060 handle = port_info->phy_info[0].handle;
3061 sas_address = port_info->phy_info[0].identify.sas_address;
0c33b27d 3062 for (i = 0; i < port_info->num_phys; i++) {
0c33b27d 3063 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
f9c34022
KD
3064 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
3065 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + handle);
0c33b27d 3066
f9c34022
KD
3067 mptsas_sas_device_pg0(ioc,
3068 &port_info->phy_info[i].identify,
3069 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3070 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3071 port_info->phy_info[i].identify.handle);
3072 port_info->phy_info[i].identify.phy_id =
3073 port_info->phy_info[i].phy_id;
0c33b27d
CH
3074
3075 if (port_info->phy_info[i].attached.handle) {
3076 mptsas_sas_device_pg0(ioc,
f9c34022
KD
3077 &port_info->phy_info[i].attached,
3078 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3079 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3080 port_info->phy_info[i].attached.handle);
db9c9174
ME
3081 port_info->phy_info[i].attached.phy_id =
3082 port_info->phy_info[i].phy_id;
0c33b27d 3083 }
547f9a21 3084 }
0c33b27d 3085
f9c34022
KD
3086 mutex_lock(&ioc->sas_topology_mutex);
3087 parent = mptsas_find_portinfo_by_handle(ioc,
3088 port_info->phy_info[0].identify.handle_parent);
3089 if (!parent) {
9a28f49a 3090 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022
KD
3091 return;
3092 }
3093 for (i = 0, parent_dev = NULL; i < parent->num_phys && !parent_dev;
3094 i++) {
3095 if (parent->phy_info[i].attached.sas_address == sas_address) {
3096 rphy = mptsas_get_rphy(&parent->phy_info[i]);
3097 parent_dev = &rphy->dev;
3098 }
547f9a21 3099 }
f9c34022 3100 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
3101
3102 mptsas_setup_wide_ports(ioc, port_info);
547f9a21 3103 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
f9c34022 3104 mptsas_probe_one_phy(parent_dev, &port_info->phy_info[i],
e6b2d76a 3105 ioc->sas_index, 0);
f9c34022 3106}
0c33b27d 3107
f9c34022
KD
3108static void
3109mptsas_expander_event_add(MPT_ADAPTER *ioc,
3110 MpiEventDataSasExpanderStatusChange_t *expander_data)
3111{
3112 struct mptsas_portinfo *port_info;
3113 int i;
3114 __le64 sas_address;
0c33b27d 3115
f9c34022
KD
3116 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3117 if (!port_info)
3118 BUG();
3119 port_info->num_phys = (expander_data->NumPhys) ?
3120 expander_data->NumPhys : 1;
3121 port_info->phy_info = kcalloc(port_info->num_phys,
3122 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
3123 if (!port_info->phy_info)
3124 BUG();
3125 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3126 for (i = 0; i < port_info->num_phys; i++) {
3127 port_info->phy_info[i].portinfo = port_info;
3128 port_info->phy_info[i].handle =
3129 le16_to_cpu(expander_data->DevHandle);
3130 port_info->phy_info[i].identify.sas_address =
3131 le64_to_cpu(sas_address);
3132 port_info->phy_info[i].identify.handle_parent =
3133 le16_to_cpu(expander_data->ParentDevHandle);
e6b2d76a 3134 }
f9c34022
KD
3135
3136 mutex_lock(&ioc->sas_topology_mutex);
3137 list_add_tail(&port_info->list, &ioc->sas_topology);
3138 mutex_unlock(&ioc->sas_topology_mutex);
3139
3140 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3141 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3142 (unsigned long long)sas_address);
3143
3144 mptsas_expander_refresh(ioc, port_info);
0c33b27d
CH
3145}
3146
f9c34022
KD
3147/**
3148 * mptsas_delete_expander_siblings - remove siblings attached to expander
3149 * @ioc: Pointer to MPT_ADAPTER structure
3150 * @parent: the parent port_info object
3151 * @expander: the expander port_info object
3152 **/
e6b2d76a 3153static void
f9c34022
KD
3154mptsas_delete_expander_siblings(MPT_ADAPTER *ioc, struct mptsas_portinfo
3155 *parent, struct mptsas_portinfo *expander)
e6b2d76a 3156{
547f9a21 3157 struct mptsas_phyinfo *phy_info;
f9c34022
KD
3158 struct mptsas_portinfo *port_info;
3159 struct sas_rphy *rphy;
e6b2d76a
ME
3160 int i;
3161
f9c34022
KD
3162 phy_info = expander->phy_info;
3163 for (i = 0; i < expander->num_phys; i++, phy_info++) {
3164 rphy = mptsas_get_rphy(phy_info);
3165 if (!rphy)
3166 continue;
3167 if (rphy->identify.device_type == SAS_END_DEVICE)
3168 mptsas_del_end_device(ioc, phy_info);
3169 }
e6b2d76a 3170
f9c34022
KD
3171 phy_info = expander->phy_info;
3172 for (i = 0; i < expander->num_phys; i++, phy_info++) {
3173 rphy = mptsas_get_rphy(phy_info);
3174 if (!rphy)
e6b2d76a 3175 continue;
f9c34022
KD
3176 if (rphy->identify.device_type ==
3177 MPI_SAS_DEVICE_INFO_EDGE_EXPANDER ||
3178 rphy->identify.device_type ==
3179 MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
3180 port_info = mptsas_find_portinfo_by_sas_address(ioc,
3181 rphy->identify.sas_address);
3182 if (!port_info)
3183 continue;
3184 if (port_info == parent) /* backlink rphy */
3185 continue;
3186 /*
3187 Delete this expander even if the expdevpage is exists
3188 because the parent expander is already deleted
3189 */
3190 mptsas_expander_delete(ioc, port_info, 1);
3191 }
3192 }
3193}
e6b2d76a 3194
e6b2d76a 3195
f9c34022
KD
3196/**
3197 * mptsas_expander_delete - remove this expander
3198 * @ioc: Pointer to MPT_ADAPTER structure
3199 * @port_info: expander port_info struct
3200 * @force: Flag to forcefully delete the expander
3201 *
3202 **/
e6b2d76a 3203
f9c34022
KD
3204static void mptsas_expander_delete(MPT_ADAPTER *ioc,
3205 struct mptsas_portinfo *port_info, u8 force)
3206{
e6b2d76a 3207
f9c34022
KD
3208 struct mptsas_portinfo *parent;
3209 int i;
3210 u64 expander_sas_address;
3211 struct mptsas_phyinfo *phy_info;
3212 struct mptsas_portinfo buffer;
3213 struct mptsas_portinfo_details *port_details;
3214 struct sas_port *port;
547f9a21 3215
f9c34022
KD
3216 if (!port_info)
3217 return;
547f9a21 3218
f9c34022
KD
3219 /* see if expander is still there before deleting */
3220 mptsas_sas_expander_pg0(ioc, &buffer,
3221 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3222 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
3223 port_info->phy_info[0].identify.handle);
547f9a21 3224
f9c34022 3225 if (buffer.num_phys) {
547f9a21 3226 kfree(buffer.phy_info);
f9c34022
KD
3227 if (!force)
3228 return;
e6b2d76a 3229 }
f9c34022
KD
3230
3231
3232 /*
3233 * Obtain the port_info instance to the parent port
3234 */
3235 port_details = NULL;
3236 expander_sas_address =
3237 port_info->phy_info[0].identify.sas_address;
3238 parent = mptsas_find_portinfo_by_handle(ioc,
3239 port_info->phy_info[0].identify.handle_parent);
3240 mptsas_delete_expander_siblings(ioc, parent, port_info);
3241 if (!parent)
3242 goto out;
3243
3244 /*
3245 * Delete rphys in the parent that point
3246 * to this expander.
3247 */
3248 phy_info = parent->phy_info;
3249 port = NULL;
3250 for (i = 0; i < parent->num_phys; i++, phy_info++) {
3251 if (!phy_info->phy)
3252 continue;
3253 if (phy_info->attached.sas_address !=
3254 expander_sas_address)
3255 continue;
3256 if (!port) {
3257 port = mptsas_get_port(phy_info);
3258 port_details = phy_info->port_details;
3259 }
3260 dev_printk(KERN_DEBUG, &phy_info->phy->dev,
3261 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
3262 phy_info->phy_id, phy_info->phy);
3263 sas_port_delete_phy(port, phy_info->phy);
3264 }
3265 if (port) {
3266 dev_printk(KERN_DEBUG, &port->dev,
3267 MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n",
3268 ioc->name, port->port_identifier,
3269 (unsigned long long)expander_sas_address);
3270 sas_port_delete(port);
3271 mptsas_port_delete(ioc, port_details);
3272 }
3273 out:
3274
3275 printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, "
3276 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3277 (unsigned long long)expander_sas_address);
3278
3279 /*
3280 * free link
3281 */
3282 list_del(&port_info->list);
3283 kfree(port_info->phy_info);
3284 kfree(port_info);
e6b2d76a
ME
3285}
3286
f9c34022
KD
3287
3288/**
3289 * mptsas_send_expander_event - expanders events
3290 * @ioc: Pointer to MPT_ADAPTER structure
3291 * @expander_data: event data
3292 *
3293 *
3294 * This function handles adding, removing, and refreshing
3295 * device handles within the expander objects.
e6b2d76a 3296 */
0c33b27d 3297static void
f9c34022 3298mptsas_send_expander_event(struct fw_event_work *fw_event)
0c33b27d 3299{
f9c34022
KD
3300 MPT_ADAPTER *ioc;
3301 MpiEventDataSasExpanderStatusChange_t *expander_data;
3302 struct mptsas_portinfo *port_info;
3303 __le64 sas_address;
f44e5461 3304 int i;
0c33b27d 3305
f9c34022
KD
3306 ioc = fw_event->ioc;
3307 expander_data = (MpiEventDataSasExpanderStatusChange_t *)
3308 fw_event->event_data;
3309 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3310 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3311
3312 if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) {
3313 if (port_info) {
3314 for (i = 0; i < port_info->num_phys; i++) {
3315 port_info->phy_info[i].portinfo = port_info;
3316 port_info->phy_info[i].handle =
3317 le16_to_cpu(expander_data->DevHandle);
3318 port_info->phy_info[i].identify.sas_address =
3319 le64_to_cpu(sas_address);
3320 port_info->phy_info[i].identify.handle_parent =
3321 le16_to_cpu(expander_data->ParentDevHandle);
3322 }
3323 mptsas_expander_refresh(ioc, port_info);
3324 } else if (!port_info && expander_data->NumPhys)
3325 mptsas_expander_event_add(ioc, expander_data);
3326 } else if (expander_data->ReasonCode ==
3327 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING)
3328 mptsas_expander_delete(ioc, port_info, 0);
3329
3330 mptsas_free_fw_event(ioc, fw_event);
3331}
3332
3333
3334/**
3335 * mptsas_expander_add -
3336 * @ioc: Pointer to MPT_ADAPTER structure
3337 * @handle:
3338 *
3339 */
3340struct mptsas_portinfo *
3341mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
3342{
3343 struct mptsas_portinfo buffer, *port_info;
3344 int i;
3345
3346 if ((mptsas_sas_expander_pg0(ioc, &buffer,
3347 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3348 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)))
3349 return NULL;
3350
3351 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_ATOMIC);
3352 if (!port_info) {
3353 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3354 "%s: exit at line=%d\n", ioc->name,
3355 __func__, __LINE__));
3356 return NULL;
3357 }
3358 port_info->num_phys = buffer.num_phys;
3359 port_info->phy_info = buffer.phy_info;
3360 for (i = 0; i < port_info->num_phys; i++)
3361 port_info->phy_info[i].portinfo = port_info;
3362 mutex_lock(&ioc->sas_topology_mutex);
3363 list_add_tail(&port_info->list, &ioc->sas_topology);
3364 mutex_unlock(&ioc->sas_topology_mutex);
3365 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3366 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3367 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3368 mptsas_expander_refresh(ioc, port_info);
3369 return port_info;
3370}
3371
3372static void
3373mptsas_send_link_status_event(struct fw_event_work *fw_event)
3374{
3375 MPT_ADAPTER *ioc;
3376 MpiEventDataSasPhyLinkStatus_t *link_data;
3377 struct mptsas_portinfo *port_info;
3378 struct mptsas_phyinfo *phy_info = NULL;
3379 __le64 sas_address;
3380 u8 phy_num;
3381 u8 link_rate;
3382
3383 ioc = fw_event->ioc;
3384 link_data = (MpiEventDataSasPhyLinkStatus_t *)fw_event->event_data;
3385
3386 memcpy(&sas_address, &link_data->SASAddress, sizeof(__le64));
3387 sas_address = le64_to_cpu(sas_address);
3388 link_rate = link_data->LinkRates >> 4;
3389 phy_num = link_data->PhyNum;
3390
3391 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3392 if (port_info) {
3393 phy_info = &port_info->phy_info[phy_num];
3394 if (phy_info)
3395 phy_info->negotiated_link_rate = link_rate;
3396 }
3397
3398 if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
3399 link_rate == MPI_SAS_IOUNIT0_RATE_3_0) {
3400
eedf92b9
KD
3401 if (!port_info) {
3402 if (ioc->old_sas_discovery_protocal) {
3403 port_info = mptsas_expander_add(ioc,
3404 le16_to_cpu(link_data->DevHandle));
3405 if (port_info)
3406 goto out;
3407 }
f9c34022 3408 goto out;
eedf92b9 3409 }
f9c34022
KD
3410
3411 if (port_info == ioc->hba_port_info)
3412 mptsas_probe_hba_phys(ioc);
3413 else
3414 mptsas_expander_refresh(ioc, port_info);
3415 } else if (phy_info && phy_info->phy) {
3416 if (link_rate == MPI_SAS_IOUNIT0_RATE_PHY_DISABLED)
3417 phy_info->phy->negotiated_linkrate =
3418 SAS_PHY_DISABLED;
3419 else if (link_rate ==
3420 MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
3421 phy_info->phy->negotiated_linkrate =
3422 SAS_LINK_RATE_FAILED;
3423 else
3424 phy_info->phy->negotiated_linkrate =
3425 SAS_LINK_RATE_UNKNOWN;
f44e5461
ME
3426 }
3427 out:
f9c34022 3428 mptsas_free_fw_event(ioc, fw_event);
e6b2d76a
ME
3429}
3430
eedf92b9
KD
3431static void
3432mptsas_not_responding_devices(MPT_ADAPTER *ioc)
3433{
3434 struct mptsas_portinfo buffer, *port_info;
3435 struct mptsas_device_info *sas_info;
3436 struct mptsas_devinfo sas_device;
3437 u32 handle;
3438 VirtTarget *vtarget = NULL;
3439 struct mptsas_phyinfo *phy_info;
3440 u8 found_expander;
3441 int retval, retry_count;
3442 unsigned long flags;
3443
3444 mpt_findImVolumes(ioc);
3445
3446 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3447 if (ioc->ioc_reset_in_progress) {
3448 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3449 "%s: exiting due to a parallel reset \n", ioc->name,
3450 __func__));
3451 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3452 return;
3453 }
3454 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3455
3456 /* devices, logical volumes */
3457 mutex_lock(&ioc->sas_device_info_mutex);
3458 redo_device_scan:
3459 list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
57e98513
KD
3460 if (sas_info->is_cached)
3461 continue;
a7938b0b
KD
3462 if (!sas_info->is_logical_volume) {
3463 sas_device.handle = 0;
3464 retry_count = 0;
eedf92b9 3465retry_page:
a7938b0b 3466 retval = mptsas_sas_device_pg0(ioc, &sas_device,
eedf92b9
KD
3467 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
3468 << MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3469 (sas_info->fw.channel << 8) +
3470 sas_info->fw.id);
3471
a7938b0b
KD
3472 if (sas_device.handle)
3473 continue;
3474 if (retval == -EBUSY) {
3475 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3476 if (ioc->ioc_reset_in_progress) {
3477 dfailprintk(ioc,
3478 printk(MYIOC_s_DEBUG_FMT
3479 "%s: exiting due to reset\n",
3480 ioc->name, __func__));
3481 spin_unlock_irqrestore
3482 (&ioc->taskmgmt_lock, flags);
3483 mutex_unlock(&ioc->
3484 sas_device_info_mutex);
3485 return;
3486 }
3487 spin_unlock_irqrestore(&ioc->taskmgmt_lock,
3488 flags);
eedf92b9 3489 }
eedf92b9 3490
a7938b0b
KD
3491 if (retval && (retval != -ENODEV)) {
3492 if (retry_count < 10) {
3493 retry_count++;
3494 goto retry_page;
3495 } else {
3496 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3497 "%s: Config page retry exceeded retry "
3498 "count deleting device 0x%llx\n",
3499 ioc->name, __func__,
3500 sas_info->sas_address));
3501 }
eedf92b9 3502 }
eedf92b9 3503
a7938b0b
KD
3504 /* delete device */
3505 vtarget = mptsas_find_vtarget(ioc,
eedf92b9 3506 sas_info->fw.channel, sas_info->fw.id);
a7938b0b
KD
3507
3508 if (vtarget)
3509 vtarget->deleted = 1;
3510
3511 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3512 sas_info->sas_address);
3513
3514 if (phy_info) {
3515 mptsas_del_end_device(ioc, phy_info);
3516 goto redo_device_scan;
3517 }
3518 } else
3519 mptsas_volume_delete(ioc, sas_info->fw.id);
eedf92b9 3520 }
129dd981 3521 mutex_unlock(&ioc->sas_device_info_mutex);
eedf92b9
KD
3522
3523 /* expanders */
3524 mutex_lock(&ioc->sas_topology_mutex);
3525 redo_expander_scan:
3526 list_for_each_entry(port_info, &ioc->sas_topology, list) {
3527
3528 if (port_info->phy_info &&
3529 (!(port_info->phy_info[0].identify.device_info &
3530 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
3531 continue;
3532 found_expander = 0;
3533 handle = 0xFFFF;
3534 while (!mptsas_sas_expander_pg0(ioc, &buffer,
3535 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3536 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle) &&
3537 !found_expander) {
3538
3539 handle = buffer.phy_info[0].handle;
3540 if (buffer.phy_info[0].identify.sas_address ==
3541 port_info->phy_info[0].identify.sas_address) {
3542 found_expander = 1;
3543 }
3544 kfree(buffer.phy_info);
3545 }
3546
3547 if (!found_expander) {
3548 mptsas_expander_delete(ioc, port_info, 0);
3549 goto redo_expander_scan;
3550 }
3551 }
129dd981 3552 mutex_unlock(&ioc->sas_topology_mutex);
eedf92b9
KD
3553}
3554
f9c34022
KD
3555/**
3556 * mptsas_probe_expanders - adding expanders
3557 * @ioc: Pointer to MPT_ADAPTER structure
3558 *
3559 **/
e6b2d76a 3560static void
f9c34022 3561mptsas_probe_expanders(MPT_ADAPTER *ioc)
e6b2d76a 3562{
f9c34022
KD
3563 struct mptsas_portinfo buffer, *port_info;
3564 u32 handle;
3565 int i;
e6b2d76a 3566
f9c34022
KD
3567 handle = 0xFFFF;
3568 while (!mptsas_sas_expander_pg0(ioc, &buffer,
3569 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3570 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)) {
3571
3572 handle = buffer.phy_info[0].handle;
3573 port_info = mptsas_find_portinfo_by_sas_address(ioc,
3574 buffer.phy_info[0].identify.sas_address);
3575
3576 if (port_info) {
3577 /* refreshing handles */
3578 for (i = 0; i < buffer.num_phys; i++) {
3579 port_info->phy_info[i].handle = handle;
3580 port_info->phy_info[i].identify.handle_parent =
3581 buffer.phy_info[0].identify.handle_parent;
3582 }
3583 mptsas_expander_refresh(ioc, port_info);
3584 kfree(buffer.phy_info);
3585 continue;
3586 }
3587
3588 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3589 if (!port_info) {
3590 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3591 "%s: exit at line=%d\n", ioc->name,
3592 __func__, __LINE__));
3593 return;
3594 }
3595 port_info->num_phys = buffer.num_phys;
3596 port_info->phy_info = buffer.phy_info;
3597 for (i = 0; i < port_info->num_phys; i++)
3598 port_info->phy_info[i].portinfo = port_info;
3599 mutex_lock(&ioc->sas_topology_mutex);
3600 list_add_tail(&port_info->list, &ioc->sas_topology);
3601 mutex_unlock(&ioc->sas_topology_mutex);
3602 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3603 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3604 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3605 mptsas_expander_refresh(ioc, port_info);
3606 }
3607}
3608
3609static void
3610mptsas_probe_devices(MPT_ADAPTER *ioc)
3611{
3612 u16 handle;
3613 struct mptsas_devinfo sas_device;
3614 struct mptsas_phyinfo *phy_info;
3615
3616 handle = 0xFFFF;
3617 while (!(mptsas_sas_device_pg0(ioc, &sas_device,
3618 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
3619
3620 handle = sas_device.handle;
3621
3622 if ((sas_device.device_info &
3623 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
3624 MPI_SAS_DEVICE_INFO_STP_TARGET |
3625 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0)
3626 continue;
3627
3628 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
3629 if (!phy_info)
3630 continue;
3631
3632 if (mptsas_get_rphy(phy_info))
3633 continue;
3634
3635 mptsas_add_end_device(ioc, phy_info);
3636 }
547f9a21
EM
3637}
3638
2f187862
KD
3639/**
3640 * mptsas_scan_sas_topology -
3641 * @ioc: Pointer to MPT_ADAPTER structure
3642 * @sas_address:
3643 *
3644 **/
547f9a21 3645static void
f9c34022 3646mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
547f9a21 3647{
f9c34022
KD
3648 struct scsi_device *sdev;
3649 int i;
547f9a21 3650
f9c34022
KD
3651 mptsas_probe_hba_phys(ioc);
3652 mptsas_probe_expanders(ioc);
3653 mptsas_probe_devices(ioc);
0c33b27d 3654
f9c34022
KD
3655 /*
3656 Reporting RAID volumes.
3657 */
3658 if (!ioc->ir_firmware || !ioc->raid_data.pIocPg2 ||
3659 !ioc->raid_data.pIocPg2->NumActiveVolumes)
3660 return;
3661 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
3662 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
3663 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
3664 if (sdev) {
3665 scsi_device_put(sdev);
3666 continue;
3667 }
3668 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
3669 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
3670 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID);
3671 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
3672 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
3673 }
3674}
3eb0822c 3675
57e98513
KD
3676
3677static void
3678mptsas_handle_queue_full_event(struct fw_event_work *fw_event)
3679{
3680 MPT_ADAPTER *ioc;
3681 EventDataQueueFull_t *qfull_data;
3682 struct mptsas_device_info *sas_info;
3683 struct scsi_device *sdev;
3684 int depth;
3685 int id = -1;
3686 int channel = -1;
3687 int fw_id, fw_channel;
3688 u16 current_depth;
3689
3690
3691 ioc = fw_event->ioc;
3692 qfull_data = (EventDataQueueFull_t *)fw_event->event_data;
3693 fw_id = qfull_data->TargetID;
3694 fw_channel = qfull_data->Bus;
3695 current_depth = le16_to_cpu(qfull_data->CurrentDepth);
3696
3697 /* if hidden raid component, look for the volume id */
3698 mutex_lock(&ioc->sas_device_info_mutex);
3699 if (mptscsih_is_phys_disk(ioc, fw_channel, fw_id)) {
3700 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
3701 list) {
3702 if (sas_info->is_cached ||
3703 sas_info->is_logical_volume)
3704 continue;
3705 if (sas_info->is_hidden_raid_component &&
3706 (sas_info->fw.channel == fw_channel &&
3707 sas_info->fw.id == fw_id)) {
3708 id = sas_info->volume_id;
3709 channel = MPTSAS_RAID_CHANNEL;
3710 goto out;
3711 }
3712 }
3713 } else {
3714 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
3715 list) {
3716 if (sas_info->is_cached ||
3717 sas_info->is_hidden_raid_component ||
3718 sas_info->is_logical_volume)
3719 continue;
3720 if (sas_info->fw.channel == fw_channel &&
3721 sas_info->fw.id == fw_id) {
3722 id = sas_info->os.id;
3723 channel = sas_info->os.channel;
3724 goto out;
3725 }
3726 }
3727
3728 }
3729
3730 out:
3731 mutex_unlock(&ioc->sas_device_info_mutex);
3732
3733 if (id != -1) {
3734 shost_for_each_device(sdev, ioc->sh) {
3735 if (sdev->id == id && sdev->channel == channel) {
3736 if (current_depth > sdev->queue_depth) {
3737 sdev_printk(KERN_INFO, sdev,
3738 "strange observation, the queue "
3739 "depth is (%d) meanwhile fw queue "
3740 "depth (%d)\n", sdev->queue_depth,
3741 current_depth);
3742 continue;
3743 }
3744 depth = scsi_track_queue_full(sdev,
3745 current_depth - 1);
3746 if (depth > 0)
3747 sdev_printk(KERN_INFO, sdev,
3748 "Queue depth reduced to (%d)\n",
3749 depth);
3750 else if (depth < 0)
3751 sdev_printk(KERN_INFO, sdev,
3752 "Tagged Command Queueing is being "
3753 "disabled\n");
3754 else if (depth == 0)
3755 sdev_printk(KERN_INFO, sdev,
3756 "Queue depth not changed yet\n");
3757 }
3758 }
3759 }
3760
3761 mptsas_free_fw_event(ioc, fw_event);
3762}
3763
3764
9a28f49a 3765static struct mptsas_phyinfo *
547f9a21 3766mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
9a28f49a
CH
3767{
3768 struct mptsas_portinfo *port_info;
9a28f49a 3769 struct mptsas_phyinfo *phy_info = NULL;
547f9a21 3770 int i;
9a28f49a 3771
9a28f49a
CH
3772 mutex_lock(&ioc->sas_topology_mutex);
3773 list_for_each_entry(port_info, &ioc->sas_topology, list) {
3774 for (i = 0; i < port_info->num_phys; i++) {
b506ade9
EM
3775 if (!mptsas_is_end_device(
3776 &port_info->phy_info[i].attached))
3777 continue;
547f9a21
EM
3778 if (port_info->phy_info[i].attached.sas_address
3779 != sas_address)
3780 continue;
b506ade9
EM
3781 phy_info = &port_info->phy_info[i];
3782 break;
3783 }
3784 }
3785 mutex_unlock(&ioc->sas_topology_mutex);
3786 return phy_info;
3787}
3788
a7938b0b
KD
3789/**
3790 * mptsas_find_phyinfo_by_phys_disk_num -
3791 * @ioc: Pointer to MPT_ADAPTER structure
3792 * @phys_disk_num:
3793 * @channel:
3794 * @id:
3795 *
3796 **/
9a28f49a 3797static struct mptsas_phyinfo *
a7938b0b
KD
3798mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num,
3799 u8 channel, u8 id)
9a28f49a 3800{
9a28f49a 3801 struct mptsas_phyinfo *phy_info = NULL;
a7938b0b
KD
3802 struct mptsas_portinfo *port_info;
3803 RaidPhysDiskPage1_t *phys_disk = NULL;
3804 int num_paths;
3805 u64 sas_address = 0;
9a28f49a
CH
3806 int i;
3807
a7938b0b
KD
3808 phy_info = NULL;
3809 if (!ioc->raid_data.pIocPg3)
3810 return NULL;
3811 /* dual port support */
3812 num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num);
3813 if (!num_paths)
3814 goto out;
3815 phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
3816 (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
3817 if (!phys_disk)
3818 goto out;
3819 mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk);
3820 for (i = 0; i < num_paths; i++) {
3821 if ((phys_disk->Path[i].Flags & 1) != 0)
3822 /* entry no longer valid */
3823 continue;
3824 if ((id == phys_disk->Path[i].PhysDiskID) &&
3825 (channel == phys_disk->Path[i].PhysDiskBus)) {
3826 memcpy(&sas_address, &phys_disk->Path[i].WWID,
3827 sizeof(u64));
3828 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3829 sas_address);
3830 goto out;
3831 }
3832 }
3833
3834 out:
3835 kfree(phys_disk);
3836 if (phy_info)
3837 return phy_info;
3838
3839 /*
3840 * Extra code to handle RAID0 case, where the sas_address is not updated
3841 * in phys_disk_page_1 when hotswapped
3842 */
9a28f49a
CH
3843 mutex_lock(&ioc->sas_topology_mutex);
3844 list_for_each_entry(port_info, &ioc->sas_topology, list) {
a7938b0b 3845 for (i = 0; i < port_info->num_phys && !phy_info; i++) {
547f9a21
EM
3846 if (!mptsas_is_end_device(
3847 &port_info->phy_info[i].attached))
3848 continue;
b506ade9
EM
3849 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
3850 continue;
a7938b0b
KD
3851 if ((port_info->phy_info[i].attached.phys_disk_num ==
3852 phys_disk_num) &&
3853 (port_info->phy_info[i].attached.id == id) &&
3854 (port_info->phy_info[i].attached.channel ==
3855 channel))
3856 phy_info = &port_info->phy_info[i];
547f9a21 3857 }
9a28f49a
CH
3858 }
3859 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
3860 return phy_info;
3861}
3862
f44e5461
ME
3863static void
3864mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
3865{
f99be43b
EM
3866 int rc;
3867
f44e5461 3868 sdev->no_uld_attach = data ? 1 : 0;
f99be43b 3869 rc = scsi_device_reprobe(sdev);
f44e5461
ME
3870}
3871
3872static void
3873mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
3874{
3875 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
3876 mptsas_reprobe_lun);
3877}
3878
b506ade9
EM
3879static void
3880mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
3881{
3882 CONFIGPARMS cfg;
3883 ConfigPageHeader_t hdr;
3884 dma_addr_t dma_handle;
3885 pRaidVolumePage0_t buffer = NULL;
3886 RaidPhysDiskPage0_t phys_disk;
3887 int i;
3eb0822c
KD
3888 struct mptsas_phyinfo *phy_info;
3889 struct mptsas_devinfo sas_device;
b506ade9
EM
3890
3891 memset(&cfg, 0 , sizeof(CONFIGPARMS));
3892 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
3893 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
3894 cfg.pageAddr = (channel << 8) + id;
3895 cfg.cfghdr.hdr = &hdr;
3896 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
3897
3898 if (mpt_config(ioc, &cfg) != 0)
3899 goto out;
3900
3901 if (!hdr.PageLength)
3902 goto out;
3903
3904 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
3905 &dma_handle);
3906
3907 if (!buffer)
3908 goto out;
3909
3910 cfg.physAddr = dma_handle;
3911 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
3912
3913 if (mpt_config(ioc, &cfg) != 0)
3914 goto out;
3915
3916 if (!(buffer->VolumeStatus.Flags &
3917 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
3918 goto out;
3919
3920 if (!buffer->NumPhysDisks)
3921 goto out;
3922
3923 for (i = 0; i < buffer->NumPhysDisks; i++) {
3924
3925 if (mpt_raid_phys_disk_pg0(ioc,
3926 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
3927 continue;
3928
3eb0822c
KD
3929 if (mptsas_sas_device_pg0(ioc, &sas_device,
3930 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
3931 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3932 (phys_disk.PhysDiskBus << 8) +
3933 phys_disk.PhysDiskID))
3934 continue;
b506ade9 3935
3eb0822c
KD
3936 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3937 sas_device.sas_address);
3938 mptsas_add_end_device(ioc, phy_info);
b506ade9
EM
3939 }
3940
3941 out:
3942 if (buffer)
3943 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
3944 dma_handle);
3945}
e6b2d76a
ME
3946/*
3947 * Work queue thread to handle SAS hotplug events
3948 */
9a28f49a 3949static void
3eb0822c
KD
3950mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
3951 struct mptsas_hotplug_event *hot_plug_info)
9a28f49a 3952{
9a28f49a 3953 struct mptsas_phyinfo *phy_info;
547f9a21 3954 struct scsi_target * starget;
c73787ee 3955 struct mptsas_devinfo sas_device;
f44e5461 3956 VirtTarget *vtarget;
3eb0822c 3957 int i;
9a28f49a 3958
3eb0822c 3959 switch (hot_plug_info->event_type) {
9a28f49a 3960
3eb0822c
KD
3961 case MPTSAS_ADD_PHYSDISK:
3962
3963 if (!ioc->raid_data.pIocPg2)
3964 break;
3965
3966 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
3967 if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID ==
3968 hot_plug_info->id) {
3969 printk(MYIOC_s_WARN_FMT "firmware bug: unable "
3970 "to add hidden disk - target_id matchs "
3971 "volume_id\n", ioc->name);
3972 mptsas_free_fw_event(ioc, fw_event);
3973 return;
3974 }
b506ade9 3975 }
3eb0822c 3976 mpt_findImVolumes(ioc);
b506ade9 3977
3eb0822c
KD
3978 case MPTSAS_ADD_DEVICE:
3979 memset(&sas_device, 0, sizeof(struct mptsas_devinfo));
3980 mptsas_sas_device_pg0(ioc, &sas_device,
3981 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
3982 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3983 (hot_plug_info->channel << 8) +
3984 hot_plug_info->id);
3985
3986 if (!sas_device.handle)
3987 return;
3988
3989 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
b506ade9 3990 if (!phy_info)
3eb0822c 3991 break;
e6b2d76a 3992
3eb0822c
KD
3993 if (mptsas_get_rphy(phy_info))
3994 break;
3995
3996 mptsas_add_end_device(ioc, phy_info);
3997 break;
3998
3999 case MPTSAS_DEL_DEVICE:
4000 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4001 hot_plug_info->sas_address);
4002 mptsas_del_end_device(ioc, phy_info);
4003 break;
4004
4005 case MPTSAS_DEL_PHYSDISK:
4006
4007 mpt_findImVolumes(ioc);
4008
4009 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
a7938b0b
KD
4010 ioc, hot_plug_info->phys_disk_num,
4011 hot_plug_info->channel,
4012 hot_plug_info->id);
3eb0822c
KD
4013 mptsas_del_end_device(ioc, phy_info);
4014 break;
4015
4016 case MPTSAS_ADD_PHYSDISK_REPROBE:
4017
4018 if (mptsas_sas_device_pg0(ioc, &sas_device,
4019 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4020 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4021 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
d6ecdd63 4022 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4023 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4024 __func__, hot_plug_info->id, __LINE__));
b506ade9
EM
4025 break;
4026 }
3eb0822c
KD
4027
4028 phy_info = mptsas_find_phyinfo_by_sas_address(
4029 ioc, sas_device.sas_address);
4030
4031 if (!phy_info) {
d6ecdd63 4032 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4033 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4034 __func__, hot_plug_info->id, __LINE__));
9a28f49a 4035 break;
547f9a21 4036 }
3eb0822c
KD
4037
4038 starget = mptsas_get_starget(phy_info);
4039 if (!starget) {
d6ecdd63 4040 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4041 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4042 __func__, hot_plug_info->id, __LINE__));
547f9a21
EM
4043 break;
4044 }
b506ade9 4045
3eb0822c
KD
4046 vtarget = starget->hostdata;
4047 if (!vtarget) {
d6ecdd63 4048 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4049 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4050 __func__, hot_plug_info->id, __LINE__));
f44e5461 4051 break;
547f9a21
EM
4052 }
4053
3eb0822c 4054 mpt_findImVolumes(ioc);
547f9a21 4055
3eb0822c
KD
4056 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Hidding: "
4057 "fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4058 ioc->name, hot_plug_info->channel, hot_plug_info->id,
4059 hot_plug_info->phys_disk_num, (unsigned long long)
4060 sas_device.sas_address);
9a28f49a 4061
3eb0822c
KD
4062 vtarget->id = hot_plug_info->phys_disk_num;
4063 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
4064 phy_info->attached.phys_disk_num = hot_plug_info->phys_disk_num;
4065 mptsas_reprobe_target(starget, 1);
9a28f49a 4066 break;
c73787ee 4067
3eb0822c 4068 case MPTSAS_DEL_PHYSDISK_REPROBE:
bd23e94c 4069
e3094447
CH
4070 if (mptsas_sas_device_pg0(ioc, &sas_device,
4071 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
b506ade9 4072 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3eb0822c 4073 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
d6ecdd63 4074 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4075 "%s: fw_id=%d exit at line=%d\n",
4076 ioc->name, __func__,
4077 hot_plug_info->id, __LINE__));
e3094447 4078 break;
547f9a21 4079 }
9a28f49a 4080
547f9a21
EM
4081 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4082 sas_device.sas_address);
3eb0822c 4083 if (!phy_info) {
d6ecdd63 4084 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4085 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4086 __func__, hot_plug_info->id, __LINE__));
547f9a21 4087 break;
e6b2d76a
ME
4088 }
4089
547f9a21 4090 starget = mptsas_get_starget(phy_info);
3eb0822c
KD
4091 if (!starget) {
4092 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4093 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4094 __func__, hot_plug_info->id, __LINE__));
9a28f49a
CH
4095 break;
4096 }
4097
3eb0822c
KD
4098 vtarget = starget->hostdata;
4099 if (!vtarget) {
d6ecdd63 4100 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4101 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4102 __func__, hot_plug_info->id, __LINE__));
f44e5461 4103 break;
547f9a21 4104 }
b506ade9 4105
3eb0822c 4106 if (!(vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) {
d6ecdd63 4107 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4108 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4109 __func__, hot_plug_info->id, __LINE__));
547f9a21
EM
4110 break;
4111 }
c73787ee 4112
3eb0822c 4113 mpt_findImVolumes(ioc);
9a28f49a 4114
3eb0822c
KD
4115 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Exposing:"
4116 " fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4117 ioc->name, hot_plug_info->channel, hot_plug_info->id,
4118 hot_plug_info->phys_disk_num, (unsigned long long)
4119 sas_device.sas_address);
4120
4121 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
4122 vtarget->id = hot_plug_info->id;
4123 phy_info->attached.phys_disk_num = ~0;
4124 mptsas_reprobe_target(starget, 0);
4125 mptsas_add_device_component_by_fw(ioc,
4126 hot_plug_info->channel, hot_plug_info->id);
9a28f49a 4127 break;
3eb0822c 4128
c73787ee 4129 case MPTSAS_ADD_RAID:
3eb0822c 4130
c73787ee 4131 mpt_findImVolumes(ioc);
3eb0822c
KD
4132 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
4133 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4134 hot_plug_info->id);
4135 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
4136 hot_plug_info->id, 0);
c73787ee 4137 break;
3eb0822c 4138
c73787ee 4139 case MPTSAS_DEL_RAID:
3eb0822c 4140
c73787ee 4141 mpt_findImVolumes(ioc);
3eb0822c
KD
4142 printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
4143 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4144 hot_plug_info->id);
4145 scsi_remove_device(hot_plug_info->sdev);
4146 scsi_device_put(hot_plug_info->sdev);
c73787ee 4147 break;
3eb0822c 4148
b506ade9 4149 case MPTSAS_ADD_INACTIVE_VOLUME:
3eb0822c
KD
4150
4151 mpt_findImVolumes(ioc);
b506ade9 4152 mptsas_adding_inactive_raid_components(ioc,
3eb0822c 4153 hot_plug_info->channel, hot_plug_info->id);
b506ade9 4154 break;
3eb0822c 4155
bd23e94c
ME
4156 default:
4157 break;
9a28f49a
CH
4158 }
4159
3eb0822c 4160 mptsas_free_fw_event(ioc, fw_event);
9a28f49a
CH
4161}
4162
4163static void
3eb0822c 4164mptsas_send_sas_event(struct fw_event_work *fw_event)
9a28f49a 4165{
3eb0822c
KD
4166 MPT_ADAPTER *ioc;
4167 struct mptsas_hotplug_event hot_plug_info;
4168 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
4169 u32 device_info;
4170 u64 sas_address;
4171
4172 ioc = fw_event->ioc;
4173 sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
4174 fw_event->event_data;
4175 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
9a28f49a
CH
4176
4177 if ((device_info &
3eb0822c
KD
4178 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
4179 MPI_SAS_DEVICE_INFO_STP_TARGET |
4180 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) {
4181 mptsas_free_fw_event(ioc, fw_event);
9a28f49a 4182 return;
3eb0822c
KD
4183 }
4184
4185 if (sas_event_data->ReasonCode ==
4186 MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED) {
4187 mptbase_sas_persist_operation(ioc,
4188 MPI_SAS_OP_CLEAR_NOT_PRESENT);
4189 mptsas_free_fw_event(ioc, fw_event);
4190 return;
4191 }
9a28f49a 4192
4b766471 4193 switch (sas_event_data->ReasonCode) {
4b766471 4194 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
df9e062a 4195 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
3eb0822c
KD
4196 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4197 hot_plug_info.handle = le16_to_cpu(sas_event_data->DevHandle);
4198 hot_plug_info.channel = sas_event_data->Bus;
4199 hot_plug_info.id = sas_event_data->TargetID;
4200 hot_plug_info.phy_id = sas_event_data->PhyNum;
4b766471 4201 memcpy(&sas_address, &sas_event_data->SASAddress,
3eb0822c
KD
4202 sizeof(u64));
4203 hot_plug_info.sas_address = le64_to_cpu(sas_address);
4204 hot_plug_info.device_info = device_info;
4b766471
ME
4205 if (sas_event_data->ReasonCode &
4206 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
3eb0822c 4207 hot_plug_info.event_type = MPTSAS_ADD_DEVICE;
4b766471 4208 else
3eb0822c
KD
4209 hot_plug_info.event_type = MPTSAS_DEL_DEVICE;
4210 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4b766471 4211 break;
3eb0822c 4212
4b766471 4213 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
3eb0822c
KD
4214 mptbase_sas_persist_operation(ioc,
4215 MPI_SAS_OP_CLEAR_NOT_PRESENT);
4216 mptsas_free_fw_event(ioc, fw_event);
4b766471 4217 break;
3eb0822c 4218
4b766471 4219 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
3eb0822c 4220 /* TODO */
4b766471 4221 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
3eb0822c 4222 /* TODO */
4b766471 4223 default:
3eb0822c 4224 mptsas_free_fw_event(ioc, fw_event);
4b766471 4225 break;
9a28f49a 4226 }
9a28f49a 4227}
3eb0822c 4228
c73787ee 4229static void
3eb0822c 4230mptsas_send_raid_event(struct fw_event_work *fw_event)
c73787ee 4231{
3eb0822c
KD
4232 MPT_ADAPTER *ioc;
4233 EVENT_DATA_RAID *raid_event_data;
4234 struct mptsas_hotplug_event hot_plug_info;
4235 int status;
4236 int state;
4237 struct scsi_device *sdev = NULL;
4238 VirtDevice *vdevice = NULL;
4239 RaidPhysDiskPage0_t phys_disk;
4240
4241 ioc = fw_event->ioc;
4242 raid_event_data = (EVENT_DATA_RAID *)fw_event->event_data;
4243 status = le32_to_cpu(raid_event_data->SettingsStatus);
4244 state = (status >> 8) & 0xff;
4245
4246 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4247 hot_plug_info.id = raid_event_data->VolumeID;
4248 hot_plug_info.channel = raid_event_data->VolumeBus;
4249 hot_plug_info.phys_disk_num = raid_event_data->PhysDiskNum;
4250
4251 if (raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_DELETED ||
4252 raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_CREATED ||
4253 raid_event_data->ReasonCode ==
4254 MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED) {
4255 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
4256 hot_plug_info.id, 0);
4257 hot_plug_info.sdev = sdev;
4258 if (sdev)
4259 vdevice = sdev->hostdata;
c73787ee
ME
4260 }
4261
3eb0822c
KD
4262 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4263 "ReasonCode=%02x\n", ioc->name, __func__,
4264 raid_event_data->ReasonCode));
c73787ee
ME
4265
4266 switch (raid_event_data->ReasonCode) {
4267 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
3eb0822c 4268 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK_REPROBE;
c73787ee
ME
4269 break;
4270 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
3eb0822c 4271 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK_REPROBE;
c73787ee 4272 break;
bd23e94c
ME
4273 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4274 switch (state) {
4275 case MPI_PD_STATE_ONLINE:
b506ade9 4276 case MPI_PD_STATE_NOT_COMPATIBLE:
3eb0822c
KD
4277 mpt_raid_phys_disk_pg0(ioc,
4278 raid_event_data->PhysDiskNum, &phys_disk);
4279 hot_plug_info.id = phys_disk.PhysDiskID;
4280 hot_plug_info.channel = phys_disk.PhysDiskBus;
4281 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
bd23e94c 4282 break;
3eb0822c 4283 case MPI_PD_STATE_FAILED:
bd23e94c 4284 case MPI_PD_STATE_MISSING:
bd23e94c
ME
4285 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
4286 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
4287 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
3eb0822c 4288 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
bd23e94c
ME
4289 break;
4290 default:
4291 break;
4292 }
4293 break;
c73787ee 4294 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
3eb0822c
KD
4295 if (!sdev)
4296 break;
4297 vdevice->vtarget->deleted = 1; /* block IO */
4298 hot_plug_info.event_type = MPTSAS_DEL_RAID;
c73787ee
ME
4299 break;
4300 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
3eb0822c
KD
4301 if (sdev) {
4302 scsi_device_put(sdev);
4303 break;
4304 }
4305 hot_plug_info.event_type = MPTSAS_ADD_RAID;
c73787ee
ME
4306 break;
4307 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
3eb0822c
KD
4308 if (!(status & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)) {
4309 if (!sdev)
4310 break;
4311 vdevice->vtarget->deleted = 1; /* block IO */
4312 hot_plug_info.event_type = MPTSAS_DEL_RAID;
4313 break;
4314 }
bd23e94c
ME
4315 switch (state) {
4316 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
4317 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
3eb0822c
KD
4318 if (!sdev)
4319 break;
4320 vdevice->vtarget->deleted = 1; /* block IO */
4321 hot_plug_info.event_type = MPTSAS_DEL_RAID;
bd23e94c
ME
4322 break;
4323 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
4324 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
3eb0822c
KD
4325 if (sdev) {
4326 scsi_device_put(sdev);
4327 break;
4328 }
4329 hot_plug_info.event_type = MPTSAS_ADD_RAID;
bd23e94c
ME
4330 break;
4331 default:
4332 break;
4333 }
c73787ee
ME
4334 break;
4335 default:
4336 break;
4337 }
3eb0822c
KD
4338
4339 if (hot_plug_info.event_type != MPTSAS_IGNORE_EVENT)
4340 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4341 else
4342 mptsas_free_fw_event(ioc, fw_event);
c73787ee
ME
4343}
4344
db7051b2
KD
4345/**
4346 * mptsas_issue_tm - send mptsas internal tm request
4347 * @ioc: Pointer to MPT_ADAPTER structure
4348 * @type: Task Management type
4349 * @channel: channel number for task management
4350 * @id: Logical Target ID for reset (if appropriate)
4351 * @lun: Logical unit for reset (if appropriate)
4352 * @task_context: Context for the task to be aborted
4353 * @timeout: timeout for task management control
4354 *
4355 * return 0 on success and -1 on failure:
4356 *
4357 */
4358static int
4359mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun,
4360 int task_context, ulong timeout, u8 *issue_reset)
4361{
4362 MPT_FRAME_HDR *mf;
4363 SCSITaskMgmt_t *pScsiTm;
4364 int retval;
4365 unsigned long timeleft;
4366
4367 *issue_reset = 0;
4368 mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
4369 if (mf == NULL) {
4370 retval = -1; /* return failure */
4371 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt request: no "
4372 "msg frames!!\n", ioc->name));
4373 goto out;
4374 }
4375
4376 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request: mr = %p, "
4377 "task_type = 0x%02X,\n\t timeout = %ld, fw_channel = %d, "
4378 "fw_id = %d, lun = %lld,\n\t task_context = 0x%x\n", ioc->name, mf,
4379 type, timeout, channel, id, (unsigned long long)lun,
4380 task_context));
4381
4382 pScsiTm = (SCSITaskMgmt_t *) mf;
4383 memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
4384 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
4385 pScsiTm->TaskType = type;
4386 pScsiTm->MsgFlags = 0;
4387 pScsiTm->TargetID = id;
4388 pScsiTm->Bus = channel;
4389 pScsiTm->ChainOffset = 0;
4390 pScsiTm->Reserved = 0;
4391 pScsiTm->Reserved1 = 0;
4392 pScsiTm->TaskMsgContext = task_context;
4393 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
4394
4395 INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4396 CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
4397 retval = 0;
4398 mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
4399
4400 /* Now wait for the command to complete */
4401 timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
4402 timeout*HZ);
4403 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
4404 retval = -1; /* return failure */
4405 dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
4406 "TaskMgmt request: TIMED OUT!(mr=%p)\n", ioc->name, mf));
4407 mpt_free_msg_frame(ioc, mf);
4408 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
4409 goto out;
4410 *issue_reset = 1;
4411 goto out;
4412 }
4413
4414 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
4415 retval = -1; /* return failure */
4416 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4417 "TaskMgmt request: failed with no reply\n", ioc->name));
4418 goto out;
4419 }
4420
4421 out:
4422 CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4423 return retval;
4424}
4425
4426/**
4427 * mptsas_broadcast_primative_work - Handle broadcast primitives
4428 * @work: work queue payload containing info describing the event
4429 *
4430 * this will be handled in workqueue context.
4431 */
4432static void
4433mptsas_broadcast_primative_work(struct fw_event_work *fw_event)
4434{
4435 MPT_ADAPTER *ioc = fw_event->ioc;
4436 MPT_FRAME_HDR *mf;
4437 VirtDevice *vdevice;
4438 int ii;
4439 struct scsi_cmnd *sc;
4440 SCSITaskMgmtReply_t *pScsiTmReply;
4441 u8 issue_reset;
4442 int task_context;
4443 u8 channel, id;
4444 int lun;
4445 u32 termination_count;
4446 u32 query_count;
4447
4448 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4449 "%s - enter\n", ioc->name, __func__));
4450
4451 mutex_lock(&ioc->taskmgmt_cmds.mutex);
4452 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
4453 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4454 mptsas_requeue_fw_event(ioc, fw_event, 1000);
4455 return;
4456 }
4457
4458 issue_reset = 0;
4459 termination_count = 0;
4460 query_count = 0;
4461 mpt_findImVolumes(ioc);
4462 pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
4463
4464 for (ii = 0; ii < ioc->req_depth; ii++) {
4465 if (ioc->fw_events_off)
4466 goto out;
4467 sc = mptscsih_get_scsi_lookup(ioc, ii);
4468 if (!sc)
4469 continue;
4470 mf = MPT_INDEX_2_MFPTR(ioc, ii);
4471 if (!mf)
4472 continue;
4473 task_context = mf->u.frame.hwhdr.msgctxu.MsgContext;
4474 vdevice = sc->device->hostdata;
4475 if (!vdevice || !vdevice->vtarget)
4476 continue;
4477 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
4478 continue; /* skip hidden raid components */
4479 if (vdevice->vtarget->raidVolume)
4480 continue; /* skip hidden raid components */
4481 channel = vdevice->vtarget->channel;
4482 id = vdevice->vtarget->id;
4483 lun = vdevice->lun;
4484 if (mptsas_issue_tm(ioc, MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK,
4485 channel, id, (u64)lun, task_context, 30, &issue_reset))
4486 goto out;
4487 query_count++;
4488 termination_count +=
4489 le32_to_cpu(pScsiTmReply->TerminationCount);
4490 if ((pScsiTmReply->IOCStatus == MPI_IOCSTATUS_SUCCESS) &&
4491 (pScsiTmReply->ResponseCode ==
4492 MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
4493 pScsiTmReply->ResponseCode ==
4494 MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC))
4495 continue;
4496 if (mptsas_issue_tm(ioc,
4497 MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET,
4498 channel, id, (u64)lun, 0, 30, &issue_reset))
4499 goto out;
4500 termination_count +=
4501 le32_to_cpu(pScsiTmReply->TerminationCount);
4502 }
4503
4504 out:
4505 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4506 "%s - exit, query_count = %d termination_count = %d\n",
4507 ioc->name, __func__, query_count, termination_count));
4508
4509 ioc->broadcast_aen_busy = 0;
4510 mpt_clear_taskmgmt_in_progress_flag(ioc);
4511 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4512
4513 if (issue_reset) {
4514 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
4515 ioc->name, __func__);
4516 mpt_HardResetHandler(ioc, CAN_SLEEP);
4517 }
4518 mptsas_free_fw_event(ioc, fw_event);
4519}
4520
b506ade9
EM
4521/*
4522 * mptsas_send_ir2_event - handle exposing hidden disk when
4523 * an inactive raid volume is added
4524 *
4525 * @ioc: Pointer to MPT_ADAPTER structure
4526 * @ir2_data
4527 *
4528 */
4529static void
3eb0822c 4530mptsas_send_ir2_event(struct fw_event_work *fw_event)
b506ade9 4531{
3eb0822c
KD
4532 MPT_ADAPTER *ioc;
4533 struct mptsas_hotplug_event hot_plug_info;
4534 MPI_EVENT_DATA_IR2 *ir2_data;
4535 u8 reasonCode;
a7938b0b 4536 RaidPhysDiskPage0_t phys_disk;
3eb0822c
KD
4537
4538 ioc = fw_event->ioc;
4539 ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data;
4540 reasonCode = ir2_data->ReasonCode;
4541
4542 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4543 "ReasonCode=%02x\n", ioc->name, __func__, reasonCode));
4544
4545 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4546 hot_plug_info.id = ir2_data->TargetID;
4547 hot_plug_info.channel = ir2_data->Bus;
4548 switch (reasonCode) {
4549 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
4550 hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
4551 break;
a7938b0b
KD
4552 case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
4553 hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4554 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
4555 break;
4556 case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
4557 hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4558 mpt_raid_phys_disk_pg0(ioc,
4559 ir2_data->PhysDiskNum, &phys_disk);
4560 hot_plug_info.id = phys_disk.PhysDiskID;
4561 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
4562 break;
3eb0822c
KD
4563 default:
4564 mptsas_free_fw_event(ioc, fw_event);
b506ade9 4565 return;
3eb0822c
KD
4566 }
4567 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4568}
e6b2d76a 4569
9a28f49a
CH
4570static int
4571mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
4572{
3eb0822c
KD
4573 u32 event = le32_to_cpu(reply->Event);
4574 int sz, event_data_sz;
4575 struct fw_event_work *fw_event;
4576 unsigned long delay;
9a28f49a 4577
3eb0822c
KD
4578 /* events turned off due to host reset or driver unloading */
4579 if (ioc->fw_events_off)
4580 return 0;
e6b2d76a 4581
3eb0822c 4582 delay = msecs_to_jiffies(1);
9a28f49a 4583 switch (event) {
db7051b2
KD
4584 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
4585 {
4586 EVENT_DATA_SAS_BROADCAST_PRIMITIVE *broadcast_event_data =
4587 (EVENT_DATA_SAS_BROADCAST_PRIMITIVE *)reply->Data;
4588 if (broadcast_event_data->Primitive !=
4589 MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
4590 return 0;
4591 if (ioc->broadcast_aen_busy)
4592 return 0;
4593 ioc->broadcast_aen_busy = 1;
4594 break;
4595 }
9a28f49a 4596 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
3eb0822c
KD
4597 {
4598 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
4599 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
4600
4601 if (sas_event_data->ReasonCode ==
4602 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
4603 mptsas_target_reset_queue(ioc, sas_event_data);
4604 return 0;
4605 }
79de278e 4606 break;
3eb0822c 4607 }
f9c34022
KD
4608 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
4609 {
4610 MpiEventDataSasExpanderStatusChange_t *expander_data =
4611 (MpiEventDataSasExpanderStatusChange_t *)reply->Data;
4612
eedf92b9
KD
4613 if (ioc->old_sas_discovery_protocal)
4614 return 0;
f9c34022
KD
4615
4616 if (expander_data->ReasonCode ==
4617 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING &&
4618 ioc->device_missing_delay)
4619 delay = HZ * ioc->device_missing_delay;
e6b2d76a 4620 break;
f9c34022
KD
4621 }
4622 case MPI_EVENT_SAS_DISCOVERY:
4623 {
4624 u32 discovery_status;
4625 EventDataSasDiscovery_t *discovery_data =
4626 (EventDataSasDiscovery_t *)reply->Data;
4627
4628 discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
4629 ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
eedf92b9
KD
4630 if (ioc->old_sas_discovery_protocal && !discovery_status)
4631 mptsas_queue_rescan(ioc);
f9c34022
KD
4632 return 0;
4633 }
3eb0822c
KD
4634 case MPI_EVENT_INTEGRATED_RAID:
4635 case MPI_EVENT_PERSISTENT_TABLE_FULL:
b506ade9 4636 case MPI_EVENT_IR2:
3eb0822c
KD
4637 case MPI_EVENT_SAS_PHY_LINK_STATUS:
4638 case MPI_EVENT_QUEUE_FULL:
b506ade9 4639 break;
9a28f49a 4640 default:
3eb0822c 4641 return 0;
9a28f49a 4642 }
c73787ee 4643
3eb0822c
KD
4644 event_data_sz = ((reply->MsgLength * 4) -
4645 offsetof(EventNotificationReply_t, Data));
4646 sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
4647 fw_event = kzalloc(sz, GFP_ATOMIC);
4648 if (!fw_event) {
4649 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
4650 __func__, __LINE__);
4651 return 0;
4652 }
4653 memcpy(fw_event->event_data, reply->Data, event_data_sz);
4654 fw_event->event = event;
4655 fw_event->ioc = ioc;
4656 mptsas_add_fw_event(ioc, fw_event, delay);
4657 return 0;
9a28f49a
CH
4658}
4659
a7938b0b
KD
4660/* Delete a volume when no longer listed in ioc pg2
4661 */
4662static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id)
4663{
4664 struct scsi_device *sdev;
4665 int i;
4666
4667 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0);
4668 if (!sdev)
4669 return;
4670 if (!ioc->raid_data.pIocPg2)
4671 goto out;
4672 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
4673 goto out;
4674 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
4675 if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id)
4676 goto release_sdev;
4677 out:
4678 printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
4679 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id);
4680 scsi_remove_device(sdev);
4681 release_sdev:
4682 scsi_device_put(sdev);
4683}
4684
0c33b27d
CH
4685static int
4686mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
4687{
4688 struct Scsi_Host *sh;
4689 MPT_SCSI_HOST *hd;
4690 MPT_ADAPTER *ioc;
4691 unsigned long flags;
1ca00bb7 4692 int ii;
0c33b27d
CH
4693 int numSGE = 0;
4694 int scale;
4695 int ioc_cap;
0c33b27d
CH
4696 int error=0;
4697 int r;
4698
4699 r = mpt_attach(pdev,id);
4700 if (r)
4701 return r;
4702
4703 ioc = pci_get_drvdata(pdev);
3eb0822c 4704 mptsas_fw_event_off(ioc);
0c33b27d
CH
4705 ioc->DoneCtx = mptsasDoneCtx;
4706 ioc->TaskCtx = mptsasTaskCtx;
4707 ioc->InternalCtx = mptsasInternalCtx;
4708
4709 /* Added sanity check on readiness of the MPT adapter.
4710 */
4711 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
4712 printk(MYIOC_s_WARN_FMT
4713 "Skipping because it's not operational!\n",
4714 ioc->name);
7acec1e7
MED
4715 error = -ENODEV;
4716 goto out_mptsas_probe;
0c33b27d
CH
4717 }
4718
4719 if (!ioc->active) {
4720 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
4721 ioc->name);
7acec1e7
MED
4722 error = -ENODEV;
4723 goto out_mptsas_probe;
0c33b27d
CH
4724 }
4725
4726 /* Sanity check - ensure at least 1 port is INITIATOR capable
4727 */
4728 ioc_cap = 0;
4729 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
4730 if (ioc->pfacts[ii].ProtocolFlags &
4731 MPI_PORTFACTS_PROTOCOL_INITIATOR)
4732 ioc_cap++;
4733 }
4734
4735 if (!ioc_cap) {
4736 printk(MYIOC_s_WARN_FMT
4737 "Skipping ioc=%p because SCSI Initiator mode "
4738 "is NOT enabled!\n", ioc->name, ioc);
466544d8 4739 return 0;
0c33b27d
CH
4740 }
4741
4742 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
4743 if (!sh) {
4744 printk(MYIOC_s_WARN_FMT
4745 "Unable to register controller with SCSI subsystem\n",
4746 ioc->name);
7acec1e7
MED
4747 error = -1;
4748 goto out_mptsas_probe;
0c33b27d
CH
4749 }
4750
4751 spin_lock_irqsave(&ioc->FreeQlock, flags);
4752
4753 /* Attach the SCSI Host to the IOC structure
4754 */
4755 ioc->sh = sh;
4756
4757 sh->io_port = 0;
4758 sh->n_io_port = 0;
4759 sh->irq = 0;
4760
4761 /* set 16 byte cdb's */
4762 sh->max_cmd_len = 16;
4763
793955f5
EM
4764 sh->max_id = ioc->pfacts[0].PortSCSIID;
4765 sh->max_lun = max_lun;
0c33b27d
CH
4766
4767 sh->transportt = mptsas_transport_template;
4768
0c33b27d
CH
4769 /* Required entry.
4770 */
4771 sh->unique_id = ioc->id;
4772
4773 INIT_LIST_HEAD(&ioc->sas_topology);
9a28f49a 4774 mutex_init(&ioc->sas_topology_mutex);
e6b2d76a 4775 mutex_init(&ioc->sas_discovery_mutex);
eeb846ce 4776 mutex_init(&ioc->sas_mgmt.mutex);
da4fa655 4777 init_completion(&ioc->sas_mgmt.done);
0c33b27d
CH
4778
4779 /* Verify that we won't exceed the maximum
4780 * number of chain buffers
4781 * We can optimize: ZZ = req_sz/sizeof(SGE)
4782 * For 32bit SGE's:
4783 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
4784 * + (req_sz - 64)/sizeof(SGE)
4785 * A slightly different algorithm is required for
4786 * 64bit SGEs.
4787 */
14d0f0b0
KD
4788 scale = ioc->req_sz/ioc->SGE_size;
4789 if (ioc->sg_addr_size == sizeof(u64)) {
0c33b27d
CH
4790 numSGE = (scale - 1) *
4791 (ioc->facts.MaxChainDepth-1) + scale +
14d0f0b0 4792 (ioc->req_sz - 60) / ioc->SGE_size;
0c33b27d
CH
4793 } else {
4794 numSGE = 1 + (scale - 1) *
4795 (ioc->facts.MaxChainDepth-1) + scale +
14d0f0b0 4796 (ioc->req_sz - 64) / ioc->SGE_size;
0c33b27d
CH
4797 }
4798
4799 if (numSGE < sh->sg_tablesize) {
4800 /* Reset this value */
d6ecdd63 4801 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
0c33b27d
CH
4802 "Resetting sg_tablesize to %d from %d\n",
4803 ioc->name, numSGE, sh->sg_tablesize));
4804 sh->sg_tablesize = numSGE;
4805 }
4806
e7eae9f6 4807 hd = shost_priv(sh);
0c33b27d
CH
4808 hd->ioc = ioc;
4809
4810 /* SCSI needs scsi_cmnd lookup table!
4811 * (with size equal to req_depth*PtrSz!)
4812 */
e8206381
EM
4813 ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
4814 if (!ioc->ScsiLookup) {
0c33b27d 4815 error = -ENOMEM;
bc6e089a 4816 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
7acec1e7 4817 goto out_mptsas_probe;
0c33b27d 4818 }
e8206381 4819 spin_lock_init(&ioc->scsi_lookup_lock);
0c33b27d 4820
d6ecdd63 4821 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
e8206381 4822 ioc->name, ioc->ScsiLookup));
0c33b27d 4823
0c33b27d
CH
4824 ioc->sas_data.ptClear = mpt_pt_clear;
4825
df9e062a
EM
4826 hd->last_queue_full = 0;
4827 INIT_LIST_HEAD(&hd->target_reset_list);
3eb0822c
KD
4828 INIT_LIST_HEAD(&ioc->sas_device_info_list);
4829 mutex_init(&ioc->sas_device_info_mutex);
4830
df9e062a
EM
4831 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4832
0c33b27d
CH
4833 if (ioc->sas_data.ptClear==1) {
4834 mptbase_sas_persist_operation(
4835 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
4836 }
4837
0c33b27d
CH
4838 error = scsi_add_host(sh, &ioc->pcidev->dev);
4839 if (error) {
29dd3609
EM
4840 dprintk(ioc, printk(MYIOC_s_ERR_FMT
4841 "scsi_add_host failed\n", ioc->name));
7acec1e7 4842 goto out_mptsas_probe;
0c33b27d
CH
4843 }
4844
eedf92b9
KD
4845 /* older firmware doesn't support expander events */
4846 if ((ioc->facts.HeaderVersion >> 8) < 0xE)
4847 ioc->old_sas_discovery_protocal = 1;
0c33b27d 4848 mptsas_scan_sas_topology(ioc);
3eb0822c 4849 mptsas_fw_event_on(ioc);
0c33b27d
CH
4850 return 0;
4851
547f9a21 4852 out_mptsas_probe:
0c33b27d
CH
4853
4854 mptscsih_remove(pdev);
4855 return error;
4856}
4857
7b5a65b9
KD
4858void
4859mptsas_shutdown(struct pci_dev *pdev)
4860{
4861 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
4862
3eb0822c
KD
4863 mptsas_fw_event_off(ioc);
4864 mptsas_cleanup_fw_event_q(ioc);
7b5a65b9
KD
4865}
4866
0c33b27d
CH
4867static void __devexit mptsas_remove(struct pci_dev *pdev)
4868{
4869 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
4870 struct mptsas_portinfo *p, *n;
547f9a21 4871 int i;
0c33b27d 4872
7b5a65b9
KD
4873 mptsas_shutdown(pdev);
4874
3eb0822c
KD
4875 mptsas_del_device_components(ioc);
4876
b506ade9 4877 ioc->sas_discovery_ignore_events = 1;
0c33b27d
CH
4878 sas_remove_host(ioc->sh);
4879
9a28f49a 4880 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
4881 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
4882 list_del(&p->list);
547f9a21 4883 for (i = 0 ; i < p->num_phys ; i++)
d6ecdd63 4884 mptsas_port_delete(ioc, p->phy_info[i].port_details);
3eb0822c 4885
547f9a21 4886 kfree(p->phy_info);
0c33b27d
CH
4887 kfree(p);
4888 }
9a28f49a 4889 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022 4890 ioc->hba_port_info = NULL;
0c33b27d
CH
4891 mptscsih_remove(pdev);
4892}
4893
4894static struct pci_device_id mptsas_pci_table[] = {
87cf8986 4895 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
0c33b27d 4896 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4897 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
0c33b27d 4898 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4899 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
0c33b27d 4900 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4901 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
0c33b27d 4902 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4903 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
0c33b27d
CH
4904 PCI_ANY_ID, PCI_ANY_ID },
4905 {0} /* Terminating entry */
4906};
4907MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
4908
4909
4910static struct pci_driver mptsas_driver = {
4911 .name = "mptsas",
4912 .id_table = mptsas_pci_table,
4913 .probe = mptsas_probe,
4914 .remove = __devexit_p(mptsas_remove),
7b5a65b9 4915 .shutdown = mptsas_shutdown,
0c33b27d
CH
4916#ifdef CONFIG_PM
4917 .suspend = mptscsih_suspend,
4918 .resume = mptscsih_resume,
4919#endif
4920};
4921
4922static int __init
4923mptsas_init(void)
4924{
57ce21bf
PS
4925 int error;
4926
0c33b27d
CH
4927 show_mptmod_ver(my_NAME, my_VERSION);
4928
4929 mptsas_transport_template =
4930 sas_attach_transport(&mptsas_transport_functions);
4931 if (!mptsas_transport_template)
4932 return -ENODEV;
4933
4934 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
e7deff33 4935 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
0c33b27d
CH
4936 mptsasInternalCtx =
4937 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
da4fa655 4938 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
e7deff33
KD
4939 mptsasDeviceResetCtx =
4940 mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
0c33b27d 4941
d6ecdd63
PS
4942 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
4943 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
0c33b27d 4944
57ce21bf
PS
4945 error = pci_register_driver(&mptsas_driver);
4946 if (error)
4947 sas_release_transport(mptsas_transport_template);
4948
4949 return error;
0c33b27d
CH
4950}
4951
4952static void __exit
4953mptsas_exit(void)
4954{
4955 pci_unregister_driver(&mptsas_driver);
4956 sas_release_transport(mptsas_transport_template);
4957
4958 mpt_reset_deregister(mptsasDoneCtx);
4959 mpt_event_deregister(mptsasDoneCtx);
4960
da4fa655 4961 mpt_deregister(mptsasMgmtCtx);
0c33b27d
CH
4962 mpt_deregister(mptsasInternalCtx);
4963 mpt_deregister(mptsasTaskCtx);
4964 mpt_deregister(mptsasDoneCtx);
e7deff33 4965 mpt_deregister(mptsasDeviceResetCtx);
0c33b27d
CH
4966}
4967
4968module_init(mptsas_init);
4969module_exit(mptsas_exit);
This page took 0.759912 seconds and 5 git commands to generate.