Lines Matching +full:- +full:a
5 * Copyright (c) 2001-2013 ATTO Technology, Inc.
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
38 * You should have received a copy of the GNU General Public License
40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
49 * Buffered ioctl handlers. A buffered ioctl is one which requires that we
50 * allocate a DMA-able memory area to communicate with the firmware. In
52 * we will allocate a global buffer the first time we need it and re-use
70 struct esas2r_adapter *a; member
84 static void complete_fm_api_req(struct esas2r_adapter *a, in complete_fm_api_req() argument
87 a->fm_api_command_done = 1; in complete_fm_api_req()
88 wake_up_interruptible(&a->fm_api_waiter); in complete_fm_api_req()
94 struct esas2r_adapter *a = (struct esas2r_adapter *)sgc->adapter; in get_physaddr_fm_api() local
95 int offset = sgc->cur_offset - a->save_offset; in get_physaddr_fm_api()
97 (*addr) = a->firmware.phys + offset; in get_physaddr_fm_api()
98 return a->firmware.orig_len - offset; in get_physaddr_fm_api()
103 struct esas2r_adapter *a = (struct esas2r_adapter *)sgc->adapter; in get_physaddr_fm_api_header() local
104 int offset = sgc->cur_offset - a->save_offset; in get_physaddr_fm_api_header()
106 (*addr) = a->firmware.header_buff_phys + offset; in get_physaddr_fm_api_header()
107 return sizeof(struct esas2r_flash_img) - offset; in get_physaddr_fm_api_header()
111 static void do_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi) in do_fm_api() argument
115 if (mutex_lock_interruptible(&a->fm_api_mutex)) { in do_fm_api()
116 fi->status = FI_STAT_BUSY; in do_fm_api()
120 rq = esas2r_alloc_request(a); in do_fm_api()
122 fi->status = FI_STAT_BUSY; in do_fm_api()
126 if (fi == &a->firmware.header) { in do_fm_api()
127 a->firmware.header_buff = dma_alloc_coherent(&a->pcid->dev, in do_fm_api()
131 (dma_addr_t *)&a-> in do_fm_api()
136 if (a->firmware.header_buff == NULL) { in do_fm_api()
138 fi->status = FI_STAT_BUSY; in do_fm_api()
142 memcpy(a->firmware.header_buff, fi, in do_fm_api()
144 a->save_offset = a->firmware.header_buff; in do_fm_api()
145 a->fm_api_sgc.get_phys_addr = in do_fm_api()
148 a->save_offset = (u8 *)fi; in do_fm_api()
149 a->fm_api_sgc.get_phys_addr = in do_fm_api()
153 rq->comp_cb = complete_fm_api_req; in do_fm_api()
154 a->fm_api_command_done = 0; in do_fm_api()
155 a->fm_api_sgc.cur_offset = a->save_offset; in do_fm_api()
157 if (!esas2r_fm_api(a, (struct esas2r_flash_img *)a->save_offset, rq, in do_fm_api()
158 &a->fm_api_sgc)) in do_fm_api()
162 while (!a->fm_api_command_done) in do_fm_api()
163 wait_event_interruptible(a->fm_api_waiter, in do_fm_api()
164 a->fm_api_command_done); in do_fm_api()
166 if (fi == &a->firmware.header) { in do_fm_api()
167 memcpy(fi, a->firmware.header_buff, in do_fm_api()
170 dma_free_coherent(&a->pcid->dev, in do_fm_api()
172 a->firmware.header_buff, in do_fm_api()
173 (dma_addr_t)a->firmware.header_buff_phys); in do_fm_api()
176 esas2r_free_request(a, (struct esas2r_request *)rq); in do_fm_api()
178 mutex_unlock(&a->fm_api_mutex); in do_fm_api()
183 static void complete_nvr_req(struct esas2r_adapter *a, in complete_nvr_req() argument
186 a->nvram_command_done = 1; in complete_nvr_req()
187 wake_up_interruptible(&a->nvram_waiter); in complete_nvr_req()
194 int offset = (u8 *)sgc->cur_offset - esas2r_buffered_ioctl; in get_physaddr_buffered_ioctl()
197 return esas2r_buffered_ioctl_size - offset; in get_physaddr_buffered_ioctl()
200 static void complete_buffered_ioctl_req(struct esas2r_adapter *a, in complete_buffered_ioctl_req() argument
203 a->buffered_ioctl_done = 1; in complete_buffered_ioctl_req()
204 wake_up_interruptible(&a->buffered_ioctl_waiter); in complete_buffered_ioctl_req()
209 struct esas2r_adapter *a = bi->a; in handle_buffered_ioctl() local
217 /* allocate a buffer or use the existing buffer. */ in handle_buffered_ioctl()
219 if (esas2r_buffered_ioctl_size < bi->length) { in handle_buffered_ioctl()
220 /* free the too-small buffer and get a new one */ in handle_buffered_ioctl()
221 dma_free_coherent(&a->pcid->dev, in handle_buffered_ioctl()
230 esas2r_buffered_ioctl_size = bi->length; in handle_buffered_ioctl()
231 esas2r_buffered_ioctl_pcid = a->pcid; in handle_buffered_ioctl()
232 esas2r_buffered_ioctl = dma_alloc_coherent(&a->pcid->dev, in handle_buffered_ioctl()
243 "for a buffered ioctl!", in handle_buffered_ioctl()
244 bi->length); in handle_buffered_ioctl()
251 memcpy(esas2r_buffered_ioctl, bi->ioctl, bi->length); in handle_buffered_ioctl()
253 rq = esas2r_alloc_request(a); in handle_buffered_ioctl()
259 esas2r_debug("buffered ioctl - no requests"); in handle_buffered_ioctl()
263 a->buffered_ioctl_done = 0; in handle_buffered_ioctl()
264 rq->comp_cb = complete_buffered_ioctl_req; in handle_buffered_ioctl()
265 sgc.cur_offset = esas2r_buffered_ioctl + bi->offset; in handle_buffered_ioctl()
269 if (!(*bi->callback)(a, rq, &sgc, bi->context)) { in handle_buffered_ioctl()
271 a->buffered_ioctl_done = 0; in handle_buffered_ioctl()
276 while (!a->buffered_ioctl_done) in handle_buffered_ioctl()
277 wait_event_interruptible(a->buffered_ioctl_waiter, in handle_buffered_ioctl()
278 a->buffered_ioctl_done); in handle_buffered_ioctl()
281 if (result == IOCTL_SUCCESS && bi->done_callback) in handle_buffered_ioctl()
282 (*bi->done_callback)(a, rq, bi->done_context); in handle_buffered_ioctl()
284 esas2r_free_request(a, rq); in handle_buffered_ioctl()
288 memcpy(bi->ioctl, esas2r_buffered_ioctl, bi->length); in handle_buffered_ioctl()
295 static int smp_ioctl_callback(struct esas2r_adapter *a, in smp_ioctl_callback() argument
302 esas2r_sgc_init(sgc, a, rq, rq->vrq->ioctl.sge); in smp_ioctl_callback()
303 esas2r_build_ioctl_req(a, rq, sgc->length, VDA_IOCTL_SMP); in smp_ioctl_callback()
305 if (!esas2r_build_sg_list(a, rq, sgc)) { in smp_ioctl_callback()
306 si->status = ATTO_STS_OUT_OF_RSRC; in smp_ioctl_callback()
310 esas2r_start_request(a, rq); in smp_ioctl_callback()
314 static u8 handle_smp_ioctl(struct esas2r_adapter *a, struct atto_ioctl_smp *si) in handle_smp_ioctl() argument
320 bi.a = a; in handle_smp_ioctl()
323 + le32_to_cpu(si->req_length) in handle_smp_ioctl()
324 + le32_to_cpu(si->rsp_length); in handle_smp_ioctl()
332 static void esas2r_csmi_ioctl_tunnel_comp_cb(struct esas2r_adapter *a, in esas2r_csmi_ioctl_tunnel_comp_cb() argument
335 rq->target_id = le16_to_cpu(rq->func_rsp.ioctl_rsp.csmi.target_id); in esas2r_csmi_ioctl_tunnel_comp_cb()
336 rq->vrq->scsi.flags |= cpu_to_le32(rq->func_rsp.ioctl_rsp.csmi.lun); in esas2r_csmi_ioctl_tunnel_comp_cb()
339 (*rq->aux_req_cb)(a, rq); in esas2r_csmi_ioctl_tunnel_comp_cb()
342 /* Tunnel a CSMI IOCTL to the back end driver for processing. */
343 static bool csmi_ioctl_tunnel(struct esas2r_adapter *a, in csmi_ioctl_tunnel() argument
350 struct atto_vda_ioctl_req *ioctl = &rq->vrq->ioctl; in csmi_ioctl_tunnel()
352 if (test_bit(AF_DEGRADED_MODE, &a->flags)) in csmi_ioctl_tunnel()
355 esas2r_sgc_init(sgc, a, rq, rq->vrq->ioctl.sge); in csmi_ioctl_tunnel()
356 esas2r_build_ioctl_req(a, rq, sgc->length, VDA_IOCTL_CSMI); in csmi_ioctl_tunnel()
357 ioctl->csmi.ctrl_code = cpu_to_le32(ctrl_code); in csmi_ioctl_tunnel()
358 ioctl->csmi.target_id = cpu_to_le16(target_id); in csmi_ioctl_tunnel()
359 ioctl->csmi.lun = (u8)le32_to_cpu(rq->vrq->scsi.flags); in csmi_ioctl_tunnel()
365 rq->aux_req_cx = ci; in csmi_ioctl_tunnel()
366 rq->aux_req_cb = rq->comp_cb; in csmi_ioctl_tunnel()
367 rq->comp_cb = esas2r_csmi_ioctl_tunnel_comp_cb; in csmi_ioctl_tunnel()
369 if (!esas2r_build_sg_list(a, rq, sgc)) in csmi_ioctl_tunnel()
372 esas2r_start_request(a, rq); in csmi_ioctl_tunnel()
392 static int csmi_ioctl_callback(struct esas2r_adapter *a, in csmi_ioctl_callback() argument
406 if (ci->control_code == CSMI_CC_GET_DEV_ADDR) { in csmi_ioctl_callback()
407 struct atto_csmi_get_dev_addr *gda = &ci->data.dev_addr; in csmi_ioctl_callback()
409 path = gda->path_id; in csmi_ioctl_callback()
410 tid = gda->target_id; in csmi_ioctl_callback()
411 lun = gda->lun; in csmi_ioctl_callback()
412 } else if (ci->control_code == CSMI_CC_TASK_MGT) { in csmi_ioctl_callback()
413 struct atto_csmi_task_mgmt *tm = &ci->data.tsk_mgt; in csmi_ioctl_callback()
415 path = tm->path_id; in csmi_ioctl_callback()
416 tid = tm->target_id; in csmi_ioctl_callback()
417 lun = tm->lun; in csmi_ioctl_callback()
421 rq->func_rsp.ioctl_rsp.csmi.csmi_status = cpu_to_le32( in csmi_ioctl_callback()
426 rq->target_id = tid; in csmi_ioctl_callback()
427 rq->vrq->scsi.flags |= cpu_to_le32(lun); in csmi_ioctl_callback()
429 switch (ci->control_code) { in csmi_ioctl_callback()
432 struct atto_csmi_get_driver_info *gdi = &ioctl_csmi->drvr_info; in csmi_ioctl_callback()
434 strcpy(gdi->description, esas2r_get_model_name(a)); in csmi_ioctl_callback()
435 gdi->csmi_major_rev = CSMI_MAJOR_REV; in csmi_ioctl_callback()
436 gdi->csmi_minor_rev = CSMI_MINOR_REV; in csmi_ioctl_callback()
442 struct atto_csmi_get_cntlr_cfg *gcc = &ioctl_csmi->cntlr_cfg; in csmi_ioctl_callback()
444 gcc->base_io_addr = 0; in csmi_ioctl_callback()
445 pci_read_config_dword(a->pcid, PCI_BASE_ADDRESS_2, in csmi_ioctl_callback()
446 &gcc->base_memaddr_lo); in csmi_ioctl_callback()
447 pci_read_config_dword(a->pcid, PCI_BASE_ADDRESS_3, in csmi_ioctl_callback()
448 &gcc->base_memaddr_hi); in csmi_ioctl_callback()
449 gcc->board_id = MAKEDWORD(a->pcid->subsystem_device, in csmi_ioctl_callback()
450 a->pcid->subsystem_vendor); in csmi_ioctl_callback()
451 gcc->slot_num = CSMI_SLOT_NUM_UNKNOWN; in csmi_ioctl_callback()
452 gcc->cntlr_class = CSMI_CNTLR_CLASS_HBA; in csmi_ioctl_callback()
453 gcc->io_bus_type = CSMI_BUS_TYPE_PCI; in csmi_ioctl_callback()
454 gcc->pci_addr.bus_num = a->pcid->bus->number; in csmi_ioctl_callback()
455 gcc->pci_addr.device_num = PCI_SLOT(a->pcid->devfn); in csmi_ioctl_callback()
456 gcc->pci_addr.function_num = PCI_FUNC(a->pcid->devfn); in csmi_ioctl_callback()
458 memset(gcc->serial_num, 0, sizeof(gcc->serial_num)); in csmi_ioctl_callback()
460 gcc->major_rev = LOBYTE(LOWORD(a->fw_version)); in csmi_ioctl_callback()
461 gcc->minor_rev = HIBYTE(LOWORD(a->fw_version)); in csmi_ioctl_callback()
462 gcc->build_rev = LOBYTE(HIWORD(a->fw_version)); in csmi_ioctl_callback()
463 gcc->release_rev = HIBYTE(HIWORD(a->fw_version)); in csmi_ioctl_callback()
464 gcc->bios_major_rev = HIBYTE(HIWORD(a->flash_ver)); in csmi_ioctl_callback()
465 gcc->bios_minor_rev = LOBYTE(HIWORD(a->flash_ver)); in csmi_ioctl_callback()
466 gcc->bios_build_rev = LOWORD(a->flash_ver); in csmi_ioctl_callback()
468 if (test_bit(AF2_THUNDERLINK, &a->flags2)) in csmi_ioctl_callback()
469 gcc->cntlr_flags = CSMI_CNTLRF_SAS_HBA in csmi_ioctl_callback()
472 gcc->cntlr_flags = CSMI_CNTLRF_SAS_RAID in csmi_ioctl_callback()
475 gcc->rrom_major_rev = 0; in csmi_ioctl_callback()
476 gcc->rrom_minor_rev = 0; in csmi_ioctl_callback()
477 gcc->rrom_build_rev = 0; in csmi_ioctl_callback()
478 gcc->rrom_release_rev = 0; in csmi_ioctl_callback()
479 gcc->rrom_biosmajor_rev = 0; in csmi_ioctl_callback()
480 gcc->rrom_biosminor_rev = 0; in csmi_ioctl_callback()
481 gcc->rrom_biosbuild_rev = 0; in csmi_ioctl_callback()
482 gcc->rrom_biosrelease_rev = 0; in csmi_ioctl_callback()
488 struct atto_csmi_get_cntlr_sts *gcs = &ioctl_csmi->cntlr_sts; in csmi_ioctl_callback()
490 if (test_bit(AF_DEGRADED_MODE, &a->flags)) in csmi_ioctl_callback()
491 gcs->status = CSMI_CNTLR_STS_FAILED; in csmi_ioctl_callback()
493 gcs->status = CSMI_CNTLR_STS_GOOD; in csmi_ioctl_callback()
495 gcs->offline_reason = CSMI_OFFLINE_NO_REASON; in csmi_ioctl_callback()
516 if (!csmi_ioctl_tunnel(a, ioctl_csmi, rq, sgc, in csmi_ioctl_callback()
517 ci->control_code, in csmi_ioctl_callback()
527 struct atto_csmi_get_scsi_addr *gsa = &ioctl_csmi->scsi_addr; in csmi_ioctl_callback()
531 memcpy(&lun, gsa->sas_lun, sizeof(struct scsi_lun)); in csmi_ioctl_callback()
539 spin_lock_irqsave(&a->mem_lock, flags); in csmi_ioctl_callback()
540 t = esas2r_targ_db_find_by_sas_addr(a, (u64 *)gsa->sas_addr); in csmi_ioctl_callback()
541 spin_unlock_irqrestore(&a->mem_lock, flags); in csmi_ioctl_callback()
548 gsa->host_index = 0xFF; in csmi_ioctl_callback()
549 gsa->lun = gsa->sas_lun[1]; in csmi_ioctl_callback()
550 rq->target_id = esas2r_targ_get_id(t, a); in csmi_ioctl_callback()
556 struct atto_csmi_get_dev_addr *gda = &ioctl_csmi->dev_addr; in csmi_ioctl_callback()
559 t = a->targetdb + rq->target_id; in csmi_ioctl_callback()
561 if (t >= a->targetdb_end in csmi_ioctl_callback()
562 || t->target_state != TS_PRESENT in csmi_ioctl_callback()
563 || t->sas_addr == 0) { in csmi_ioctl_callback()
569 *(u64 *)gda->sas_addr = t->sas_addr; in csmi_ioctl_callback()
570 memset(gda->sas_lun, 0, sizeof(gda->sas_lun)); in csmi_ioctl_callback()
571 gda->sas_lun[1] = (u8)le32_to_cpu(rq->vrq->scsi.flags); in csmi_ioctl_callback()
578 t = a->targetdb + rq->target_id; in csmi_ioctl_callback()
580 if (t >= a->targetdb_end in csmi_ioctl_callback()
581 || t->target_state != TS_PRESENT in csmi_ioctl_callback()
582 || !(t->flags & TF_PASS_THRU)) { in csmi_ioctl_callback()
587 if (!csmi_ioctl_tunnel(a, ioctl_csmi, rq, sgc, in csmi_ioctl_callback()
588 ci->control_code, in csmi_ioctl_callback()
589 t->phys_targ_id)) { in csmi_ioctl_callback()
602 rq->func_rsp.ioctl_rsp.csmi.csmi_status = cpu_to_le32(sts); in csmi_ioctl_callback()
608 static void csmi_ioctl_done_callback(struct esas2r_adapter *a, in csmi_ioctl_done_callback() argument
615 switch (ci->control_code) { in csmi_ioctl_done_callback()
619 &ioctl_csmi->drvr_info; in csmi_ioctl_done_callback()
621 strcpy(gdi->name, ESAS2R_VERSION_STR); in csmi_ioctl_done_callback()
623 gdi->major_rev = ESAS2R_MAJOR_REV; in csmi_ioctl_done_callback()
624 gdi->minor_rev = ESAS2R_MINOR_REV; in csmi_ioctl_done_callback()
625 gdi->build_rev = 0; in csmi_ioctl_done_callback()
626 gdi->release_rev = 0; in csmi_ioctl_done_callback()
632 struct atto_csmi_get_scsi_addr *gsa = &ioctl_csmi->scsi_addr; in csmi_ioctl_done_callback()
634 if (le32_to_cpu(rq->func_rsp.ioctl_rsp.csmi.csmi_status) == in csmi_ioctl_done_callback()
636 gsa->target_id = rq->target_id; in csmi_ioctl_done_callback()
637 gsa->path_id = 0; in csmi_ioctl_done_callback()
644 ci->status = le32_to_cpu(rq->func_rsp.ioctl_rsp.csmi.csmi_status); in csmi_ioctl_done_callback()
648 static u8 handle_csmi_ioctl(struct esas2r_adapter *a, struct atto_csmi *ci) in handle_csmi_ioctl() argument
654 bi.a = a; in handle_csmi_ioctl()
655 bi.ioctl = &ci->data; in handle_csmi_ioctl()
669 static bool hba_ioctl_tunnel(struct esas2r_adapter *a, in hba_ioctl_tunnel() argument
674 esas2r_sgc_init(sgc, a, rq, rq->vrq->ioctl.sge); in hba_ioctl_tunnel()
676 esas2r_build_ioctl_req(a, rq, sgc->length, VDA_IOCTL_HBA); in hba_ioctl_tunnel()
678 if (!esas2r_build_sg_list(a, rq, sgc)) { in hba_ioctl_tunnel()
679 hi->status = ATTO_STS_OUT_OF_RSRC; in hba_ioctl_tunnel()
684 esas2r_start_request(a, rq); in hba_ioctl_tunnel()
689 static void scsi_passthru_comp_cb(struct esas2r_adapter *a, in scsi_passthru_comp_cb() argument
692 struct atto_ioctl *hi = (struct atto_ioctl *)rq->aux_req_cx; in scsi_passthru_comp_cb()
693 struct atto_hba_scsi_pass_thru *spt = &hi->data.scsi_pass_thru; in scsi_passthru_comp_cb()
696 spt->scsi_status = rq->func_rsp.scsi_rsp.scsi_stat; in scsi_passthru_comp_cb()
697 spt->sense_length = rq->sense_len; in scsi_passthru_comp_cb()
698 spt->residual_length = in scsi_passthru_comp_cb()
699 le32_to_cpu(rq->func_rsp.scsi_rsp.residual_length); in scsi_passthru_comp_cb()
701 switch (rq->req_stat) { in scsi_passthru_comp_cb()
736 spt->req_status = sts; in scsi_passthru_comp_cb()
739 spt->target_id = in scsi_passthru_comp_cb()
740 esas2r_targ_db_find_next_present(a, (u16)spt->target_id); in scsi_passthru_comp_cb()
743 (*rq->aux_req_cb)(a, rq); in scsi_passthru_comp_cb()
746 static int hba_ioctl_callback(struct esas2r_adapter *a, in hba_ioctl_callback() argument
753 hi->status = ATTO_STS_SUCCESS; in hba_ioctl_callback()
755 switch (hi->function) { in hba_ioctl_callback()
758 u8 *class_code = (u8 *)&a->pcid->class; in hba_ioctl_callback()
761 &hi->data.get_adap_info; in hba_ioctl_callback()
763 if (hi->flags & HBAF_TUNNEL) { in hba_ioctl_callback()
764 hi->status = ATTO_STS_UNSUPPORTED; in hba_ioctl_callback()
768 if (hi->version > ATTO_VER_GET_ADAP_INFO0) { in hba_ioctl_callback()
769 hi->status = ATTO_STS_INV_VERSION; in hba_ioctl_callback()
770 hi->version = ATTO_VER_GET_ADAP_INFO0; in hba_ioctl_callback()
776 gai->pci.vendor_id = a->pcid->vendor; in hba_ioctl_callback()
777 gai->pci.device_id = a->pcid->device; in hba_ioctl_callback()
778 gai->pci.ss_vendor_id = a->pcid->subsystem_vendor; in hba_ioctl_callback()
779 gai->pci.ss_device_id = a->pcid->subsystem_device; in hba_ioctl_callback()
780 gai->pci.class_code[0] = class_code[0]; in hba_ioctl_callback()
781 gai->pci.class_code[1] = class_code[1]; in hba_ioctl_callback()
782 gai->pci.class_code[2] = class_code[2]; in hba_ioctl_callback()
783 gai->pci.rev_id = a->pcid->revision; in hba_ioctl_callback()
784 gai->pci.bus_num = a->pcid->bus->number; in hba_ioctl_callback()
785 gai->pci.dev_num = PCI_SLOT(a->pcid->devfn); in hba_ioctl_callback()
786 gai->pci.func_num = PCI_FUNC(a->pcid->devfn); in hba_ioctl_callback()
788 if (pci_is_pcie(a->pcid)) { in hba_ioctl_callback()
792 pcie_capability_read_word(a->pcid, PCI_EXP_LNKSTA, in hba_ioctl_callback()
794 pcie_capability_read_dword(a->pcid, PCI_EXP_LNKCAP, in hba_ioctl_callback()
797 gai->pci.link_speed_curr = FIELD_GET(PCI_EXP_LNKSTA_CLS, stat); in hba_ioctl_callback()
798 gai->pci.link_speed_max = FIELD_GET(PCI_EXP_LNKCAP_SLS, caps); in hba_ioctl_callback()
799 gai->pci.link_width_curr = FIELD_GET(PCI_EXP_LNKSTA_NLW, stat); in hba_ioctl_callback()
800 gai->pci.link_width_max = FIELD_GET(PCI_EXP_LNKCAP_MLW, caps); in hba_ioctl_callback()
803 gai->pci.msi_vector_cnt = 1; in hba_ioctl_callback()
805 if (a->pcid->msix_enabled) in hba_ioctl_callback()
806 gai->pci.interrupt_mode = ATTO_GAI_PCIIM_MSIX; in hba_ioctl_callback()
807 else if (a->pcid->msi_enabled) in hba_ioctl_callback()
808 gai->pci.interrupt_mode = ATTO_GAI_PCIIM_MSI; in hba_ioctl_callback()
810 gai->pci.interrupt_mode = ATTO_GAI_PCIIM_LEGACY; in hba_ioctl_callback()
812 gai->adap_type = ATTO_GAI_AT_ESASRAID2; in hba_ioctl_callback()
814 if (test_bit(AF2_THUNDERLINK, &a->flags2)) in hba_ioctl_callback()
815 gai->adap_type = ATTO_GAI_AT_TLSASHBA; in hba_ioctl_callback()
817 if (test_bit(AF_DEGRADED_MODE, &a->flags)) in hba_ioctl_callback()
818 gai->adap_flags |= ATTO_GAI_AF_DEGRADED; in hba_ioctl_callback()
820 gai->adap_flags |= ATTO_GAI_AF_SPT_SUPP | in hba_ioctl_callback()
823 if (a->pcid->subsystem_device == ATTO_ESAS_R60F in hba_ioctl_callback()
824 || a->pcid->subsystem_device == ATTO_ESAS_R608 in hba_ioctl_callback()
825 || a->pcid->subsystem_device == ATTO_ESAS_R644 in hba_ioctl_callback()
826 || a->pcid->subsystem_device == ATTO_TSSC_3808E) in hba_ioctl_callback()
827 gai->adap_flags |= ATTO_GAI_AF_VIRT_SES; in hba_ioctl_callback()
829 gai->num_ports = ESAS2R_NUM_PHYS; in hba_ioctl_callback()
830 gai->num_phys = ESAS2R_NUM_PHYS; in hba_ioctl_callback()
832 strcpy(gai->firmware_rev, a->fw_rev); in hba_ioctl_callback()
833 strcpy(gai->flash_rev, a->flash_rev); in hba_ioctl_callback()
834 strcpy(gai->model_name_short, esas2r_get_model_name_short(a)); in hba_ioctl_callback()
835 strcpy(gai->model_name, esas2r_get_model_name(a)); in hba_ioctl_callback()
837 gai->num_targets = ESAS2R_MAX_TARGETS; in hba_ioctl_callback()
839 gai->num_busses = 1; in hba_ioctl_callback()
840 gai->num_targsper_bus = gai->num_targets; in hba_ioctl_callback()
841 gai->num_lunsper_targ = 256; in hba_ioctl_callback()
843 if (a->pcid->subsystem_device == ATTO_ESAS_R6F0 in hba_ioctl_callback()
844 || a->pcid->subsystem_device == ATTO_ESAS_R60F) in hba_ioctl_callback()
845 gai->num_connectors = 4; in hba_ioctl_callback()
847 gai->num_connectors = 2; in hba_ioctl_callback()
849 gai->adap_flags2 |= ATTO_GAI_AF2_ADAP_CTRL_SUPP; in hba_ioctl_callback()
851 gai->num_targets_backend = a->num_targets_backend; in hba_ioctl_callback()
853 gai->tunnel_flags = a->ioctl_tunnel in hba_ioctl_callback()
867 &hi->data.get_adap_addr; in hba_ioctl_callback()
869 if (hi->flags & HBAF_TUNNEL) { in hba_ioctl_callback()
870 hi->status = ATTO_STS_UNSUPPORTED; in hba_ioctl_callback()
874 if (hi->version > ATTO_VER_GET_ADAP_ADDR0) { in hba_ioctl_callback()
875 hi->status = ATTO_STS_INV_VERSION; in hba_ioctl_callback()
876 hi->version = ATTO_VER_GET_ADAP_ADDR0; in hba_ioctl_callback()
877 } else if (gaa->addr_type == ATTO_GAA_AT_PORT in hba_ioctl_callback()
878 || gaa->addr_type == ATTO_GAA_AT_NODE) { in hba_ioctl_callback()
879 if (gaa->addr_type == ATTO_GAA_AT_PORT in hba_ioctl_callback()
880 && gaa->port_id >= ESAS2R_NUM_PHYS) { in hba_ioctl_callback()
881 hi->status = ATTO_STS_NOT_APPL; in hba_ioctl_callback()
883 memcpy((u64 *)gaa->address, in hba_ioctl_callback()
884 &a->nvram->sas_addr[0], sizeof(u64)); in hba_ioctl_callback()
885 gaa->addr_len = sizeof(u64); in hba_ioctl_callback()
888 hi->status = ATTO_STS_INV_PARAM; in hba_ioctl_callback()
896 if (hi->flags & HBAF_TUNNEL) { in hba_ioctl_callback()
897 if (hba_ioctl_tunnel(a, hi, rq, sgc)) in hba_ioctl_callback()
903 hi->status = ATTO_STS_UNSUPPORTED; in hba_ioctl_callback()
910 struct atto_hba_trace *trc = &hi->data.trace; in hba_ioctl_callback()
912 if (hi->flags & HBAF_TUNNEL) { in hba_ioctl_callback()
913 if (hba_ioctl_tunnel(a, hi, rq, sgc)) in hba_ioctl_callback()
919 if (hi->version > ATTO_VER_TRACE1) { in hba_ioctl_callback()
920 hi->status = ATTO_STS_INV_VERSION; in hba_ioctl_callback()
921 hi->version = ATTO_VER_TRACE1; in hba_ioctl_callback()
925 if (trc->trace_type == ATTO_TRC_TT_FWCOREDUMP in hba_ioctl_callback()
926 && hi->version >= ATTO_VER_TRACE1) { in hba_ioctl_callback()
927 if (trc->trace_func == ATTO_TRC_TF_UPLOAD) { in hba_ioctl_callback()
928 u32 len = hi->data_length; in hba_ioctl_callback()
929 u32 offset = trc->current_offset; in hba_ioctl_callback()
932 /* Size is zero if a core dump isn't present */ in hba_ioctl_callback()
933 if (!test_bit(AF2_COREDUMP_SAVED, &a->flags2)) in hba_ioctl_callback()
942 hi->status = ATTO_STS_INV_PARAM; in hba_ioctl_callback()
946 memcpy(trc->contents, in hba_ioctl_callback()
947 a->fw_coredump_buff + offset, in hba_ioctl_callback()
949 hi->data_length = len; in hba_ioctl_callback()
950 } else if (trc->trace_func == ATTO_TRC_TF_RESET) { in hba_ioctl_callback()
951 memset(a->fw_coredump_buff, 0, in hba_ioctl_callback()
954 clear_bit(AF2_COREDUMP_SAVED, &a->flags2); in hba_ioctl_callback()
955 } else if (trc->trace_func != ATTO_TRC_TF_GET_INFO) { in hba_ioctl_callback()
956 hi->status = ATTO_STS_UNSUPPORTED; in hba_ioctl_callback()
961 trc->trace_mask = 0; in hba_ioctl_callback()
962 trc->current_offset = 0; in hba_ioctl_callback()
963 trc->total_length = ESAS2R_FWCOREDUMP_SZ; in hba_ioctl_callback()
966 if (!test_bit(AF2_COREDUMP_SAVED, &a->flags2)) in hba_ioctl_callback()
967 trc->total_length = 0; in hba_ioctl_callback()
969 hi->status = ATTO_STS_UNSUPPORTED; in hba_ioctl_callback()
977 struct atto_hba_scsi_pass_thru *spt = &hi->data.scsi_pass_thru; in hba_ioctl_callback()
980 memcpy(&lun, spt->lun, sizeof(struct scsi_lun)); in hba_ioctl_callback()
982 if (hi->flags & HBAF_TUNNEL) { in hba_ioctl_callback()
983 if (hba_ioctl_tunnel(a, hi, rq, sgc)) in hba_ioctl_callback()
989 if (hi->version > ATTO_VER_SCSI_PASS_THRU0) { in hba_ioctl_callback()
990 hi->status = ATTO_STS_INV_VERSION; in hba_ioctl_callback()
991 hi->version = ATTO_VER_SCSI_PASS_THRU0; in hba_ioctl_callback()
995 if (spt->target_id >= ESAS2R_MAX_TARGETS || !check_lun(lun)) { in hba_ioctl_callback()
996 hi->status = ATTO_STS_INV_PARAM; in hba_ioctl_callback()
1000 esas2r_sgc_init(sgc, a, rq, NULL); in hba_ioctl_callback()
1002 sgc->length = hi->data_length; in hba_ioctl_callback()
1003 sgc->cur_offset += offsetof(struct atto_ioctl, data.byte) in hba_ioctl_callback()
1007 rq->target_id = (u16)spt->target_id; in hba_ioctl_callback()
1008 rq->vrq->scsi.flags |= cpu_to_le32(spt->lun[1]); in hba_ioctl_callback()
1009 memcpy(rq->vrq->scsi.cdb, spt->cdb, 16); in hba_ioctl_callback()
1010 rq->vrq->scsi.length = cpu_to_le32(hi->data_length); in hba_ioctl_callback()
1011 rq->sense_len = spt->sense_length; in hba_ioctl_callback()
1012 rq->sense_buf = (u8 *)spt->sense_data; in hba_ioctl_callback()
1013 /* NOTE: we ignore spt->timeout */ in hba_ioctl_callback()
1020 rq->aux_req_cx = hi; in hba_ioctl_callback()
1021 rq->aux_req_cb = rq->comp_cb; in hba_ioctl_callback()
1022 rq->comp_cb = scsi_passthru_comp_cb; in hba_ioctl_callback()
1024 if (spt->flags & ATTO_SPTF_DATA_IN) { in hba_ioctl_callback()
1025 rq->vrq->scsi.flags |= cpu_to_le32(FCP_CMND_RDD); in hba_ioctl_callback()
1026 } else if (spt->flags & ATTO_SPTF_DATA_OUT) { in hba_ioctl_callback()
1027 rq->vrq->scsi.flags |= cpu_to_le32(FCP_CMND_WRD); in hba_ioctl_callback()
1029 if (sgc->length) { in hba_ioctl_callback()
1030 hi->status = ATTO_STS_INV_PARAM; in hba_ioctl_callback()
1035 if (spt->flags & ATTO_SPTF_ORDERED_Q) in hba_ioctl_callback()
1036 rq->vrq->scsi.flags |= in hba_ioctl_callback()
1038 else if (spt->flags & ATTO_SPTF_HEAD_OF_Q) in hba_ioctl_callback()
1039 rq->vrq->scsi.flags |= cpu_to_le32(FCP_CMND_TA_HEAD_Q); in hba_ioctl_callback()
1042 if (!esas2r_build_sg_list(a, rq, sgc)) { in hba_ioctl_callback()
1043 hi->status = ATTO_STS_OUT_OF_RSRC; in hba_ioctl_callback()
1047 esas2r_start_request(a, rq); in hba_ioctl_callback()
1055 &hi->data.get_dev_addr; in hba_ioctl_callback()
1058 if (hi->flags & HBAF_TUNNEL) { in hba_ioctl_callback()
1059 if (hba_ioctl_tunnel(a, hi, rq, sgc)) in hba_ioctl_callback()
1065 if (hi->version > ATTO_VER_GET_DEV_ADDR0) { in hba_ioctl_callback()
1066 hi->status = ATTO_STS_INV_VERSION; in hba_ioctl_callback()
1067 hi->version = ATTO_VER_GET_DEV_ADDR0; in hba_ioctl_callback()
1071 if (gda->target_id >= ESAS2R_MAX_TARGETS) { in hba_ioctl_callback()
1072 hi->status = ATTO_STS_INV_PARAM; in hba_ioctl_callback()
1076 t = a->targetdb + (u16)gda->target_id; in hba_ioctl_callback()
1078 if (t->target_state != TS_PRESENT) { in hba_ioctl_callback()
1079 hi->status = ATTO_STS_FAILED; in hba_ioctl_callback()
1080 } else if (gda->addr_type == ATTO_GDA_AT_PORT) { in hba_ioctl_callback()
1081 if (t->sas_addr == 0) { in hba_ioctl_callback()
1082 hi->status = ATTO_STS_UNSUPPORTED; in hba_ioctl_callback()
1084 *(u64 *)gda->address = t->sas_addr; in hba_ioctl_callback()
1086 gda->addr_len = sizeof(u64); in hba_ioctl_callback()
1088 } else if (gda->addr_type == ATTO_GDA_AT_NODE) { in hba_ioctl_callback()
1089 hi->status = ATTO_STS_NOT_APPL; in hba_ioctl_callback()
1091 hi->status = ATTO_STS_INV_PARAM; in hba_ioctl_callback()
1096 gda->target_id = in hba_ioctl_callback()
1097 esas2r_targ_db_find_next_present(a, in hba_ioctl_callback()
1098 (u16)gda->target_id); in hba_ioctl_callback()
1105 if (hba_ioctl_tunnel(a, hi, rq, sgc)) in hba_ioctl_callback()
1113 struct atto_hba_adap_ctrl *ac = &hi->data.adap_ctrl; in hba_ioctl_callback()
1115 if (hi->flags & HBAF_TUNNEL) { in hba_ioctl_callback()
1116 hi->status = ATTO_STS_UNSUPPORTED; in hba_ioctl_callback()
1120 if (hi->version > ATTO_VER_ADAP_CTRL0) { in hba_ioctl_callback()
1121 hi->status = ATTO_STS_INV_VERSION; in hba_ioctl_callback()
1122 hi->version = ATTO_VER_ADAP_CTRL0; in hba_ioctl_callback()
1126 if (ac->adap_func == ATTO_AC_AF_HARD_RST) { in hba_ioctl_callback()
1127 esas2r_reset_adapter(a); in hba_ioctl_callback()
1128 } else if (ac->adap_func != ATTO_AC_AF_GET_STATE) { in hba_ioctl_callback()
1129 hi->status = ATTO_STS_UNSUPPORTED; in hba_ioctl_callback()
1133 if (test_bit(AF_CHPRST_NEEDED, &a->flags)) in hba_ioctl_callback()
1134 ac->adap_state = ATTO_AC_AS_RST_SCHED; in hba_ioctl_callback()
1135 else if (test_bit(AF_CHPRST_PENDING, &a->flags)) in hba_ioctl_callback()
1136 ac->adap_state = ATTO_AC_AS_RST_IN_PROG; in hba_ioctl_callback()
1137 else if (test_bit(AF_DISC_PENDING, &a->flags)) in hba_ioctl_callback()
1138 ac->adap_state = ATTO_AC_AS_RST_DISC; in hba_ioctl_callback()
1139 else if (test_bit(AF_DISABLED, &a->flags)) in hba_ioctl_callback()
1140 ac->adap_state = ATTO_AC_AS_DISABLED; in hba_ioctl_callback()
1141 else if (test_bit(AF_DEGRADED_MODE, &a->flags)) in hba_ioctl_callback()
1142 ac->adap_state = ATTO_AC_AS_DEGRADED; in hba_ioctl_callback()
1144 ac->adap_state = ATTO_AC_AS_OK; in hba_ioctl_callback()
1151 struct atto_hba_get_device_info *gdi = &hi->data.get_dev_info; in hba_ioctl_callback()
1154 if (hi->flags & HBAF_TUNNEL) { in hba_ioctl_callback()
1155 if (hba_ioctl_tunnel(a, hi, rq, sgc)) in hba_ioctl_callback()
1161 if (hi->version > ATTO_VER_GET_DEV_INFO0) { in hba_ioctl_callback()
1162 hi->status = ATTO_STS_INV_VERSION; in hba_ioctl_callback()
1163 hi->version = ATTO_VER_GET_DEV_INFO0; in hba_ioctl_callback()
1167 if (gdi->target_id >= ESAS2R_MAX_TARGETS) { in hba_ioctl_callback()
1168 hi->status = ATTO_STS_INV_PARAM; in hba_ioctl_callback()
1172 t = a->targetdb + (u16)gdi->target_id; in hba_ioctl_callback()
1176 gdi->target_id = in hba_ioctl_callback()
1177 esas2r_targ_db_find_next_present(a, in hba_ioctl_callback()
1178 (u16)gdi->target_id); in hba_ioctl_callback()
1180 if (t->target_state != TS_PRESENT) { in hba_ioctl_callback()
1181 hi->status = ATTO_STS_FAILED; in hba_ioctl_callback()
1185 hi->status = ATTO_STS_UNSUPPORTED; in hba_ioctl_callback()
1191 hi->status = ATTO_STS_INV_FUNC; in hba_ioctl_callback()
1198 static void hba_ioctl_done_callback(struct esas2r_adapter *a, in hba_ioctl_done_callback() argument
1204 esas2r_debug("hba_ioctl_done_callback %d", a->index); in hba_ioctl_done_callback()
1206 if (ioctl_hba->function == ATTO_FUNC_GET_ADAP_INFO) { in hba_ioctl_done_callback()
1208 &ioctl_hba->data.get_adap_info; in hba_ioctl_done_callback()
1212 gai->drvr_rev_major = ESAS2R_MAJOR_REV; in hba_ioctl_done_callback()
1213 gai->drvr_rev_minor = ESAS2R_MINOR_REV; in hba_ioctl_done_callback()
1215 strcpy(gai->drvr_rev_ascii, ESAS2R_VERSION_STR); in hba_ioctl_done_callback()
1216 strcpy(gai->drvr_name, ESAS2R_DRVR_NAME); in hba_ioctl_done_callback()
1218 gai->num_busses = 1; in hba_ioctl_done_callback()
1219 gai->num_targsper_bus = ESAS2R_MAX_ID + 1; in hba_ioctl_done_callback()
1220 gai->num_lunsper_targ = 1; in hba_ioctl_done_callback()
1224 u8 handle_hba_ioctl(struct esas2r_adapter *a, in handle_hba_ioctl() argument
1231 bi.a = a; in handle_hba_ioctl()
1233 bi.length = sizeof(struct atto_ioctl) + ioctl_hba->data_length; in handle_hba_ioctl()
1244 int esas2r_write_params(struct esas2r_adapter *a, struct esas2r_request *rq, in esas2r_write_params() argument
1249 a->nvram_command_done = 0; in esas2r_write_params()
1250 rq->comp_cb = complete_nvr_req; in esas2r_write_params()
1252 if (esas2r_nvram_write(a, rq, data)) { in esas2r_write_params()
1254 while (!a->nvram_command_done) in esas2r_write_params()
1255 wait_event_interruptible(a->nvram_waiter, in esas2r_write_params()
1256 a->nvram_command_done); in esas2r_write_params()
1260 if (rq->req_stat == RS_SUCCESS) in esas2r_write_params()
1267 /* This function only cares about ATTO-specific ioctls (atto_express_ioctl) */
1271 struct esas2r_adapter *a; in esas2r_ioctl_handler() local
1281 return -ENOTSUPP; in esas2r_ioctl_handler()
1293 if (memcmp(ioctl->header.signature, in esas2r_ioctl_handler()
1299 return -ENOTSUPP; in esas2r_ioctl_handler()
1304 ioctl->header.return_code = IOCTL_SUCCESS; in esas2r_ioctl_handler()
1315 ioctl->data.chanlist.num_channels = 0; in esas2r_ioctl_handler()
1319 ioctl->data.chanlist.num_channels++; in esas2r_ioctl_handler()
1320 ioctl->data.chanlist.channel[k] = i; in esas2r_ioctl_handler()
1331 if (ioctl->header.channel == 0xFF) { in esas2r_ioctl_handler()
1332 a = (struct esas2r_adapter *)hostdata; in esas2r_ioctl_handler()
1334 if (ioctl->header.channel >= MAX_ADAPTERS || in esas2r_ioctl_handler()
1335 esas2r_adapters[ioctl->header.channel] == NULL) { in esas2r_ioctl_handler()
1336 ioctl->header.return_code = IOCTL_BAD_CHANNEL; in esas2r_ioctl_handler()
1340 return -ENOTSUPP; in esas2r_ioctl_handler()
1342 a = esas2r_adapters[ioctl->header.channel]; in esas2r_ioctl_handler()
1348 if (ioctl->data.fwrw.img_type == FW_IMG_FM_API) { in esas2r_ioctl_handler()
1349 err = esas2r_write_fw(a, in esas2r_ioctl_handler()
1350 (char *)ioctl->data.fwrw.image, in esas2r_ioctl_handler()
1356 err = esas2r_read_fw(a, in esas2r_ioctl_handler()
1357 (char *)ioctl->data.fwrw. in esas2r_ioctl_handler()
1363 } else if (ioctl->data.fwrw.img_type == FW_IMG_FS_API) { in esas2r_ioctl_handler()
1364 err = esas2r_write_fs(a, in esas2r_ioctl_handler()
1365 (char *)ioctl->data.fwrw.image, in esas2r_ioctl_handler()
1371 err = esas2r_read_fs(a, in esas2r_ioctl_handler()
1372 (char *)ioctl->data.fwrw. in esas2r_ioctl_handler()
1379 ioctl->header.return_code = IOCTL_BAD_FLASH_IMGTYPE; in esas2r_ioctl_handler()
1386 memcpy(ioctl->data.prw.data_buffer, a->nvram, in esas2r_ioctl_handler()
1388 ioctl->data.prw.code = 1; in esas2r_ioctl_handler()
1393 rq = esas2r_alloc_request(a); in esas2r_ioctl_handler()
1398 return -ENOMEM; in esas2r_ioctl_handler()
1401 code = esas2r_write_params(a, rq, in esas2r_ioctl_handler()
1402 (struct esas2r_sas_nvram *)ioctl->data.prw.data_buffer); in esas2r_ioctl_handler()
1403 ioctl->data.prw.code = code; in esas2r_ioctl_handler()
1405 esas2r_free_request(a, rq); in esas2r_ioctl_handler()
1411 esas2r_nvram_get_defaults(a, in esas2r_ioctl_handler()
1412 (struct esas2r_sas_nvram *)ioctl->data.prw.data_buffer); in esas2r_ioctl_handler()
1413 ioctl->data.prw.code = 1; in esas2r_ioctl_handler()
1418 ioctl->data.chaninfo.major_rev = ESAS2R_MAJOR_REV; in esas2r_ioctl_handler()
1419 ioctl->data.chaninfo.minor_rev = ESAS2R_MINOR_REV; in esas2r_ioctl_handler()
1420 ioctl->data.chaninfo.IRQ = a->pcid->irq; in esas2r_ioctl_handler()
1421 ioctl->data.chaninfo.device_id = a->pcid->device; in esas2r_ioctl_handler()
1422 ioctl->data.chaninfo.vendor_id = a->pcid->vendor; in esas2r_ioctl_handler()
1423 ioctl->data.chaninfo.ven_dev_id = a->pcid->subsystem_device; in esas2r_ioctl_handler()
1424 ioctl->data.chaninfo.revision_id = a->pcid->revision; in esas2r_ioctl_handler()
1425 ioctl->data.chaninfo.pci_bus = a->pcid->bus->number; in esas2r_ioctl_handler()
1426 ioctl->data.chaninfo.pci_dev_func = a->pcid->devfn; in esas2r_ioctl_handler()
1427 ioctl->data.chaninfo.core_rev = 0; in esas2r_ioctl_handler()
1428 ioctl->data.chaninfo.host_no = a->host->host_no; in esas2r_ioctl_handler()
1429 ioctl->data.chaninfo.hbaapi_rev = 0; in esas2r_ioctl_handler()
1433 ioctl->header.return_code = handle_smp_ioctl(a, in esas2r_ioctl_handler()
1434 &ioctl->data. in esas2r_ioctl_handler()
1439 ioctl->header.return_code = in esas2r_ioctl_handler()
1440 handle_csmi_ioctl(a, &ioctl->data.csmi); in esas2r_ioctl_handler()
1444 ioctl->header.return_code = handle_hba_ioctl(a, in esas2r_ioctl_handler()
1445 &ioctl->data. in esas2r_ioctl_handler()
1450 err = esas2r_write_vda(a, in esas2r_ioctl_handler()
1451 (char *)&ioctl->data.ioctl_vda, in esas2r_ioctl_handler()
1454 ioctl->data.ioctl_vda.data_length); in esas2r_ioctl_handler()
1457 err = esas2r_read_vda(a, in esas2r_ioctl_handler()
1458 (char *)&ioctl->data.ioctl_vda, in esas2r_ioctl_handler()
1461 ioctl->data.ioctl_vda.data_length); in esas2r_ioctl_handler()
1471 ioctl->data.modinfo.adapter = a; in esas2r_ioctl_handler()
1472 ioctl->data.modinfo.pci_dev = a->pcid; in esas2r_ioctl_handler()
1473 ioctl->data.modinfo.scsi_host = a->host; in esas2r_ioctl_handler()
1474 ioctl->data.modinfo.host_no = a->host->host_no; in esas2r_ioctl_handler()
1480 ioctl->header.return_code = IOCTL_ERR_INVCMD; in esas2r_ioctl_handler()
1490 case -ENOMEM: in esas2r_ioctl_handler()
1491 case -EBUSY: in esas2r_ioctl_handler()
1492 ioctl->header.return_code = IOCTL_OUT_OF_RESOURCES; in esas2r_ioctl_handler()
1495 case -ENOSYS: in esas2r_ioctl_handler()
1496 case -EINVAL: in esas2r_ioctl_handler()
1497 ioctl->header.return_code = IOCTL_INVALID_PARAM; in esas2r_ioctl_handler()
1501 ioctl->header.return_code = IOCTL_GENERAL_ERROR; in esas2r_ioctl_handler()
1515 return -EFAULT; in esas2r_ioctl_handler()
1525 return esas2r_ioctl_handler(sd->host->hostdata, cmd, arg); in esas2r_ioctl()
1528 static void free_fw_buffers(struct esas2r_adapter *a) in free_fw_buffers() argument
1530 if (a->firmware.data) { in free_fw_buffers()
1531 dma_free_coherent(&a->pcid->dev, in free_fw_buffers()
1532 (size_t)a->firmware.orig_len, in free_fw_buffers()
1533 a->firmware.data, in free_fw_buffers()
1534 (dma_addr_t)a->firmware.phys); in free_fw_buffers()
1536 a->firmware.data = NULL; in free_fw_buffers()
1540 static int allocate_fw_buffers(struct esas2r_adapter *a, u32 length) in allocate_fw_buffers() argument
1542 free_fw_buffers(a); in allocate_fw_buffers()
1544 a->firmware.orig_len = length; in allocate_fw_buffers()
1546 a->firmware.data = dma_alloc_coherent(&a->pcid->dev, in allocate_fw_buffers()
1548 (dma_addr_t *)&a->firmware.phys, in allocate_fw_buffers()
1551 if (!a->firmware.data) { in allocate_fw_buffers()
1559 /* Handle a call to read firmware. */
1560 int esas2r_read_fw(struct esas2r_adapter *a, char *buf, long off, int count) in esas2r_read_fw() argument
1563 /* if the cached header is a status, simply copy it over and return. */ in esas2r_read_fw()
1564 if (a->firmware.state == FW_STATUS_ST) { in esas2r_read_fw()
1565 int size = min_t(int, count, sizeof(a->firmware.header)); in esas2r_read_fw()
1567 memcpy(buf, &a->firmware.header, size); in esas2r_read_fw()
1573 * if the cached header is a command, do it if at in esas2r_read_fw()
1577 if (a->firmware.state == FW_COMMAND_ST) { in esas2r_read_fw()
1578 u32 length = a->firmware.header.length; in esas2r_read_fw()
1586 if (a->firmware.header.action == FI_ACT_UP) { in esas2r_read_fw()
1587 if (!allocate_fw_buffers(a, length)) in esas2r_read_fw()
1588 return -ENOMEM; in esas2r_read_fw()
1593 memcpy(a->firmware.data, in esas2r_read_fw()
1594 &a->firmware.header, in esas2r_read_fw()
1595 sizeof(a->firmware.header)); in esas2r_read_fw()
1597 do_fm_api(a, in esas2r_read_fw()
1598 (struct esas2r_flash_img *)a->firmware.data); in esas2r_read_fw()
1599 } else if (a->firmware.header.action == FI_ACT_UPSZ) { in esas2r_read_fw()
1602 (int)sizeof(a->firmware.header)); in esas2r_read_fw()
1603 do_fm_api(a, &a->firmware.header); in esas2r_read_fw()
1604 memcpy(buf, &a->firmware.header, size); in esas2r_read_fw()
1609 a->firmware.header.action); in esas2r_read_fw()
1610 return -ENOSYS; in esas2r_read_fw()
1615 count = length - off; in esas2r_read_fw()
1620 if (!a->firmware.data) { in esas2r_read_fw()
1623 return -ENOMEM; in esas2r_read_fw()
1630 memcpy(buf, &a->firmware.data[off], count); in esas2r_read_fw()
1637 free_fw_buffers(a); in esas2r_read_fw()
1645 a->firmware.state); in esas2r_read_fw()
1647 return -EINVAL; in esas2r_read_fw()
1650 /* Handle a call to write firmware. */
1651 int esas2r_write_fw(struct esas2r_adapter *a, const char *buf, long off, in esas2r_write_fw() argument
1664 a->firmware.state = FW_INVALID_ST; in esas2r_write_fw()
1669 || header->fi_version > FI_VERSION_1) { in esas2r_write_fw()
1672 return -EINVAL; in esas2r_write_fw()
1675 /* See if its a version 1 flash image */ in esas2r_write_fw()
1677 if (header->fi_version == FI_VERSION_1) in esas2r_write_fw()
1683 return -EINVAL; in esas2r_write_fw()
1687 length = header->length; in esas2r_write_fw()
1692 length, header->fi_version); in esas2r_write_fw()
1693 return -EINVAL; in esas2r_write_fw()
1697 * If this is a write command, allocate memory because in esas2r_write_fw()
1702 if (header->action == FI_ACT_DOWN) { in esas2r_write_fw()
1703 if (!allocate_fw_buffers(a, length)) in esas2r_write_fw()
1704 return -ENOMEM; in esas2r_write_fw()
1710 memcpy(&a->firmware.header, in esas2r_write_fw()
1713 } else if (header->action == FI_ACT_UP in esas2r_write_fw()
1714 || header->action == FI_ACT_UPSZ) { in esas2r_write_fw()
1716 memcpy(&a->firmware.header, in esas2r_write_fw()
1720 a->firmware.state = FW_COMMAND_ST; in esas2r_write_fw()
1724 count, header->action); in esas2r_write_fw()
1734 a->firmware.header.action); in esas2r_write_fw()
1735 return -ENOSYS; in esas2r_write_fw()
1738 length = a->firmware.header.length; in esas2r_write_fw()
1742 * We only get here on a download command, regardless of offset. in esas2r_write_fw()
1748 count = length - off; in esas2r_write_fw()
1756 * On a full upload, the system tries sending the whole buffer. in esas2r_write_fw()
1760 if (a->firmware.header.action == FI_ACT_UP) in esas2r_write_fw()
1763 if (!a->firmware.data) { in esas2r_write_fw()
1766 return -ENOMEM; in esas2r_write_fw()
1769 memcpy(&a->firmware.data[off], buf, count); in esas2r_write_fw()
1772 do_fm_api(a, in esas2r_write_fw()
1773 (struct esas2r_flash_img *)a->firmware.data); in esas2r_write_fw()
1779 memcpy(&a->firmware.header, in esas2r_write_fw()
1780 a->firmware.data, in esas2r_write_fw()
1781 sizeof(a->firmware.header)); in esas2r_write_fw()
1783 a->firmware.state = FW_STATUS_ST; in esas2r_write_fw()
1789 * this can leak is if a root user writes a program in esas2r_write_fw()
1790 * that writes a shorter buffer than it claims, and the in esas2r_write_fw()
1793 free_fw_buffers(a); in esas2r_write_fw()
1800 /* Callback for the completion of a VDA request. */
1801 static void vda_complete_req(struct esas2r_adapter *a, in vda_complete_req() argument
1804 a->vda_command_done = 1; in vda_complete_req()
1805 wake_up_interruptible(&a->vda_waiter); in vda_complete_req()
1811 struct esas2r_adapter *a = (struct esas2r_adapter *)sgc->adapter; in get_physaddr_vda() local
1812 int offset = (u8 *)sgc->cur_offset - (u8 *)a->vda_buffer; in get_physaddr_vda()
1814 (*addr) = a->ppvda_buffer + offset; in get_physaddr_vda()
1815 return VDA_MAX_BUFFER_SIZE - offset; in get_physaddr_vda()
1818 /* Handle a call to read a VDA command. */
1819 int esas2r_read_vda(struct esas2r_adapter *a, char *buf, long off, int count) in esas2r_read_vda() argument
1821 if (!a->vda_buffer) in esas2r_read_vda()
1822 return -ENOMEM; in esas2r_read_vda()
1827 (struct atto_ioctl_vda *)a->vda_buffer; in esas2r_read_vda()
1837 /* allocate a request */ in esas2r_read_vda()
1838 rq = esas2r_alloc_request(a); in esas2r_read_vda()
1841 return -EBUSY; in esas2r_read_vda()
1844 rq->comp_cb = vda_complete_req; in esas2r_read_vda()
1847 sgc.adapter = a; in esas2r_read_vda()
1848 sgc.cur_offset = a->vda_buffer + VDA_BUFFER_HEADER_SZ; in esas2r_read_vda()
1851 a->vda_command_done = 0; in esas2r_read_vda()
1854 esas2r_process_vda_ioctl(a, vi, rq, &sgc); in esas2r_read_vda()
1859 while (!a->vda_command_done) in esas2r_read_vda()
1860 wait_event_interruptible(a->vda_waiter, in esas2r_read_vda()
1861 a->vda_command_done); in esas2r_read_vda()
1864 esas2r_free_request(a, (struct esas2r_request *)rq); in esas2r_read_vda()
1871 count = VDA_MAX_BUFFER_SIZE - off; in esas2r_read_vda()
1876 memcpy(buf, a->vda_buffer + off, count); in esas2r_read_vda()
1881 /* Handle a call to write a VDA command. */
1882 int esas2r_write_vda(struct esas2r_adapter *a, const char *buf, long off, in esas2r_write_vda() argument
1890 if (!a->vda_buffer) { in esas2r_write_vda()
1892 a->vda_buffer = dma_alloc_coherent(&a->pcid->dev, in esas2r_write_vda()
1898 a->ppvda_buffer = dma_addr; in esas2r_write_vda()
1901 if (!a->vda_buffer) in esas2r_write_vda()
1902 return -ENOMEM; in esas2r_write_vda()
1908 count = VDA_MAX_BUFFER_SIZE - off; in esas2r_write_vda()
1913 memcpy(a->vda_buffer + off, buf, count); in esas2r_write_vda()
1919 static void fs_api_complete_req(struct esas2r_adapter *a, in fs_api_complete_req() argument
1922 a->fs_api_command_done = 1; in fs_api_complete_req()
1924 wake_up_interruptible(&a->fs_api_waiter); in fs_api_complete_req()
1930 struct esas2r_adapter *a = (struct esas2r_adapter *)sgc->adapter; in get_physaddr_fs_api() local
1932 (struct esas2r_ioctl_fs *)a->fs_api_buffer; in get_physaddr_fs_api()
1933 u32 offset = (u8 *)sgc->cur_offset - (u8 *)fs; in get_physaddr_fs_api()
1935 (*addr) = a->ppfs_api_buffer + offset; in get_physaddr_fs_api()
1937 return a->fs_api_buffer_size - offset; in get_physaddr_fs_api()
1940 /* Handle a call to read firmware via FS_API. */
1941 int esas2r_read_fs(struct esas2r_adapter *a, char *buf, long off, int count) in esas2r_read_fs() argument
1943 if (!a->fs_api_buffer) in esas2r_read_fs()
1944 return -ENOMEM; in esas2r_read_fs()
1950 (struct esas2r_ioctl_fs *)a->fs_api_buffer; in esas2r_read_fs()
1953 if (mutex_lock_interruptible(&a->fs_api_mutex)) { in esas2r_read_fs()
1955 fs->status = ATTO_STS_OUT_OF_RSRC; in esas2r_read_fs()
1956 return -EBUSY; in esas2r_read_fs()
1963 * chip and reply. Allocate a request in esas2r_read_fs()
1966 rq = esas2r_alloc_request(a); in esas2r_read_fs()
1969 mutex_unlock(&a->fs_api_mutex); in esas2r_read_fs()
1973 rq->comp_cb = fs_api_complete_req; in esas2r_read_fs()
1977 sgc.cur_offset = fs->data; in esas2r_read_fs()
1980 a->fs_api_command_done = 0; in esas2r_read_fs()
1982 if (!esas2r_process_fs_ioctl(a, fs, rq, &sgc)) { in esas2r_read_fs()
1983 if (fs->status == ATTO_STS_OUT_OF_RSRC) in esas2r_read_fs()
1984 count = -EBUSY; in esas2r_read_fs()
1991 while (!a->fs_api_command_done) in esas2r_read_fs()
1992 wait_event_interruptible(a->fs_api_waiter, in esas2r_read_fs()
1993 a->fs_api_command_done); in esas2r_read_fs()
1997 mutex_unlock(&a->fs_api_mutex); in esas2r_read_fs()
1998 esas2r_free_request(a, (struct esas2r_request *)rq); in esas2r_read_fs()
2005 if (off > a->fs_api_buffer_size) in esas2r_read_fs()
2008 if (count + off > a->fs_api_buffer_size) in esas2r_read_fs()
2009 count = a->fs_api_buffer_size - off; in esas2r_read_fs()
2014 memcpy(buf, a->fs_api_buffer + off, count); in esas2r_read_fs()
2019 /* Handle a call to write firmware via FS_API. */
2020 int esas2r_write_fs(struct esas2r_adapter *a, const char *buf, long off, in esas2r_write_fs() argument
2025 u32 length = fs->command.length + offsetof( in esas2r_write_fs()
2034 if (fs->command.command == ESAS2R_FS_CMD_BEGINW) in esas2r_write_fs()
2038 * Beginning a command. We assume we'll get at least in esas2r_write_fs()
2044 return -EINVAL; in esas2r_write_fs()
2046 /* Allocate a buffer or use the existing buffer. */ in esas2r_write_fs()
2047 if (a->fs_api_buffer) { in esas2r_write_fs()
2048 if (a->fs_api_buffer_size < length) { in esas2r_write_fs()
2049 /* Free too-small buffer and get a new one */ in esas2r_write_fs()
2050 dma_free_coherent(&a->pcid->dev, in esas2r_write_fs()
2051 (size_t)a->fs_api_buffer_size, in esas2r_write_fs()
2052 a->fs_api_buffer, in esas2r_write_fs()
2053 (dma_addr_t)a->ppfs_api_buffer); in esas2r_write_fs()
2059 a->fs_api_buffer_size = length; in esas2r_write_fs()
2061 a->fs_api_buffer = dma_alloc_coherent(&a->pcid->dev, in esas2r_write_fs()
2062 (size_t)a->fs_api_buffer_size, in esas2r_write_fs()
2063 (dma_addr_t *)&a->ppfs_api_buffer, in esas2r_write_fs()
2068 if (!a->fs_api_buffer) in esas2r_write_fs()
2069 return -ENOMEM; in esas2r_write_fs()
2071 if (off > a->fs_api_buffer_size) in esas2r_write_fs()
2074 if (count + off > a->fs_api_buffer_size) in esas2r_write_fs()
2075 count = a->fs_api_buffer_size - off; in esas2r_write_fs()
2080 memcpy(a->fs_api_buffer + off, buf, count); in esas2r_write_fs()