aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libata-core.c6
-rw-r--r--drivers/scsi/libata-eh.c31
-rw-r--r--include/linux/libata.h2
3 files changed, 23 insertions, 16 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 73174452d1c1..f368536f8e91 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -5447,6 +5447,7 @@ int ata_device_add(const struct ata_probe_ent *ent)
5447 } 5447 }
5448 5448
5449 if (ap->ops->error_handler) { 5449 if (ap->ops->error_handler) {
5450 struct ata_eh_info *ehi = &ap->eh_info;
5450 unsigned long flags; 5451 unsigned long flags;
5451 5452
5452 ata_port_probe(ap); 5453 ata_port_probe(ap);
@@ -5454,8 +5455,9 @@ int ata_device_add(const struct ata_probe_ent *ent)
5454 /* kick EH for boot probing */ 5455 /* kick EH for boot probing */
5455 spin_lock_irqsave(ap->lock, flags); 5456 spin_lock_irqsave(ap->lock, flags);
5456 5457
5457 ap->eh_info.probe_mask = (1 << ATA_MAX_DEVICES) - 1; 5458 ehi->probe_mask = (1 << ATA_MAX_DEVICES) - 1;
5458 ap->eh_info.action |= ATA_EH_SOFTRESET; 5459 ehi->action |= ATA_EH_SOFTRESET;
5460 ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
5459 5461
5460 ap->pflags |= ATA_PFLAG_LOADING; 5462 ap->pflags |= ATA_PFLAG_LOADING;
5461 ata_port_schedule_eh(ap); 5463 ata_port_schedule_eh(ap);
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index d19666c376ad..1e9e73d13485 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -322,14 +322,13 @@ void ata_scsi_error(struct Scsi_Host *host)
322 /* clean up */ 322 /* clean up */
323 spin_lock_irqsave(ap->lock, flags); 323 spin_lock_irqsave(ap->lock, flags);
324 324
325 if (ap->pflags & ATA_PFLAG_LOADING) { 325 if (ap->pflags & ATA_PFLAG_LOADING)
326 ap->pflags &= ~ATA_PFLAG_LOADING; 326 ap->pflags &= ~ATA_PFLAG_LOADING;
327 } else { 327 else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG)
328 if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG) 328 queue_work(ata_aux_wq, &ap->hotplug_task);
329 queue_work(ata_aux_wq, &ap->hotplug_task); 329
330 if (ap->pflags & ATA_PFLAG_RECOVERED) 330 if (ap->pflags & ATA_PFLAG_RECOVERED)
331 ata_port_printk(ap, KERN_INFO, "EH complete\n"); 331 ata_port_printk(ap, KERN_INFO, "EH complete\n");
332 }
333 332
334 ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED); 333 ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED);
335 334
@@ -759,8 +758,12 @@ static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev,
759 unsigned long flags; 758 unsigned long flags;
760 759
761 spin_lock_irqsave(ap->lock, flags); 760 spin_lock_irqsave(ap->lock, flags);
761
762 ata_eh_clear_action(dev, &ap->eh_info, action); 762 ata_eh_clear_action(dev, &ap->eh_info, action);
763 ap->pflags |= ATA_PFLAG_RECOVERED; 763
764 if (!(ap->eh_context.i.flags & ATA_EHI_QUIET))
765 ap->pflags |= ATA_PFLAG_RECOVERED;
766
764 spin_unlock_irqrestore(ap->lock, flags); 767 spin_unlock_irqrestore(ap->lock, flags);
765} 768}
766 769
@@ -1274,6 +1277,9 @@ static void ata_eh_autopsy(struct ata_port *ap)
1274 1277
1275 DPRINTK("ENTER\n"); 1278 DPRINTK("ENTER\n");
1276 1279
1280 if (ehc->i.flags & ATA_EHI_NO_AUTOPSY)
1281 return;
1282
1277 /* obtain and analyze SError */ 1283 /* obtain and analyze SError */
1278 rc = sata_scr_read(ap, SCR_ERROR, &serror); 1284 rc = sata_scr_read(ap, SCR_ERROR, &serror);
1279 if (rc == 0) { 1285 if (rc == 0) {
@@ -1464,7 +1470,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
1464 struct ata_eh_context *ehc = &ap->eh_context; 1470 struct ata_eh_context *ehc = &ap->eh_context;
1465 unsigned int *classes = ehc->classes; 1471 unsigned int *classes = ehc->classes;
1466 int tries = ATA_EH_RESET_TRIES; 1472 int tries = ATA_EH_RESET_TRIES;
1467 int verbose = !(ap->pflags & ATA_PFLAG_LOADING); 1473 int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
1468 unsigned int action; 1474 unsigned int action;
1469 ata_reset_fn_t reset; 1475 ata_reset_fn_t reset;
1470 int i, did_followup_srst, rc; 1476 int i, did_followup_srst, rc;
@@ -1907,11 +1913,8 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
1907 ata_reset_fn_t softreset, ata_reset_fn_t hardreset, 1913 ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
1908 ata_postreset_fn_t postreset) 1914 ata_postreset_fn_t postreset)
1909{ 1915{
1910 if (!(ap->pflags & ATA_PFLAG_LOADING)) { 1916 ata_eh_autopsy(ap);
1911 ata_eh_autopsy(ap); 1917 ata_eh_report(ap);
1912 ata_eh_report(ap);
1913 }
1914
1915 ata_eh_recover(ap, prereset, softreset, hardreset, postreset); 1918 ata_eh_recover(ap, prereset, softreset, hardreset, postreset);
1916 ata_eh_finish(ap); 1919 ata_eh_finish(ap);
1917} 1920}
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 2f7bbfc0c41b..36938ae1254d 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -260,6 +260,8 @@ enum {
260 /* ata_eh_info->flags */ 260 /* ata_eh_info->flags */
261 ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ 261 ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */
262 ATA_EHI_RESUME_LINK = (1 << 1), /* need to resume link */ 262 ATA_EHI_RESUME_LINK = (1 << 1), /* need to resume link */
263 ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */
264 ATA_EHI_QUIET = (1 << 3), /* be quiet */
263 265
264 ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */ 266 ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */
265 267
kwb">int btusb_submit_bulk_urb(struct hci_dev *hdev) { struct btusb_data *data = hdev->driver_data; struct urb *urb; unsigned char *buf; unsigned int pipe; int err, size; BT_DBG("%s", hdev->name); urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return -ENOMEM; size = le16_to_cpu(data->bulk_rx_ep->wMaxPacketSize); buf = kmalloc(size, GFP_KERNEL); if (!buf) { usb_free_urb(urb); return -ENOMEM; } pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress); usb_fill_bulk_urb(urb, data->udev, pipe, buf, size, btusb_bulk_complete, hdev); urb->transfer_flags |= URB_FREE_BUFFER; usb_anchor_urb(urb, &data->bulk_anchor); err = usb_submit_urb(urb, GFP_KERNEL); if (err < 0) { BT_ERR("%s urb %p submission failed (%d)", hdev->name, urb, -err); usb_unanchor_urb(urb); kfree(buf); } usb_free_urb(urb); return err; } static void btusb_tx_complete(struct urb *urb) { struct sk_buff *skb = urb->context; struct hci_dev *hdev = (struct hci_dev *) skb->dev; BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status, urb->actual_length); if (!test_bit(HCI_RUNNING, &hdev->flags)) goto done; if (!urb->status) hdev->stat.byte_tx += urb->transfer_buffer_length; else hdev->stat.err_tx++; done: kfree(urb->setup_packet); kfree_skb(skb); } static int btusb_open(struct hci_dev *hdev) { struct btusb_data *data = hdev->driver_data; int err; BT_DBG("%s", hdev->name); if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) return 0; if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags)) return 0; err = btusb_submit_intr_urb(hdev); if (err < 0) { clear_bit(BTUSB_INTR_RUNNING, &hdev->flags); clear_bit(HCI_RUNNING, &hdev->flags); } return err; } static int btusb_close(struct hci_dev *hdev) { struct btusb_data *data = hdev->driver_data; BT_DBG("%s", hdev->name); if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) return 0; clear_bit(BTUSB_BULK_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->bulk_anchor); clear_bit(BTUSB_INTR_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->intr_anchor); return 0; } static int btusb_flush(struct hci_dev *hdev) { struct btusb_data *data = hdev->driver_data; BT_DBG("%s", hdev->name); usb_kill_anchored_urbs(&data->tx_anchor); return 0; } static int btusb_send_frame(struct sk_buff *skb) { struct hci_dev *hdev = (struct hci_dev *) skb->dev; struct btusb_data *data = hdev->driver_data; struct usb_ctrlrequest *dr; struct urb *urb; unsigned int pipe; int err; BT_DBG("%s", hdev->name); if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; switch (bt_cb(skb)->pkt_type) { case HCI_COMMAND_PKT: urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; dr = kmalloc(sizeof(*dr), GFP_ATOMIC); if (!dr) { usb_free_urb(urb); return -ENOMEM; } dr->bRequestType = USB_TYPE_CLASS; dr->bRequest = 0; dr->wIndex = 0; dr->wValue = 0; dr->wLength = __cpu_to_le16(skb->len); pipe = usb_sndctrlpipe(data->udev, 0x00); usb_fill_control_urb(urb, data->udev, pipe, (void *) dr, skb->data, skb->len, btusb_tx_complete, skb); hdev->stat.cmd_tx++; break; case HCI_ACLDATA_PKT: urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress); usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len, btusb_tx_complete, skb); hdev->stat.acl_tx++; break; case HCI_SCODATA_PKT: hdev->stat.sco_tx++; kfree_skb(skb); return 0; default: return -EILSEQ; } usb_anchor_urb(urb, &data->tx_anchor); err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { BT_ERR("%s urb %p submission failed", hdev->name, urb); kfree(urb->setup_packet); usb_unanchor_urb(urb); } usb_free_urb(urb); return err; } static void btusb_destruct(struct hci_dev *hdev) { struct btusb_data *data = hdev->driver_data; BT_DBG("%s", hdev->name); kfree(data); } static void btusb_notify(struct hci_dev *hdev, unsigned int evt) { struct btusb_data *data = hdev->driver_data; BT_DBG("%s evt %d", hdev->name, evt); if (evt == HCI_NOTIFY_CONN_ADD || evt == HCI_NOTIFY_CONN_DEL) schedule_work(&data->work); } static void btusb_work(struct work_struct *work) { struct btusb_data *data = container_of(work, struct btusb_data, work); struct hci_dev *hdev = data->hdev; if (hdev->conn_hash.acl_num == 0) { clear_bit(BTUSB_BULK_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->bulk_anchor); return; } if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) { if (btusb_submit_bulk_urb(hdev) < 0) clear_bit(BTUSB_BULK_RUNNING, &data->flags); else btusb_submit_bulk_urb(hdev); } } static int btusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_endpoint_descriptor *ep_desc; struct btusb_data *data; struct hci_dev *hdev; int i, err; BT_DBG("intf %p id %p", intf, id); if (intf->cur_altsetting->desc.bInterfaceNumber != 0) return -ENODEV; if (!id->driver_info) { const struct usb_device_id *match; match = usb_match_id(intf, blacklist_table); if (match) id = match; } data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { ep_desc = &intf->cur_altsetting->endpoint[i].desc; if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) { data->intr_ep = ep_desc; continue; } if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) { data->bulk_tx_ep = ep_desc; continue; } if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) { data->bulk_rx_ep = ep_desc; continue; } } if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) { kfree(data); return -ENODEV; } data->udev = interface_to_usbdev(intf); spin_lock_init(&data->lock); INIT_WORK(&data->work, btusb_work); init_usb_anchor(&data->tx_anchor); init_usb_anchor(&data->intr_anchor); init_usb_anchor(&data->bulk_anchor); hdev = hci_alloc_dev(); if (!hdev) {